build / build (push) Successful in 5m40s
- index.html 插 A 类 loader:唯一接入点,FOUC 门/manifest 预取/主题 link 追加与排序 全由通道 yh-theme-init.js 承担,主题升级走 /static 通道,本应用无需重新构建 - vite.config 加 /static dev 代理(YH_THEME_PROXY_TARGET 可覆盖,默认线上通道) - host.config 回写 __APP_CONFIG__.serviceHost(仅同源):init 的 appearance 请求有硬性 同源限制,跨源会被直接跳过;本地 dev 保持空串走同源 /api 代理 - 顶栏头像接平台键 yh-avatar,监听 yh-appearance-updated,userInfo 兜底 - view-ui-plus 声明锁 1.3.24(对齐通道皮肤生成版本)
110 lines
4.7 KiB
TypeScript
110 lines
4.7 KiB
TypeScript
import { BaseConf } from "@/types/Basics";
|
||
|
||
/**
|
||
* 配置优先级(高 → 低):
|
||
* ① 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;
|
||
|
||
// ③ 同域推导兜底:context 段取当前路径首段(/{contextPath}/front/ → contextPath,即后端上下文),
|
||
// 与服务端 context-path 对齐(本地无、base/prod /familyactivity);本地 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,
|
||
relayConf: {
|
||
ziyuankuHost: env.VITE_ZIYUANKU_HOST,
|
||
zhuanxiangHost: env.VITE_ZHUANXIANG_HOST,
|
||
},
|
||
isMock: env.VITE_IS_MOCK === "true",
|
||
});
|
||
|
||
// ① 线上运行时配置(最高优先,覆盖前面所有);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;
|
||
if (ishttps) {
|
||
Object.keys(conf).forEach(element => {
|
||
if (typeof conf[element] === "string" && conf[element].indexOf("http://") > -1) {
|
||
conf[element] = conf[element].replace("http://", "https://");
|
||
}
|
||
});
|
||
// relayConf 内部也需要处理
|
||
if (conf.relayConf) {
|
||
Object.keys(conf.relayConf).forEach(key => {
|
||
const val = (conf.relayConf as any)[key];
|
||
if (typeof val === "string" && val.indexOf("http://") > -1) {
|
||
(conf.relayConf as any)[key] = val.replace("http://", "https://");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 回写 __APP_CONFIG__.serviceHost(仅同源场景)——云海子 A 类接入 §3 外观三键。
|
||
* 主题通道 yh-theme-init.js 的 appearance 请求有硬性同源限制:
|
||
* if (!url || !appearanceSameOrigin(url)) return; → 跨源会被直接跳过、连请求都不发。
|
||
* 本地 dev:serviceHost 是 VITE_SERVICE_HOST 的绝对地址(跨源),此时不能回写,
|
||
* 保持空串让 init 走同源 "/api/appearance",由 vite 代理转发到后端。
|
||
* 生产:serviceHost = 同域 ctx(https://base.../<contextPath>),同源,回写后 init 请求正确前缀。
|
||
* 已有 env-config 下发值时不动(以平台配置为准)。
|
||
*/
|
||
try {
|
||
const w = window as any;
|
||
w.__APP_CONFIG__ = w.__APP_CONFIG__ || {};
|
||
if (!w.__APP_CONFIG__.serviceHost) {
|
||
const candidate = conf.serviceHost || "";
|
||
let sameOrigin = !candidate;
|
||
try {
|
||
sameOrigin = new URL(candidate, window.location.href).origin === window.location.origin;
|
||
} catch {
|
||
sameOrigin = false;
|
||
}
|
||
if (sameOrigin) w.__APP_CONFIG__.serviceHost = candidate;
|
||
}
|
||
} catch {
|
||
/* 极端环境无 window:忽略,保持同源兜底 */
|
||
}
|
||
|
||
export default conf;
|