feat(theme): A 类免插件接入 YschTheme 中央静态通道(index.html loader + 删本地 layout.css)

- index.html:env-config 引导后插主题通道 loader(优先级 staticHost > baseHost > %VITE_THEME_HOST% 仅 dev > 同源 /static,document.write parser-blocking,产物占位符零烧入)
- main.ts:删本地 layout.css 引入(通道旧版全量拷贝 14.8KB),注释改指通道下发链
- src/assets/styles/layout.css:删除(staged)
- vite.config.ts:/static dev 代理(YH_THEME_PROXY_TARGET 可覆盖)+ /api /mobiapi 代理整理
- .env.dev:三种 dev 模式说明 + VITE_THEME_HOST 连法注释
- App.vue:注释纠正(主题样式改由中央通道下发)
- alova-iview/alova-vant:修 mock 失效(baseUrl 未认 isMock)
依据:YschTheme 方案 §11 A 类契约 +《主题通道当前困境与待决问题-20260929》§3 九文件清单
This commit is contained in:
chenxing
2026-10-06 20:16:03 +08:00
parent ec53c34b9c
commit 5296b5999c
8 changed files with 68 additions and 47 deletions
+8
View File
@@ -1,9 +1,17 @@
# 开发环境 (dev):仅 vite dev 加载(--mode dev)。值可自由指本地或线上地址。
# build 产物不读此文件(build 默认 production mode,只认 .env / .env.production,两者均不存在),
# 线上环境差异全部由 projman 的 env-config-{目标}.json 承担。
#
# 本地起服务的三种模式(详见 vite.config.ts 的 server.proxy 注释):
# 纯前端 mock: VITE_IS_MOCK=true npm run dev → 用户/菜单走 src/assets/mock,其余接口透传给后端
# 本地后端联调: npm run dev → 跨源直连本文件 VITE_SERVICE_HOST
# 线上后端联调: VITE_SERVICE_HOST= YH_API_PROXY_TARGET=http://base.yunhaixingtong.com/userbase npm run dev
# (留空 VITE_SERVICE_HOST 让请求走同源 /api,由 dev 代理转发;CAS 登录 cookie 跨域带不过去时改用本地后端)
VITE_BASE_HOST=http://base.bestsch.com
VITE_SSO_HOST=http://sso.yunhaixingtong.com
VITE_SERVICE_HOST=http://localhost:8060
VITE_ZIYUANKU_HOST=https://base.bestsch.com/BschZyk
VITE_ZHUANXIANG_HOST=https://base.bestsch.com/BschZncpd
VITE_IS_MOCK=false
# 主题通道 dev 跨源直连(可选,需通道已开 CORS);留空则同源相对 → 走 vite 的 /static 代理
VITE_THEME_HOST=
+20
View File
@@ -27,6 +27,26 @@
}
})();
</script>
<!-- 主题通道引导(A 类免插件接入,见 YschTheme《管理端主题远程化与公共静态通道方案》§11):
唯一接入点。不装 npm 依赖、不改构建配置;FOUC 门、manifest 预取、主题 <link> 追加与
排序(晚于 viewuiplus.css)全由通道 yh-theme-init.js 承担,主题升级走 /static 通道,
本应用无需重新构建。
origin 零写死,优先级四档:__APP_CONFIG__.staticHost(专用通道覆盖)
> __APP_CONFIG__.baseHost(env-config 在线维护,换域名改配置即生效)
> %VITE_THEME_HOST%(仅 dev 注入的跨源直连,需通道已开 CORS)
> 同源相对 "/static/…"(生产常态:本应用部署在 base 域 /userbase/front/,与通道同源;
本地 dev 由 vite.config 的 /static 代理兜到通道)。
document.write 是有意为之:保证 parser-blocking,让档位类与 FOUC 门先于首帧;
build 不读 .env,占位符留字面量 → 判首字符 % 置空 → 产物零环境值烧入。 -->
<script>
(function () {
var c = window.__APP_CONFIG__ || {};
var themeHost = "%VITE_THEME_HOST%";
if (themeHost.charAt(0) === "%") themeHost = "";
var host = String(c.staticHost || c.baseHost || themeHost).replace(/\/+$/, "");
document.write('<script src="' + host + '/static/js/yh-theme-init.js"><\/script>');
})();
</script>
<title><%- title %></title>
<link rel="stylesheet" href="./libs/ztree/zTreeStyle.css" />
<script src="./libs/jquery.min.js"></script>
+1 -1
View File
@@ -70,7 +70,7 @@ const setCurrentRole = (user: any) => {
};
localStorage.setItem("currentRole", encodeURI(JSON.stringify(currentRole)));
// 主题样式已本地化到 src/assets/styles/layout.css(含 default-theme / base.layout.beta / _iview_override),不再请求远程样式
// 主题样式由中央静态通道下发(index.html 的 yh-theme-init.js 挂 /static/*),本仓不再持有 layout.css
if (user?.type === 1) {
store.setUserRole(UserRoleEnum.SuperAdmin);
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -13,8 +13,9 @@ import mittBus from "@/utils/mitt";
import "view-ui-plus/dist/styles/viewuiplus.css";
import "@/assets/styles/main.scss";
// 本地化的布局/主题样式(原远程 base.layout.beta / _iview_override / default-theme 合并)
import "@/assets/styles/layout.css";
// 布局/主题/图标(base.layout.css + iview.override.css + icons.css)由中央静态通道下发:
// index.html 的 yh-theme-init.js 在 DOMContentLoaded 后按 manifest 版本追加 <link>,
// 天然排在本行组件库样式与 main.scss 之后(原本地 layout.css 是通道旧版全量拷贝,已删)
//导入自定义指令
import directive from "@/utils/directive/index";
+8 -1
View File
@@ -14,7 +14,14 @@ function closeLoading() {
}
}
const baseUrl = conf.serviceHost;
/**
* mock 模式必须短路成同源相对路径,否则 alova 会带着 serviceHost(本地 8060 / 线上域)跨源直连,
* vite-plugin-mock 的中间件根本拦不到——这正是 `VITE_IS_MOCK=true` 开了却仍报 "Failed to fetch" 的根因
* (axios 那条老链路的 api.config.ts 认 isMock,迁到 alova 后这一处漏了)。
* 同源之后:mock 注册过的接口(/api/base/GetUserInfo、GetUserMod)由 mock 应答,
* 未注册的接口继续经 vite.config 的 /api 代理透传给后端(见 YH_API_PROXY_TARGET)。
*/
const baseUrl = conf.isMock ? "" : conf.serviceHost;
/* 创建带 View Design UI 的 Alova 实例 */
export const alovaInstance = createBschAlova(baseUrl, {
+2 -1
View File
@@ -19,7 +19,8 @@ function closeLoading() {
}
// const baseUrl = conf.serviceHost + "/api";
const baseUrl = conf.serviceHost + "/mobiapi";
// 同 alova-iview:mock 模式短路成同源,否则 vite-plugin-mock / dev 代理都拦不到跨源请求
const baseUrl = (conf.isMock ? "" : conf.serviceHost) + "/mobiapi";
/* 创建带 Vant UI 的 Alova 实例 */
export const alovaInstance = createBschAlova(baseUrl, {
injectHeaders(method) {
+26 -9
View File
@@ -99,15 +99,32 @@ export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
server: {
host: "localhost",
port: 8130,
// proxy: {
// // //api是自行设置的请求前缀,任何请求路径以/api开头的请求将被代理到对应的target目标
// // "/api": {
// // target: "http://localhost:8064/",
// // // target: "http://debugold.hongyucloud.com/ChildOptCourse",
// // changeOrigin: true, //需要代理跨域
// // rewrite: (path: any) => path.replace(/^\/api/, "/api/"), //路径重写,把'/api'替换为''
// // },
// },
proxy: {
// 主题通道本地联调(唯一必需项):dev 下 index.html 的 loader 走同源相对(见其注释的优先级四档),
// manifest/CSS 经此代理到中央通道;changeOrigin 顺带把 Host 改写成目标域,Caddy 按 Host 匹配站点。
// 联调本地通道源:YschTheme 侧 npm run serve:static(默认 9527),再用
// YH_THEME_PROXY_TARGET=http://localhost:9527 覆盖本 target。prod 同源用不到这段。
"/static": {
target: process.env.YH_THEME_PROXY_TARGET || "http://base.yunhaixingtong.com",
changeOrigin: true,
},
// 后端接口同源代理:alova 的 baseURL 在非 mock 时取 .env 的 VITE_SERVICE_HOST,
// 想"只换后端不改 .env"就把 VITE_SERVICE_HOST 留空 → 请求落同源 /api、/mobiapi → 由此处代理决定去向。
// 本地后端(默认):npm run dev
// 线上后端: YH_API_PROXY_TARGET=http://base.yunhaixingtong.com/userbase npm run dev
// (changeOrigin 已改写 Host,Caddy 按 Host 匹配;但 CAS 登录 cookie 属
// yunhaixingtong 域,localhost 侧带不上 → 未登录接口会被 302 到 SSO,
// 需要真数据时优先配合 VITE_IS_MOCK=false + 本地后端,或先在同浏览器登录线上)
// mock 模式(VITE_IS_MOCK=true)下已注册的接口由 vite-plugin-mock 直接应答,未注册的仍透传到本 target。
"/api": {
target: process.env.YH_API_PROXY_TARGET || "http://localhost:8060",
changeOrigin: true,
},
"/mobiapi": {
target: process.env.YH_API_PROXY_TARGET || "http://localhost:8060",
changeOrigin: true,
},
},
},
// css预处理器
css: {