19de7e24ec
从 docs-local 迁移以下文档: - backend/guides/: AI开发环境配置、Nacos配置、GitNexus指南、OpenCode工作流等 - backend/templates/: Superpowers设计模板、计划模板、审查清单 - backend/config-templates/: 应用配置模板、Nacos配置 - backend/design/: 数据库表结构规划 - backend/specs/: 项目文档治理、MQ统一推送设计 - backend/: 代码分析报告、Feign分析报告、文档治理报告 - frontend/design/: Admin-UI分模块打包设计
13 KiB
13 KiB
Admin-UI 分模块打包功能设计文档
设计日期: 2026-06-04 版本: v1.0 状态: 已批准 目标: 实现 Admin-UI 按系统配置分模块打包,支持不同租户类型输出不同产物包
一、背景与目标
1.1 现状分析
当前 Admin-UI 存在以下问题:
- 路由硬编码:所有页面路由集中在
router/index.ts中硬编码,无法按模块裁剪 - 构建产物单一:无论服务哪个租户,都打包所有页面代码,产物体积大
- 缺乏系统差异化:Dashboard、登录页等核心页面无法根据不同系统定制
- 模块管理已有雏形:后端已支持租户模块配置(
ModuleDialog.vue),但前端构建未与之配合
1.2 目标定义
- 构建时分包:根据 JSON 配置文件,构建时只打包指定模块的代码
- 动态路由生成:替换硬编码路由,构建时根据配置动态生成路由表
- 系统差异化页面:支持 Dashboard、登录页按系统配置加载不同子组件
- 多产物输出:不同系统输出到
dist/{systemKey}/目录 - 保持现有功能:菜单 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 配置文件:
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
}
}
示例配置:
// 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": "睿核平台管理"
}
}
// 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)
插件职责:
- 解析命令行参数:读取
--system={key}参数 - 加载配置:读取
build-config/{key}.json - 生成虚拟路由模块:
virtual:generated-routes- 根据
config.modules从路由模板中组装路由表 - 只包含指定模块的路由 + 核心页面路由(登录、Dashboard入口、个人中心、设置)
- 根据
- 生成虚拟配置模块:
virtual:system-config- 将配置对象注入为全局常量
__SYSTEM_CONFIG__
- 将配置对象注入为全局常量
- 配置构建输出:
build.outDir = dist/${config.key}build.rollupOptions.treeshake = true确保未使用代码被移除
路由生成逻辑:
// 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):
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
import systemConfig from 'virtual:system-config'
// 动态加载系统特定的 Dashboard 组件
const dashboardComponent = defineAsyncComponent(() =>
import(`./systems/${systemConfig.dashboard.component}.vue`)
)
</script>
<template>
<component :is="dashboardComponent" />
</template>
登录页入口(views/login/Index.vue):
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
import systemConfig from 'virtual:system-config'
// 动态加载系统特定的登录组件
const loginComponent = defineAsyncComponent(() =>
import(`./systems/${systemConfig.login.component}.vue`)
)
</script>
<template>
<component :is="loginComponent" :config="systemConfig.login" />
</template>
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 构建命令
// 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 字段在运行时应用:
// 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、主题切换 |
| 多人协作冲突 | 低 | 配置文件集中管理,模块路由独立文件,减少冲突 |
五、后续扩展
- 国际化支持:配置文件中可扩展
locales字段,支持系统特定的翻译覆盖 - 模块懒加载:未来可考虑运行时动态加载模块(Module Federation)
- 版本管理:配置文件支持
version字段,用于产物版本控制 - CI/CD 集成:构建命令可直接接入 Jenkins/GitHub Actions,参数化构建不同系统