From 2f423c2d334fe5283cfc1cdfbb3049e0064849dc Mon Sep 17 00:00:00 2001 From: chenxing Date: Tue, 8 Sep 2026 22:10:37 +0800 Subject: [PATCH] =?UTF-8?q?env-config=20=E8=BF=90=E8=A1=8C=E6=97=B6?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E8=BF=81=E7=A7=BB=EF=BC=9Avite=20=E4=BA=A7?= =?UTF-8?q?=E7=89=A9=E7=9B=B4=E5=87=BA=20dist/=EF=BC=88=E6=A0=B9=E6=B2=BB?= =?UTF-8?q?=20zip=20=E6=A0=B9=E5=8F=AA=E6=9C=89=20base/=20=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E3=80=81projman=20=E5=89=8D=E7=AB=AF=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E6=A0=A1=E9=AA=8C=E7=BC=BA=20html=EF=BC=89=EF=BC=8Cin?= =?UTF-8?q?dex.html=20=E5=86=85=E8=81=94=E5=BC=95=E5=AF=BC=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=8B=89=20/api/env-config=3Ftarget=3Dfront=EF=BC=8Ch?= =?UTF-8?q?ost.config=20=E6=94=B9=E4=B8=89=E7=BA=A7=E5=90=88=E5=B9=B6?= =?UTF-8?q?=EF=BC=88=5F=5FAPP=5FCONFIG=5F=5F=20>=20VITE=5F*=20=E4=BB=85?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=20>=20=E5=90=8C=E5=9F=9F=E6=8E=A8=E5=AF=BC?= =?UTF-8?q?=EF=BC=89=EF=BC=9B=E5=88=A0=20.env.base/.env.prod/.env.ld?= =?UTF-8?q?=EF=BC=8Cbuild=20=E4=BA=A7=E7=89=A9=E9=9B=B6=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=80=BC=E7=83=A7=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.base | 7 ----- .env.dev | 5 +++- .env.ld | 7 ----- .env.mock | 3 +- .env.prod | 7 ----- .gitea/workflows/build.yml | 4 ++- index.html | 24 +++++++++++++++ src/assets/config/host.config.ts | 51 +++++++++++++++++++++++++++++--- src/assets/mock/noticeapi.ts | 2 +- vite.config.ts | 10 ++++--- 10 files changed, 87 insertions(+), 33 deletions(-) delete mode 100644 .env.base delete mode 100644 .env.ld delete mode 100644 .env.prod diff --git a/.env.base b/.env.base deleted file mode 100644 index b83e642..0000000 --- a/.env.base +++ /dev/null @@ -1,7 +0,0 @@ -# 正式环境 - base -VITE_BASE_HOST=http://base.yunhaixingtong.com -VITE_SSO_HOST=http://sso.yunhaixingtong.com -VITE_SERVICE_HOST=http://base.yunhaixingtong.com/notice -VITE_ZIYUANKU_HOST=https://base.bestsch.com/BschZyk -VITE_ZHUANXIANG_HOST=https://base.bestsch.com/BschZncpd -VITE_IS_MOCK=false diff --git a/.env.dev b/.env.dev index 6c4d1d2..1ae819e 100644 --- a/.env.dev +++ b/.env.dev @@ -1,4 +1,7 @@ -# 开发环境 (dev):API 走 /api 同源相对路径(vite proxy 转发到本地后端 8070), +# 开发环境 (dev):仅 vite dev --mode dev 加载;build 产物不读任何 .env.* +# (.env.base/.env.ld/.env.prod 已删,线上由 /api/env-config?target=front 运行时下发)。 +# ⚠️ VITE_* 仅本地开发生效。 +# API 走 /api 同源相对路径(vite proxy 转发到本地后端 8101), # 规避后端 CAS 过滤器不回 CORS 头导致的跨域拦截;SSO/基础平台用真实环境 VITE_BASE_HOST=http://base.yunhaixingtong.com VITE_SSO_HOST=http://sso.yunhaixingtong.com diff --git a/.env.ld b/.env.ld deleted file mode 100644 index 87a8a5a..0000000 --- a/.env.ld +++ /dev/null @@ -1,7 +0,0 @@ -# 正式环境 - ld -VITE_BASE_HOST=https://ld.bestsch.com -VITE_SSO_HOST=http://sso.yunhaixingtong.com -VITE_SERVICE_HOST=https://ld.yunhaixingtong.com/notice -VITE_ZIYUANKU_HOST=https://ld.bestsch.com/BschZyk -VITE_ZHUANXIANG_HOST=https://ld.bestsch.com/BschZncpd -VITE_IS_MOCK=false diff --git a/.env.mock b/.env.mock index 90dfc5c..ffc6301 100644 --- a/.env.mock +++ b/.env.mock @@ -1,4 +1,5 @@ -# 本地纯前端调试模式:后端 SSO/base 不可达时启用内置 mock +# 本地纯前端调试模式:仅 vite dev --mode mock 加载(build 产物不读任何 .env.*, +# 线上由 /api/env-config?target=front 运行时下发)。后端 SSO/base 不可达时启用内置 mock # 启动:npm run dev:mock VITE_BASE_HOST= VITE_SSO_HOST= diff --git a/.env.prod b/.env.prod deleted file mode 100644 index 627c98f..0000000 --- a/.env.prod +++ /dev/null @@ -1,7 +0,0 @@ -# 生产环境 - prod(vite build --mode prod 加载此文件) -VITE_BASE_HOST=http://base.yunhaixingtong.com -VITE_SSO_HOST=http://sso.yunhaixingtong.com -VITE_SERVICE_HOST=http://base.yunhaixingtong.com/notice -VITE_ZIYUANKU_HOST=https://base.bestsch.com/BschZyk -VITE_ZHUANXIANG_HOST=https://base.bestsch.com/BschZncpd -VITE_IS_MOCK=false diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 8621be1..cea668b 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -55,7 +55,9 @@ jobs: docker rm -f frontbuild echo "BUILD CHECK OK" - # 打包 dist → zip(进入 dist 目录打包,zip 根目录直接是 html/css/js 文件) + # 打包 dist → zip(vite outDir 已简化为直出 dist/,无中间层;进入 dist 打包, + # zip 根目录直接是 index.html/css/js。此前 outDir=dist/base 时曾误打 dist/ 整层, + # zip 根只有 base/ 目录,projman 前端发布校验报「zip 根目录缺少 html 文件」) - name: 打包产物 run: | TAG=$(echo "$GITHUB_SHA" | cut -c1-8) diff --git a/index.html b/index.html index 1f63a2d..5d7555f 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,30 @@ + + <%- title %> diff --git a/src/assets/config/host.config.ts b/src/assets/config/host.config.ts index a39c7a4..d9f8849 100644 --- a/src/assets/config/host.config.ts +++ b/src/assets/config/host.config.ts @@ -1,12 +1,48 @@ import { BaseConf } from "@/types/Basics"; /** - * 通过 Vite 环境变量管理配置,不再依赖 window.conf / config.js - * 环境变量定义在项目根目录的 .env.dev / .env.base / .env.ld 中 + * 配置优先级(高 → 低): + * ① window.__APP_CONFIG__:线上运行时配置,index.html 引导脚本在应用模块加载前同步拉取 + * //api/env-config?target=<部署目录名>(本应用部署于 /{contextPath}/front/, + * 故为 front,对应后端键 yh.env-config.source.front,projman 配置管理维护)写入 + * ② import.meta.env.VITE_*:仅本地开发/演示(vite dev --mode dev 读 .env.dev、--mode mock 读 .env.mock); + * build 产物不读任何 .env.*(.env.base/.env.ld/.env.prod 已删),VITE_* 恒为 undefined, + * 本层自动跳过,产物不含任何环境值 + * ③ 同域推导兜底:env-config 未配置/拉取失败时框架至少能渲染并调通同源 API; + * ssoHost 为空 → 登出跳转不可用——与后端未就绪状态一致,可接受。 */ const env = import.meta.env; +// ③ 同域推导兜底:context 段取当前路径首段(/{contextPath}/front/ → contextPath,即后端上下文), +// 与服务端 context-path 对齐(本地无、base/prod /notice);本地 dev/mock 在根路径运行(无段), +// serviceHost 留空走 vite 同源代理(规避 CAS 过滤器不回 CORS 头) +const seg = window.location.pathname.split("/").filter(Boolean); +const origin = window.location.origin; + let conf: BaseConf = { + baseHost: origin, + ssoHost: "", + serviceHost: seg.length >= 2 ? `${origin}/${seg[0]}` : "", + relayConf: { + ziyuankuHost: "", + zhuanxiangHost: "", + }, + isMock: false, + isDebug: env.DEV, +}; + +// 逐键覆盖:只覆盖来源里实际出现且非空的键,未出现的键沿用底层值 +const applyConf = (target: any, source: any) => { + if (!source || typeof source !== "object") return; + Object.keys(source).forEach(key => { + if (source[key] !== undefined && source[key] !== null && source[key] !== "") { + (target as any)[key] = source[key]; + } + }); +}; + +// ② 本地开发/演示(build 产物中恒 undefined → 自动跳过) +applyConf(conf, { baseHost: env.VITE_BASE_HOST, ssoHost: env.VITE_SSO_HOST, serviceHost: env.VITE_IS_MOCK === "true" ? "" : env.VITE_SERVICE_HOST, @@ -15,8 +51,15 @@ let conf: BaseConf = { zhuanxiangHost: env.VITE_ZHUANXIANG_HOST, }, isMock: env.VITE_IS_MOCK === "true", - isDebug: env.DEV, -}; +}); + +// ① 线上运行时配置(最高优先,覆盖前面所有);relayConf 为嵌套对象,按子键合并, +// 运行时 JSON 只配部分资源库地址时未配的键沿用兜底值 +const runtime = (window as any).__APP_CONFIG__; +applyConf(conf, runtime); +if (runtime && typeof runtime === "object" && runtime.relayConf) { + applyConf(conf.relayConf, runtime.relayConf); +} // HTTPS 自动升级:当前页面是 https 时,将所有 http:// 配置项升级为 https:// var ishttps = "https:" == document.location.protocol ? true : false; diff --git a/src/assets/mock/noticeapi.ts b/src/assets/mock/noticeapi.ts index d402c21..243fa87 100644 --- a/src/assets/mock/noticeapi.ts +++ b/src/assets/mock/noticeapi.ts @@ -1,7 +1,7 @@ /** * 通知公告本地 Mock 数据(vite-plugin-mock,dev 下 VITE_IS_MOCK=true 生效)。 * - * 背景:本地无法访问 sso.yunhaixingtong.com / base.yunhaixingtong.com, + * 背景:本地无法访问真实环境的 SSO / 基础平台域名, * 后端 CAS 过滤器会拦截 /api/* 请求,导致前端无法联调。 * 该文件按后端 NoticeApiController / DictController / ContactsController / * FileController 的真实响应契约({code, msg, data})提供内存数据, diff --git a/vite.config.ts b/vite.config.ts index d878390..b187c01 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -12,9 +12,11 @@ import presetUno from "@unocss/preset-uno"; import presetRemToPx from "@unocss/preset-rem-to-px"; export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => { - // 构建输出目录:base -> dist/base, ld -> dist/ld, 默认 dist/base - const subDir = mode === "ld" ? "ld" : "base"; - const outDir = command === "build" ? `dist/${subDir}` : "dist"; + // 构建产物直出 dist/(env-config 模式,与 Cms/UserBase 同风格):CI zip 打包取 dist 根, + // 不再有 dist/base 中间层(此前 outDir=dist/base 时 zip 打 dist 整层,zip 根只有 base/ + // 目录,projman 前端发布校验报「zip 根目录缺少 html 文件」);dev(serve) 不写产物, + // 两者共用该值无冲突 + const outDir = "dist"; return { plugins: [ @@ -117,7 +119,7 @@ export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => { base: "./", build: { target: "modules", //设置最终构建的浏览器兼容目标 //es2015(编译成es5) | modules - outDir, // 构建输出目录,根据环境变量区分 base/ld + outDir, // 构建输出目录(恒 dist 根,见文件头说明) assetsDir: "assets", // 静态资源得存放路径文件名 assets sourcemap: false, //构建后是否生成 source map 文件 minify: "esbuild", // 项目压缩 :boolean | 'terser' | 'esbuild'