Files
rui-docs/frontend/design/2026-06-04-admin-ui-module-build-design.md
T
vifo 19de7e24ec docs: 迁移 spring-ai 通用文档到 rui-docs
从 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分模块打包设计
2026-06-04 09:34:03 +08:00

13 KiB
Raw Blame History

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 配置文件:

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

插件职责:

  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 确保未使用代码被移除

路由生成逻辑:

// 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、主题切换
多人协作冲突 配置文件集中管理,模块路由独立文件,减少冲突

五、后续扩展

  1. 国际化支持:配置文件中可扩展 locales 字段,支持系统特定的翻译覆盖
  2. 模块懒加载:未来可考虑运行时动态加载模块(Module Federation
  3. 版本管理:配置文件支持 version 字段,用于产物版本控制
  4. CI/CD 集成:构建命令可直接接入 Jenkins/GitHub Actions,参数化构建不同系统