# Admin-UI 分模块打包功能设计文档 > **设计日期**: 2026-06-04 > **版本**: v1.0 > **状态**: 已批准 > **目标**: 实现 Admin-UI 按系统配置分模块打包,支持不同租户类型输出不同产物包 --- ## 一、背景与目标 ### 1.1 现状分析 当前 Admin-UI 存在以下问题: 1. **路由硬编码**:所有页面路由集中在 `router/index.ts` 中硬编码,无法按模块裁剪 2. **构建产物单一**:无论服务哪个租户,都打包所有页面代码,产物体积大 3. **缺乏系统差异化**:Dashboard、登录页等核心页面无法根据不同系统定制 4. **模块管理已有雏形**:后端已支持租户模块配置(`ModuleDialog.vue`),但前端构建未与之配合 ### 1.2 目标定义 1. **构建时分包**:根据 JSON 配置文件,构建时只打包指定模块的代码 2. **动态路由生成**:替换硬编码路由,构建时根据配置动态生成路由表 3. **系统差异化页面**:支持 Dashboard、登录页按系统配置加载不同子组件 4. **多产物输出**:不同系统输出到 `dist/{systemKey}/` 目录 5. **保持现有功能**:菜单 API 获取、权限控制、主题切换等功能不受影响 --- ## 二、详细设计 ### 2.1 整体架构 ``` 构建流程: ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ build-config/ │ │ Vite Plugin │ │ 构建产物 │ │ cashier.json │────→│ (module-build) │────→│ dist/cashier/ │ │ admin.json │ │ │ │ dist/admin/ │ │ super.json │ │ 1. 读取配置 │ │ dist/super/ │ └─────────────────┘ │ 2. 生成路由 │ │ │ │ 3. 注入配置 │ └─────────────────┘ │ 4. 配置输出 │ └──────────────────┘ 运行时: ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ 统一入口页面 │────→│ 虚拟模块配置 │────→│ 系统特定子组件 │ │ Dashboard │ │ __SYSTEM_CONFIG__│ │ systems/ │ │ Login │ │ │ │ Cashier.vue │ └─────────────────┘ └──────────────────┘ │ Super.vue │ └─────────────────┘ ``` ### 2.2 核心组件 #### 2.2.1 配置文件(`build-config/`) 每个系统一个 JSON 配置文件: ```typescript interface BuildConfig { /** 系统唯一标识,产物目录名 */ key: string /** 系统显示名称 */ name: string /** 系统描述 */ description?: string /** 包含的模块列表 */ modules: string[] /** 登录页配置 */ login: { /** 登录组件名(对应 views/login/systems/ 下的组件) */ component: string /** 是否显示租户ID输入 */ showTenantInput: boolean /** 页面标题 */ title: string /** 副标题 */ subtitle?: string /** 背景图路径 */ background?: string /** Logo路径 */ logo?: string } /** Dashboard配置 */ dashboard: { /** Dashboard组件名(对应 views/dashboard/systems/ 下的组件) */ component: string /** 页面标题 */ title: string } /** 主题配置 */ theme: { /** 主题色 */ primaryColor: string /** 页面标题 */ title: string } } ``` **示例配置:** ```json // build-config/super.json { "key": "super", "name": "超级管理后台", "description": "超级租户专用,包含租户管理", "modules": ["system", "user"], "login": { "component": "Super", "showTenantInput": false, "title": "睿核平台管理", "subtitle": "超级管理员登录" }, "dashboard": { "component": "Super", "title": "平台运营概览" }, "theme": { "primaryColor": "#722ed1", "title": "睿核平台管理" } } ``` ```json // build-config/cashier.json { "key": "cashier", "name": "收银系统", "description": "面向收银场景的管理后台", "modules": ["system", "user", "cms", "cashier"], "login": { "component": "Cashier", "showTenantInput": true, "title": "睿核收银", "subtitle": "门店管理系统" }, "dashboard": { "component": "Cashier", "title": "收银数据概览" }, "theme": { "primaryColor": "#1677ff", "title": "睿核收银" } } ``` #### 2.2.2 Vite 插件(`scripts/vite-plugin-module-build.ts`) 插件职责: 1. **解析命令行参数**:读取 `--system={key}` 参数 2. **加载配置**:读取 `build-config/{key}.json` 3. **生成虚拟路由模块**:`virtual:generated-routes` - 根据 `config.modules` 从路由模板中组装路由表 - 只包含指定模块的路由 + 核心页面路由(登录、Dashboard入口、个人中心、设置) 4. **生成虚拟配置模块**:`virtual:system-config` - 将配置对象注入为全局常量 `__SYSTEM_CONFIG__` 5. **配置构建输出**: - `build.outDir = dist/${config.key}` - `build.rollupOptions.treeshake = true` 确保未使用代码被移除 **路由生成逻辑:** ```typescript // router/modules/system.ts export const systemRoutes = [ { path: 'system/menu', name: 'SystemMenu', component: () => import('@/views/system/menu/Index.vue'), meta: { i18n: 'menu.systemMenu' } }, { path: 'system/role', name: 'SystemRole', component: () => import('@/views/system/role/Index.vue'), meta: { i18n: 'menu.systemRole' } }, // ... ] // router/modules/user.ts export const userRoutes = [ { path: 'user/info', name: 'UserInfo', component: () => import('@/views/user/info/Index.vue'), meta: { i18n: 'menu.userInfo' } }, // ... ] // 插件根据 config.modules 动态组装 const moduleRoutes = config.modules.flatMap(module => { const routeModule = routeModules[module] return routeModule ? routeModule.routes : [] }) ``` #### 2.2.3 统一入口页面 **Dashboard 入口(`views/dashboard/Index.vue`):** ```vue ``` **登录页入口(`views/login/Index.vue`):** ```vue ``` ### 2.3 模块映射关系 建立 `src/views/` 下的页面目录与模块标识的映射: | 模块标识 | 对应目录 | 包含页面 | |---------|---------|---------| | `system` | `views/system/*` | 菜单、角色、部门、岗位、字典、配置、日志、登录日志、租户、租户套餐、数据权限、OAuth2客户端 | | `user` | `views/user/*` | 用户信息、用户详情、等级、等级日志、地址、账户 | | `order` | `views/order/*` | 订单列表、退款记录 | | `cms` | `views/cms/*` | 文章、分类、轮播图 | | `marketing` | `views/marketing/*` | 优惠券、活动管理 | | `demo` | `views/demo/*` | 图标演示、列表演示 | | `cashier` | `views/cashier/*` | 门店、包间、定价、订单、商品、报表 | **核心页面(所有系统默认包含,不依赖模块配置):** - `views/login/Index.vue` - 登录页入口 - `views/login/systems/*.vue` - 系统特定登录组件 - `views/dashboard/Index.vue` - Dashboard 入口 - `views/dashboard/systems/*.vue` - 系统特定 Dashboard 组件 - `views/profile/Index.vue` - 个人中心 - `views/settings/Index.vue` - 系统设置 ### 2.4 目录结构 ``` admin-ui/ ├── build-config/ # 系统打包配置 │ ├── cashier.json │ ├── admin.json │ ├── super.json │ └── default.json # 默认配置(全模块,用于开发) ├── scripts/ # 构建脚本 │ └── vite-plugin-module-build.ts # Vite 插件 ├── src/ │ ├── router/ │ │ ├── index.ts # 改造:使用虚拟路由模块 │ │ └── modules/ # 新增:按模块拆分路由配置 │ │ ├── core.ts # 核心路由(登录、Dashboard入口等) │ │ ├── system.ts │ │ ├── user.ts │ │ ├── order.ts │ │ ├── cms.ts │ │ ├── marketing.ts │ │ ├── demo.ts │ │ └── cashier.ts │ ├── views/ │ │ ├── login/ │ │ │ ├── Index.vue # 改造:统一入口 │ │ │ └── systems/ # 新增:系统特定登录组件 │ │ │ ├── Default.vue # 默认登录页 │ │ │ ├── Super.vue # 超级租户登录页 │ │ │ └── Cashier.vue # 收银系统登录页 │ │ ├── dashboard/ │ │ │ ├── Index.vue # 改造:统一入口 │ │ │ └── systems/ # 新增:系统特定 Dashboard │ │ │ ├── Default.vue # 默认 Dashboard │ │ │ ├── Cashier.vue # 收银系统 Dashboard │ │ │ └── Super.vue # 超级租户 Dashboard │ │ └── ... # 业务页面(保持现有结构) │ ├── types/ │ │ └── system-config.d.ts # 系统配置类型定义 │ └── ... ├── package.json # 改造:添加构建命令 └── vite.config.ts # 改造:注册插件 ``` ### 2.5 构建命令 ```json // package.json { "scripts": { "dev": "vite --port 3000", "dev:cashier": "vite --port 3000 -- --system=cashier", "dev:super": "vite --port 3000 -- --system=super", "build": "vue-tsc && vite build", "build:cashier": "vue-tsc && vite build -- --system=cashier", "build:super": "vue-tsc && vite build -- --system=super", "build:admin": "vue-tsc && vite build -- --system=admin", "build:all": "pnpm build:cashier && pnpm build:super && pnpm build:admin" } } ``` **产物输出:** ``` dist/ ├── cashier/ # 收银系统(system + user + cms + cashier) ├── super/ # 超级租户(system + user) ├── admin/ # 普通后台(system + user + order + cms + marketing) └── default/ # 默认(全模块,用于开发测试) ``` ### 2.6 主题配置应用 系统配置中的 `theme` 字段在运行时应用: ```typescript // App.vue 或布局组件 import systemConfig from 'virtual:system-config' // 设置页面标题 document.title = systemConfig.theme.title // 设置主题色(Element Plus) const el = document.documentElement el.style.setProperty('--el-color-primary', systemConfig.theme.primaryColor) ``` --- ## 三、验收标准 - [ ] 执行 `pnpm build:super` 成功构建,产物输出到 `dist/super/`,只包含 system 和 user 模块的页面 - [ ] 执行 `pnpm build:cashier` 成功构建,产物输出到 `dist/cashier/`,包含 system、user、cms、cashier 模块的页面 - [ ] 不同系统的 Dashboard 显示不同的子组件内容 - [ ] 不同系统的登录页显示不同的子组件内容(超级租户无租户ID输入) - [ ] 构建产物中不包含未配置模块的页面代码(Tree Shaking 生效) - [ ] 现有菜单 API 获取、权限控制、主题切换功能正常 - [ ] 开发模式 `pnpm dev:cashier` 正常工作,热更新无问题 --- ## 四、风险与依赖 | 风险 | 影响 | 缓解措施 | |------|------|---------| | Vite 插件开发复杂度 | 中 | 插件逻辑清晰拆分:配置读取、路由生成、虚拟模块、输出配置 | | Tree Shaking 不彻底 | 中 | 使用 `import()` 动态导入,配合 Rollup 的 `treeshake` 配置,构建后检查产物 | | 动态组件加载失败 | 低 | 添加错误处理,加载失败时回退到 Default 组件 | | 现有功能回归 | 中 | 构建后逐一验证核心功能:登录、菜单、CRUD、主题切换 | | 多人协作冲突 | 低 | 配置文件集中管理,模块路由独立文件,减少冲突 | --- ## 五、后续扩展 1. **国际化支持**:配置文件中可扩展 `locales` 字段,支持系统特定的翻译覆盖 2. **模块懒加载**:未来可考虑运行时动态加载模块(Module Federation) 3. **版本管理**:配置文件支持 `version` 字段,用于产物版本控制 4. **CI/CD 集成**:构建命令可直接接入 Jenkins/GitHub Actions,参数化构建不同系统