feat(mock): 内置 mock 模式——严格契约中间件 + 种子数据(--mode mock 专用)

This commit is contained in:
chenxing
2026-10-01 23:10:08 +08:00
parent 8c8147cd5b
commit 7d6560703d
3 changed files with 458 additions and 1 deletions
+32 -1
View File
@@ -1,4 +1,4 @@
import { ConfigEnv, UserConfig, defineConfig } from "vite";
import { ConfigEnv, UserConfig, defineConfig, type Plugin } from "vite";
import { createHtmlPlugin } from "vite-plugin-html";
import vue from "@vitejs/plugin-vue";
import path, { resolve } from "path";
@@ -9,6 +9,35 @@ import UnoCSS from "@unocss/vite";
import presetUno from "@unocss/preset-uno";
import presetRemToPx from "@unocss/preset-rem-to-px";
// mock 数据层(仅 --mode mock 注册,见下方 gatewayAdminMockPlugin;零依赖手写中间件而非
// vite-plugin-mock:后者独立打包 mock 文件为第二模块实例,无法实现"整页刷新重置内存态")
import { handleGatewayMockRequest, resetGatewayMockState } from "./src/assets/mock/gatewayApi";
/** 内置 mock(仅 serve + --mode mock):拦截 /open-gateway/api/internal/** 按后端契约应答。
* 直接注册在 configureServer(先于 vite 内部中间件,含 /open-gateway/api 代理);
* 整页文档请求(刷新/直达)触发内存态重置回静态种子,SPA 站内切换不重置。 */
function gatewayAdminMockPlugin(): Plugin {
return {
name: "gateway-admin-mock",
apply: "serve",
configureServer(server) {
server.middlewares.use((req, _res, next) => {
const accept = String(req.headers.accept ?? "");
if (accept.includes("text/html")) resetGatewayMockState();
next();
});
server.middlewares.use(async (req, res, next) => {
try {
if (!(await handleGatewayMockRequest(req, res))) next();
} catch (e) {
next(e);
}
});
},
};
}
// 构建输出恒为 dist 根:CI 打包 zip 的根目录必须直接是 index.html(projman 前端发布校验 zip 根含 html)。
// 不再有 dist/base 中间层——outDir=dist/base 时 zip 打 dist 整层,zip 根只有 base/,发布会校验失败。
// dev(--mode dev)读 .env.dev,VITE_SERVICE_HOST 指向同源前缀 /open-gateway(经下方 proxy 打到 base 域)
@@ -17,6 +46,8 @@ export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
return {
plugins: [
// 仅 --mode mock 启用内置 mock;dev/联调/正式 build 行为零变化
...(mode === "mock" ? [gatewayAdminMockPlugin()] : []),
vue(),
createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), "src/assets/icons")],