From 19d048dd6671ba1a42ff408edc78263b31ee6513 Mon Sep 17 00:00:00 2001 From: lyf <2514544224@qq.com> Date: Mon, 6 Jul 2026 11:59:54 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=89=8D=E7=AB=AF=E4=B8=89?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 14 --- .env.development | 27 ++++++ .env.example | 28 ++++-- .env.production | 19 ++++ .env.test | 19 ++++ .gitignore | 4 + package.json | 12 ++- src/config/dataSource.ts | 4 +- src/env.d.ts | 3 + src/manifest.json | 2 +- src/repositories/GuideModelRepository.ts | 3 +- src/services/tencent/TencentMapService.ts | 3 +- src/utils/publicUrl.ts | 11 ++- vite.config.ts | 106 ++++++++++++---------- 14 files changed, 173 insertions(+), 82 deletions(-) delete mode 100644 .env create mode 100644 .env.development create mode 100644 .env.production create mode 100644 .env.test diff --git a/.env b/.env deleted file mode 100644 index 2be80c6..0000000 --- a/.env +++ /dev/null @@ -1,14 +0,0 @@ -# 腾讯地图 API Key -# 请到 https://lbs.qq.com/index.html 申请 -VITE_DATA_SOURCE_MODE=sdk -VITE_GUIDE_CONTENT_SOURCE_MODE=static -VITE_API_BASE_URL=/app-api -VITE_SGS_SDK_TIMEOUT_MS=15000 -VITE_TENCENT_MAP_KEY=EJPBZ-DQEEQ-PDN5U-4ZDVX-F4I3F-6MBJC - -# SGS SDK 配置(SDK 模式下必需) -VITE_SGS_API_BASE_URL=/app-api -VITE_SGS_MAP_ID=1 -VITE_SGS_SDK_SCRIPT_URL=/static/sgs-map-sdk/index.global.js -VITE_SGS_H5_ENGINE_URL=/h5-sdk -VITE_SGS_SDK_ORIGIN=https://guide.whaoyue.com diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..f7c07b2 --- /dev/null +++ b/.env.development @@ -0,0 +1,27 @@ +# uni-app + Vite 开发环境默认配置。 +# 真实本地接口地址或 key 请放入 .env.development.local。 + +VITE_APP_PUBLIC_BASE=/ +VITE_DATA_SOURCE_MODE=sdk +VITE_GUIDE_CONTENT_SOURCE_MODE=static +VITE_GUIDE_STATIC_DATA_BASE_URL=/static/guide-data +VITE_API_BASE_URL=/app-api +VITE_AUDIO_API_BASE_URL=/nhm/audio +VITE_AUDIO_LANGUAGE=zh-CN +VITE_SGS_API_BASE_URL=/app-api +VITE_SGS_MAP_ID=1 +VITE_SGS_SDK_SCRIPT_URL=/static/sgs-map-sdk/index.global.js +VITE_SGS_H5_ENGINE_URL=/h5-sdk +VITE_SGS_SDK_ORIGIN= +VITE_SGS_SDK_TIMEOUT_MS=15000 +VITE_TENCENT_MAP_KEY=__REPLACE_WITH_TENCENT_MAP_WEB_KEY__ +VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST= +VITE_PUBLIC_LEGACY_AUDIO_HOST= + +# Vite 开发服务器代理目标,只由 vite.config.ts 读取。 +DEV_PROXY_APP_API_TARGET=http://localhost:3001 +DEV_PROXY_H5_SDK_TARGET=http://localhost:3001 +DEV_PROXY_SDK_TARGET=http://localhost:3001 +DEV_PROXY_MUSEUM_ASSETS_TARGET=http://localhost:9000 +DEV_PROXY_MINIO_TARGET=http://localhost:3001 +DEV_PROXY_AUDIO_TARGET=http://localhost:19000 diff --git a/.env.example b/.env.example index 22b8ed4..5fe63ac 100644 --- a/.env.example +++ b/.env.example @@ -1,15 +1,27 @@ -# 腾讯地图 API Key -# 请到 https://lbs.qq.com/index.html 申请 -VITE_TENCENT_MAP_KEY=your_tencent_map_key_here +# 复制到 .env.development.local、.env.test.local 或 .env.production.local 后填写真实部署值。 +# VITE_ 前缀变量会被打包进前端产物,不应存放后端密钥或私有令牌。 -# 数据源模式:sdk / mock +VITE_APP_PUBLIC_BASE=/ VITE_DATA_SOURCE_MODE=sdk +VITE_GUIDE_CONTENT_SOURCE_MODE=static +VITE_GUIDE_STATIC_DATA_BASE_URL=/static/guide-data VITE_API_BASE_URL=/app-api -VITE_SGS_SDK_TIMEOUT_MS=15000 - -# SGS SDK 配置(生产部署使用同源路径,避免 HTTPS 页面请求 HTTP 后端被浏览器拦截) +VITE_AUDIO_API_BASE_URL=/yudao-server +VITE_AUDIO_LANGUAGE=zh-CN VITE_SGS_API_BASE_URL=/app-api VITE_SGS_MAP_ID=1 VITE_SGS_SDK_SCRIPT_URL=/static/sgs-map-sdk/index.global.js VITE_SGS_H5_ENGINE_URL=/h5-sdk -VITE_SGS_SDK_ORIGIN=https://guide.whaoyue.com +VITE_SGS_SDK_ORIGIN= +VITE_SGS_SDK_TIMEOUT_MS=15000 +VITE_TENCENT_MAP_KEY=__REPLACE_WITH_TENCENT_MAP_WEB_KEY__ +VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST= +VITE_PUBLIC_LEGACY_AUDIO_HOST= + +# 仅开发环境使用的 Vite 代理目标,只由 vite.config.ts 读取。 +DEV_PROXY_APP_API_TARGET=http://localhost:3001 +DEV_PROXY_H5_SDK_TARGET=http://localhost:3001 +DEV_PROXY_SDK_TARGET=http://localhost:3001 +DEV_PROXY_MUSEUM_ASSETS_TARGET=http://localhost:9000 +DEV_PROXY_MINIO_TARGET=http://localhost:3001 +DEV_PROXY_AUDIO_TARGET=http://localhost:19000 diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..a979d22 --- /dev/null +++ b/.env.production @@ -0,0 +1,19 @@ +# uni-app + Vite 生产环境默认配置。 +# 真实生产值请通过部署平台环境变量或 .env.production.local 覆盖。 + +VITE_APP_PUBLIC_BASE=/ +VITE_DATA_SOURCE_MODE=sdk +VITE_GUIDE_CONTENT_SOURCE_MODE=static +VITE_GUIDE_STATIC_DATA_BASE_URL=/static/guide-data +VITE_API_BASE_URL=/app-api +VITE_AUDIO_API_BASE_URL=/yudao-server +VITE_AUDIO_LANGUAGE=zh-CN +VITE_SGS_API_BASE_URL=/app-api +VITE_SGS_MAP_ID=1 +VITE_SGS_SDK_SCRIPT_URL=/static/sgs-map-sdk/index.global.js +VITE_SGS_H5_ENGINE_URL=/h5-sdk +VITE_SGS_SDK_ORIGIN=https://guide.sznhmuseum.org.cn +VITE_SGS_SDK_TIMEOUT_MS=15000 +VITE_TENCENT_MAP_KEY=__REPLACE_WITH_TENCENT_MAP_WEB_KEY__ +VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST= +VITE_PUBLIC_LEGACY_AUDIO_HOST= diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..6cf4cc1 --- /dev/null +++ b/.env.test @@ -0,0 +1,19 @@ +# uni-app + Vite 测试环境默认配置。 +# 真实测试环境接口地址或 key 请通过部署平台环境变量或 .env.test.local 覆盖。 + +VITE_APP_PUBLIC_BASE=/ +VITE_DATA_SOURCE_MODE=sdk +VITE_GUIDE_CONTENT_SOURCE_MODE=static +VITE_GUIDE_STATIC_DATA_BASE_URL=/static/guide-data +VITE_API_BASE_URL=/app-api +VITE_AUDIO_API_BASE_URL=/yudao-server +VITE_AUDIO_LANGUAGE=zh-CN +VITE_SGS_API_BASE_URL=/app-api +VITE_SGS_MAP_ID=1 +VITE_SGS_SDK_SCRIPT_URL=/static/sgs-map-sdk/index.global.js +VITE_SGS_H5_ENGINE_URL=/h5-sdk +VITE_SGS_SDK_ORIGIN=https://guide.whaoyue.com +VITE_SGS_SDK_TIMEOUT_MS=15000 +VITE_TENCENT_MAP_KEY=__REPLACE_WITH_TENCENT_MAP_WEB_KEY__ +VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST= +VITE_PUBLIC_LEGACY_AUDIO_HOST= diff --git a/.gitignore b/.gitignore index 5042c29..93eb693 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,10 @@ coverage/ .env .env.local .env.*.local +!.env.example +!.env.development +!.env.test +!.env.production .claude/*.local.json .claude/worktrees/ .codex-artifacts/ diff --git a/package.json b/package.json index 27f0b07..0486550 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,14 @@ "node": ">=20 <25" }, "scripts": { - "dev:h5": "uni -p h5", - "build:h5": "uni build -p h5 && node scripts/copy-h5-nav-assets.cjs", - "dev:mp-weixin": "uni -p mp-weixin", - "build:mp-weixin": "uni build -p mp-weixin", + "dev:h5": "uni -p h5 --mode development", + "dev:test:h5": "uni -p h5 --mode test", + "build:test:h5": "uni build -p h5 --mode test && node scripts/copy-h5-nav-assets.cjs", + "build:h5": "uni build -p h5 --mode production && node scripts/copy-h5-nav-assets.cjs", + "dev:mp-weixin": "uni -p mp-weixin --mode development", + "dev:test:mp-weixin": "uni -p mp-weixin --mode test", + "build:test:mp-weixin": "uni build -p mp-weixin --mode test", + "build:mp-weixin": "uni build -p mp-weixin --mode production", "type-check": "vue-tsc --noEmit", "lint": "eslint \"src/**/*.{ts,vue}\"" }, diff --git a/src/config/dataSource.ts b/src/config/dataSource.ts index b2ab69e..8dbf892 100644 --- a/src/config/dataSource.ts +++ b/src/config/dataSource.ts @@ -68,7 +68,9 @@ export const dataSourceConfig = { sgsSdkScriptUrl: normalizeUrl(import.meta.env.VITE_SGS_SDK_SCRIPT_URL, defaultSdkScriptUrl), sgsMapEngineUrl: normalizeUrl(import.meta.env.VITE_SGS_H5_ENGINE_URL, defaultSgsEngineUrl), sgsSdkTargetOrigin: import.meta.env.VITE_SGS_SDK_ORIGIN?.trim() || '', - sgsSdkTimeoutMs: normalizeTimeout(import.meta.env.VITE_SGS_SDK_TIMEOUT_MS) + sgsSdkTimeoutMs: normalizeTimeout(import.meta.env.VITE_SGS_SDK_TIMEOUT_MS), + publicSameOriginAssetHost: import.meta.env.VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST?.trim() || '', + publicLegacyAudioHost: import.meta.env.VITE_PUBLIC_LEGACY_AUDIO_HOST?.trim() || '' } export const isSgsSdkMode = () => dataSourceConfig.mode === 'sdk' diff --git a/src/env.d.ts b/src/env.d.ts index a24da32..16a1eaf 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,6 +1,7 @@ /// interface ImportMetaEnv { + readonly VITE_APP_PUBLIC_BASE?: string readonly VITE_DATA_SOURCE_MODE?: 'static' | 'api' | 'sdk' readonly VITE_GUIDE_CONTENT_SOURCE_MODE?: 'static' | 'remote' | 'mock' readonly VITE_GUIDE_STATIC_DATA_BASE_URL?: string @@ -14,6 +15,8 @@ interface ImportMetaEnv { readonly VITE_SGS_SDK_ORIGIN?: string readonly VITE_SGS_SDK_TIMEOUT_MS?: string readonly VITE_TENCENT_MAP_KEY?: string + readonly VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST?: string + readonly VITE_PUBLIC_LEGACY_AUDIO_HOST?: string } interface ImportMeta { diff --git a/src/manifest.json b/src/manifest.json index a5fb986..fdefd5c 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -55,7 +55,7 @@ "sdkConfigs": { "maps": { "qqmap": { - "key": "EJPBZ-DQEEQ-PDN5U-4ZDVX-F4I3F-6MBJC" + "key": "__REPLACE_WITH_TENCENT_MAP_WEB_KEY__" } } } diff --git a/src/repositories/GuideModelRepository.ts b/src/repositories/GuideModelRepository.ts index 249e4d7..d0166b4 100644 --- a/src/repositories/GuideModelRepository.ts +++ b/src/repositories/GuideModelRepository.ts @@ -113,7 +113,8 @@ const resolveSgsAssetUrl = (url?: string | null) => { try { const assetUrl = new URL(normalizedUrl) if ( - assetUrl.hostname === '1.92.206.90' + dataSourceConfig.publicSameOriginAssetHost + && assetUrl.hostname === dataSourceConfig.publicSameOriginAssetHost && assetUrl.port === '9000' && assetUrl.pathname.startsWith('/museum-assets/') ) { diff --git a/src/services/tencent/TencentMapService.ts b/src/services/tencent/TencentMapService.ts index a38dcdd..f41858e 100644 --- a/src/services/tencent/TencentMapService.ts +++ b/src/services/tencent/TencentMapService.ts @@ -3,8 +3,7 @@ * 用于 POI 搜索、地址解析、路线规划等 */ -// 优先从环境变量读取 API Key,回退到硬编码值(仅用于开发环境) -const TENCENT_MAP_KEY = import.meta.env.VITE_TENCENT_MAP_KEY || 'EJPBZ-DQEEQ-PDN5U-4ZDVX-F4I3F-6MBJC' +const TENCENT_MAP_KEY = import.meta.env.VITE_TENCENT_MAP_KEY?.trim() || '' const TENCENT_MAP_BASE_URL = 'https://apis.map.qq.com/ws' const TENCENT_DIRECTION_BASE_URL = `${TENCENT_MAP_BASE_URL}/direction/v1` diff --git a/src/utils/publicUrl.ts b/src/utils/publicUrl.ts index 80df70c..c55e295 100644 --- a/src/utils/publicUrl.ts +++ b/src/utils/publicUrl.ts @@ -1,5 +1,6 @@ -const SAME_SERVER_HOST = '1.92.206.90' -const LEGACY_AUDIO_HOST = '47.120.48.148' +import { + dataSourceConfig +} from '@/config/dataSource' const isAbsoluteHttpUrl = (url: string) => /^https?:\/\//i.test(url) @@ -9,7 +10,8 @@ export const normalizeSameOriginPublicUrl = (url: string | null | undefined) => try { const parsed = new URL(value) - const isSameServer = parsed.hostname === SAME_SERVER_HOST + const isSameServer = Boolean(dataSourceConfig.publicSameOriginAssetHost) + && parsed.hostname === dataSourceConfig.publicSameOriginAssetHost if ( isSameServer @@ -31,7 +33,8 @@ export const normalizeSameOriginPublicUrl = (url: string | null | undefined) => } if ( - parsed.hostname === LEGACY_AUDIO_HOST + dataSourceConfig.publicLegacyAudioHost + && parsed.hostname === dataSourceConfig.publicLegacyAudioHost && parsed.port === '19000' && parsed.pathname.startsWith('/nhm/audio/') ) { diff --git a/vite.config.ts b/vite.config.ts index f37f11e..fcfdb45 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,54 +1,66 @@ -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' import uni from '@dcloudio/vite-plugin-uni' -const sgsDevServer = 'http://1.92.206.90:3001' -const sgsAssetServer = 'http://1.92.206.90:9000' -const legacyAudioServer = 'http://47.120.48.148:19000' +const normalizeEnvUrl = (value: string | undefined, fallback: string) => { + const normalized = value?.trim() + return normalized || fallback +} -export default defineConfig({ - plugins: [uni()], - server: { - host: '0.0.0.0', - proxy: { - '/app-api': { - target: sgsDevServer, - changeOrigin: true - }, - '/h5-sdk': { - target: sgsDevServer, - changeOrigin: true - }, - '/sdk': { - target: sgsDevServer, - changeOrigin: true - }, - '/museum-assets': { - target: sgsAssetServer, - changeOrigin: true - }, - '/minio': { - target: sgsDevServer, - changeOrigin: true - }, - '/nhm/audio': { - target: legacyAudioServer, - changeOrigin: true +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), '') + const appApiProxyTarget = normalizeEnvUrl(env.DEV_PROXY_APP_API_TARGET, 'http://localhost:3001') + const h5SdkProxyTarget = normalizeEnvUrl(env.DEV_PROXY_H5_SDK_TARGET, appApiProxyTarget) + const sdkProxyTarget = normalizeEnvUrl(env.DEV_PROXY_SDK_TARGET, appApiProxyTarget) + const museumAssetsProxyTarget = normalizeEnvUrl(env.DEV_PROXY_MUSEUM_ASSETS_TARGET, 'http://localhost:9000') + const minioProxyTarget = normalizeEnvUrl(env.DEV_PROXY_MINIO_TARGET, appApiProxyTarget) + const audioProxyTarget = normalizeEnvUrl(env.DEV_PROXY_AUDIO_TARGET, 'http://localhost:19000') + + return { + base: normalizeEnvUrl(env.VITE_APP_PUBLIC_BASE, '/'), + plugins: [uni()], + server: { + host: '0.0.0.0', + proxy: { + '/app-api': { + target: appApiProxyTarget, + changeOrigin: true + }, + '/h5-sdk': { + target: h5SdkProxyTarget, + changeOrigin: true + }, + '/sdk': { + target: sdkProxyTarget, + changeOrigin: true + }, + '/museum-assets': { + target: museumAssetsProxyTarget, + changeOrigin: true + }, + '/minio': { + target: minioProxyTarget, + changeOrigin: true + }, + '/nhm/audio': { + target: audioProxyTarget, + changeOrigin: true + } } - } - }, - resolve: { - alias: { - '@': '/src' - } - }, - optimizeDeps: { - include: ['three'] - }, - build: { - rollupOptions: { - output: { - manualChunks: { - three: ['three'] + }, + resolve: { + alias: { + '@': '/src' + } + }, + optimizeDeps: { + include: ['three'] + }, + build: { + rollupOptions: { + output: { + manualChunks: { + three: ['three'] + } } } }