env-config 运行时配置迁移:vite 产物直出 dist/(根治 zip 根只有 base/ 目录、projman 前端发布校验缺 html),index.html 内联引导同步拉 /api/env-config?target=front,host.config 改三级合并(__APP_CONFIG__ > VITE_* 仅本地 > 同域推导);删 .env.base/.env.prod/.env.ld,build 产物零环境值烧入
build / build (push) Successful in 4m21s
build / build (push) Successful in 4m21s
This commit is contained in:
@@ -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
|
|
||||||
@@ -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/基础平台用真实环境
|
# 规避后端 CAS 过滤器不回 CORS 头导致的跨域拦截;SSO/基础平台用真实环境
|
||||||
VITE_BASE_HOST=http://base.yunhaixingtong.com
|
VITE_BASE_HOST=http://base.yunhaixingtong.com
|
||||||
VITE_SSO_HOST=http://sso.yunhaixingtong.com
|
VITE_SSO_HOST=http://sso.yunhaixingtong.com
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
# 启动:npm run dev:mock
|
||||||
VITE_BASE_HOST=
|
VITE_BASE_HOST=
|
||||||
VITE_SSO_HOST=
|
VITE_SSO_HOST=
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -55,7 +55,9 @@ jobs:
|
|||||||
docker rm -f frontbuild
|
docker rm -f frontbuild
|
||||||
echo "BUILD CHECK OK"
|
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: 打包产物
|
- name: 打包产物
|
||||||
run: |
|
run: |
|
||||||
TAG=$(echo "$GITHUB_SHA" | cut -c1-8)
|
TAG=$(echo "$GITHUB_SHA" | cut -c1-8)
|
||||||
|
|||||||
+24
@@ -5,6 +5,30 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="../../favicon.ico" />
|
<link rel="icon" type="image/svg+xml" href="../../favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<!-- 运行时配置引导:在任何应用模块执行前同步拉取 /<contextPath>/api/env-config
|
||||||
|
(后端免登录端点,projman 配置管理在线维护),替代生产构建环境变量。
|
||||||
|
必须同步:host.config.ts 在模块求值期就读 window.__APP_CONFIG__;失败/本地开发
|
||||||
|
(根路径,段数不足 2)则不设置:本地走 .env.dev/.env.mock(VITE_*),线上走同域推导兜底。
|
||||||
|
target = URL 第 2 段目录名:本应用产物部署于 /{contextPath}/front/,故为 front,
|
||||||
|
对应后端配置键 yh.env-config.source.front(环境变量 YH_ENV_CONFIG_SOURCE_FRONT)。
|
||||||
|
注意:同步 XHR 不支持 timeout 属性(赋值会抛 InvalidAccessError),依赖内网快速失败 -->
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
try {
|
||||||
|
var seg = location.pathname.split("/").filter(Boolean);
|
||||||
|
if (seg.length < 2) return; // 本地开发(根路径):走 .env.dev / .env.mock
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/" + seg[0] + "/api/env-config?target=" + encodeURIComponent(seg[1]), false);
|
||||||
|
xhr.send(null);
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
var conf = JSON.parse(xhr.responseText);
|
||||||
|
if (conf && typeof conf === "object") window.__APP_CONFIG__ = conf;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
/* 拉取失败保持未设置,走同域推导兜底 */
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
<title><%- title %></title>
|
<title><%- title %></title>
|
||||||
<link rel="stylesheet" href="./libs/ztree/zTreeStyle.css" />
|
<link rel="stylesheet" href="./libs/ztree/zTreeStyle.css" />
|
||||||
<script src="./libs/jquery.min.js"></script>
|
<script src="./libs/jquery.min.js"></script>
|
||||||
|
|||||||
@@ -1,12 +1,48 @@
|
|||||||
import { BaseConf } from "@/types/Basics";
|
import { BaseConf } from "@/types/Basics";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 Vite 环境变量管理配置,不再依赖 window.conf / config.js
|
* 配置优先级(高 → 低):
|
||||||
* 环境变量定义在项目根目录的 .env.dev / .env.base / .env.ld 中
|
* ① window.__APP_CONFIG__:线上运行时配置,index.html 引导脚本在应用模块加载前同步拉取
|
||||||
|
* /<contextPath>/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;
|
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 = {
|
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,
|
baseHost: env.VITE_BASE_HOST,
|
||||||
ssoHost: env.VITE_SSO_HOST,
|
ssoHost: env.VITE_SSO_HOST,
|
||||||
serviceHost: env.VITE_IS_MOCK === "true" ? "" : env.VITE_SERVICE_HOST,
|
serviceHost: env.VITE_IS_MOCK === "true" ? "" : env.VITE_SERVICE_HOST,
|
||||||
@@ -15,8 +51,15 @@ let conf: BaseConf = {
|
|||||||
zhuanxiangHost: env.VITE_ZHUANXIANG_HOST,
|
zhuanxiangHost: env.VITE_ZHUANXIANG_HOST,
|
||||||
},
|
},
|
||||||
isMock: env.VITE_IS_MOCK === "true",
|
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://
|
// HTTPS 自动升级:当前页面是 https 时,将所有 http:// 配置项升级为 https://
|
||||||
var ishttps = "https:" == document.location.protocol ? true : false;
|
var ishttps = "https:" == document.location.protocol ? true : false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* 通知公告本地 Mock 数据(vite-plugin-mock,dev 下 VITE_IS_MOCK=true 生效)。
|
* 通知公告本地 Mock 数据(vite-plugin-mock,dev 下 VITE_IS_MOCK=true 生效)。
|
||||||
*
|
*
|
||||||
* 背景:本地无法访问 sso.yunhaixingtong.com / base.yunhaixingtong.com,
|
* 背景:本地无法访问真实环境的 SSO / 基础平台域名,
|
||||||
* 后端 CAS 过滤器会拦截 /api/* 请求,导致前端无法联调。
|
* 后端 CAS 过滤器会拦截 /api/* 请求,导致前端无法联调。
|
||||||
* 该文件按后端 NoticeApiController / DictController / ContactsController /
|
* 该文件按后端 NoticeApiController / DictController / ContactsController /
|
||||||
* FileController 的真实响应契约({code, msg, data})提供内存数据,
|
* FileController 的真实响应契约({code, msg, data})提供内存数据,
|
||||||
|
|||||||
+6
-4
@@ -12,9 +12,11 @@ import presetUno from "@unocss/preset-uno";
|
|||||||
import presetRemToPx from "@unocss/preset-rem-to-px";
|
import presetRemToPx from "@unocss/preset-rem-to-px";
|
||||||
|
|
||||||
export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
|
export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
|
||||||
// 构建输出目录:base -> dist/base, ld -> dist/ld, 默认 dist/base
|
// 构建产物直出 dist/(env-config 模式,与 Cms/UserBase 同风格):CI zip 打包取 dist 根,
|
||||||
const subDir = mode === "ld" ? "ld" : "base";
|
// 不再有 dist/base 中间层(此前 outDir=dist/base 时 zip 打 dist 整层,zip 根只有 base/
|
||||||
const outDir = command === "build" ? `dist/${subDir}` : "dist";
|
// 目录,projman 前端发布校验报「zip 根目录缺少 html 文件」);dev(serve) 不写产物,
|
||||||
|
// 两者共用该值无冲突
|
||||||
|
const outDir = "dist";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
plugins: [
|
plugins: [
|
||||||
@@ -117,7 +119,7 @@ export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
|
|||||||
base: "./",
|
base: "./",
|
||||||
build: {
|
build: {
|
||||||
target: "modules", //设置最终构建的浏览器兼容目标 //es2015(编译成es5) | modules
|
target: "modules", //设置最终构建的浏览器兼容目标 //es2015(编译成es5) | modules
|
||||||
outDir, // 构建输出目录,根据环境变量区分 base/ld
|
outDir, // 构建输出目录(恒 dist 根,见文件头说明)
|
||||||
assetsDir: "assets", // 静态资源得存放路径文件名 assets
|
assetsDir: "assets", // 静态资源得存放路径文件名 assets
|
||||||
sourcemap: false, //构建后是否生成 source map 文件
|
sourcemap: false, //构建后是否生成 source map 文件
|
||||||
minify: "esbuild", // 项目压缩 :boolean | 'terser' | 'esbuild'
|
minify: "esbuild", // 项目压缩 :boolean | 'terser' | 'esbuild'
|
||||||
|
|||||||
Reference in New Issue
Block a user