- W2: 4 主题 (科技蓝/中国红/Notion 紫/暗夜黑) + LoginView + DashboardView + 询价管理 (InquiryList + InquiryDetail) - W4.1: 集成管理 - 应用列表 (OpenAppListView) - W4.2: 集成管理 - 审计日志 (AuditLogListView) + 菜单 label 补全 - W4.2: 菜单从后端拉 + 看板接真 API - W31: safeParseArray 防御 localStorage permissions 损坏 (运营后台白屏修复) 关联: Mac F002-W31-交接文档.md / F006-W4-交接文档.md / GIT-AUDIT-REPORT-2026-06-24.md 本地备份: ~/projects/_meta/f002-fix/admin-new-w4-*/
9.5 KiB
9.5 KiB
F006 新管理后台 - 架构原则
核心铁律:本项目在设计架构时,必须把"后续修改的灵活性、可配置性、先进性、前瞻性"放在第一位。 老的 renren-cloud-admin 之所以改不动,就是因为缺乏这 4 个性质。
1. 4 个核心原则
1.1 灵活性(Flexibility)
- 业务代码不耦合样式:每个 view 模板只关心数据流,样式全部从主题/布局组件继承
- 可插拔的目录约定:
src/modules/{模块名}/每个模块自带views/、api/、types/、components/,删除模块 = 删除文件夹 - 运行时配置:菜单、路由、权限都从后端拉,不在前端硬编码
1.2 可配置性(Configurability)
- 主题系统由配置驱动:新增主题 = 加 22 个 CSS 变量 + ThemePicker 加一个按钮,不改业务代码
- 菜单从后端配置:管理员可以在系统里改菜单,前端不用动
- 权限从后端配置:按钮级别权限 =
v-permission="'sys:user:add'",不写死在组件里 - 页面配置化:列表页的列、搜索项、筛选条件都在 meta 配置里,不改代码就能加列
1.3 先进性(State of the Art)
- Vue 3.4 Composition API +
<script setup>(不混用 Options API) - Pinia(不混用 Vuex)
- TypeScript 严格模式(
strict: true) - Vite 5+(不混用 Webpack/Vue CLI)
- Element Plus 2.4+(用新主题系统,不覆写内部 CSS)
- SCSS Modules(组件级样式隔离,不全局污染)
1.4 前瞻性(Future-proof)
- 预留微前端入口:用 Vite Module Federation 或 qiankun,后期可以拆出独立模块
- 预留 i18n 接口:组件文案都走
t('key'),即使现在只有中文 - 预留暗色模式:主题系统已经是 4 套,加第 5 套(比如企业定制色)只改 22 个变量
- 预留 OpenAPI 集成:api 层用类型化客户端,后期后端换 schema 前端零改动
- 预留移动端:布局组件按响应式写,后期加移动端只需要换 layout
2. 目录结构(按"修改灵活性"优化)
admin_new/
├── ARCHITECTURE.md # 本文档(架构原则,所有开发必读)
├── .env # 环境变量(API 地址、开关)
├── .env.development
├── .env.production
├── package.json
├── vite.config.ts # 构建配置
├── tsconfig.json
├── index.html
├── public/
├── src/
│ ├── main.ts # 启动入口(主题恢复 + 路由 + store + UI 库)
│ ├── App.vue # 根组件(只决定 layout 策略)
│ │
│ ├── theme/ # 主题系统(独立子模块,可整体替换)
│ │ ├── tokens.scss # 22 个 CSS 变量(主题无关部分)
│ │ ├── themes.scss # 4 套主题(主题相关部分)
│ │ ├── presets.ts # 主题选项配置(新增主题只改这里)
│ │ └── README.md # 主题系统使用说明
│ │
│ ├── layout/ # 布局组件(顶栏 + 侧边栏 + 内容区)
│ │ ├── AppLayout.vue # 主布局
│ │ ├── TopBar.vue # 顶栏
│ │ ├── SideBar.vue # 侧边栏
│ │ ├── ThemePicker.vue # 主题切换器
│ │ └── UserMenu.vue # 用户菜单
│ │
│ ├── router/
│ │ ├── index.ts # 路由配置
│ │ ├── routes.ts # 静态路由(从后端拉的也注入这里)
│ │ └── guards.ts # 路由守卫
│ │
│ ├── stores/ # Pinia 状态管理
│ │ ├── user.ts # 用户 + token
│ │ ├── theme.ts # 当前主题
│ │ ├── menu.ts # 菜单(从后端拉)
│ │ └── permission.ts # 权限(v-permission 用)
│ │
│ ├── api/ # API 层(所有 HTTP 请求)
│ │ ├── request.ts # axios 封装(拦截器 + token 注入)
│ │ ├── auth.ts # 登录/登出
│ │ ├── menu.ts # 菜单 + 权限
│ │ └── ...
│ │
│ ├── modules/ # 业务模块(每个模块独立,可整体删除)
│ │ ├── dashboard/ # 数据看板
│ │ │ ├── DashboardView.vue
│ │ │ ├── api.ts
│ │ │ ├── types.ts
│ │ │ └── components/
│ │ ├── inquiry/ # 询价管理
│ │ ├── order/ # 订单管理
│ │ ├── supplier/ # 供应商
│ │ ├── user/ # 用户/角色
│ │ └── system/ # 系统设置
│ │
│ ├── components/ # 全局通用组件(跨模块)
│ │ ├── DataTable/ # 通用列表(分页 + 搜索 + 列配置)
│ │ │ ├── DataTable.vue
│ │ │ ├── types.ts # 列配置类型
│ │ │ └── README.md
│ │ ├── StatusTag/ # 状态徽章
│ │ ├── SearchForm/ # 搜索表单
│ │ └── PageContainer/ # 页面容器(统一 padding + 面包屑)
│ │
│ ├── composables/ # Vue 3 组合式 API(可复用逻辑)
│ │ ├── useTable.ts # 列表逻辑(分页 + 搜索 + 加载)
│ │ ├── usePermission.ts # 权限判断
│ │ └── useDict.ts # 字典查询
│ │
│ ├── directives/ # 全局指令
│ │ ├── permission.ts # v-permission
│ │ └── copy.ts # v-copy
│ │
│ ├── utils/ # 工具函数
│ │ ├── auth.ts # token 存储
│ │ ├── format.ts # 格式化
│ │ └── request.ts # 旧兼容(逐步废弃)
│ │
│ ├── styles/ # 全局样式
│ │ ├── reset.scss
│ │ └── global.scss
│ │
│ ├── icons/ # 图标(按需引入)
│ │ └── index.ts
│ │
│ ├── types/ # 全局类型定义
│ │ ├── api.ts # 通用 API 响应类型
│ │ └── global.d.ts
│ │
│ └── env.d.ts
└── Dockerfile # nginx 镜像
3. 关键架构决策(为什么这么做)
3.1 为什么用 src/modules/ 而不是 src/views/
- 修改灵活:删除一个模块 = 删除一个文件夹,不会污染其他模块
- 团队协作:不同人负责不同模块,merge 冲突少
- 微前端准备:后期可以拆出独立 module,用 qiankun 加载
3.2 为什么菜单从后端拉
- 配置灵活:管理员可以在系统里改菜单,不用发版
- 多租户:不同租户看不同菜单
- 角色权限:菜单本身就是权限的载体,后端管控最准确
3.3 为什么主题系统独立成 src/theme/
- 整体替换:后期要换主题方案(比如用 styled-components),只改
theme/文件夹 - 新增主题 = 加 22 个变量 + 1 个 button,不碰业务
- 可被 design token 工具读取:后期对接 Figma Tokens,只导出
themes.scss
3.4 为什么 DataTable 通用化
- 列表页占 60% 工作量,通用化能省一半时间
- 列配置化:新增列表 = 配 columns,不写模板
- 统一交互:所有列表分页/筛选/排序行为一致,降低学习成本
3.5 为什么用 composables 而不是 mixins
- 类型友好:TypeScript 推断更准
- 逻辑复用:同一逻辑可在多个组件复用,不污染 options
- tree-shaking 友好:只引入用到的
3.6 为什么用 v-permission 指令而不是组件
- 声明式:
<button v-permission="'sys:user:add'">比<Permission code="sys:user:add">更直观 - 可扩展:支持 hide / disable / function 三种模式
- 性能好:编译时确定,无运行时组件嵌套
4. 命名规范(避免后期混乱)
4.1 文件命名
- 组件:PascalCase (
UserMenu.vue) - 工具/脚本:camelCase (
auth.ts/format.ts) - 样式:kebab-case (
user-menu.scss) - 常量:UPPER_SNAKE_CASE (
MAX_FILE_SIZE)
4.2 CSS 变量
- 主题相关:加
--brand/--bg-soft等 - 主题无关:加
--radius/--shadow等 - 模块私有:加
--module-前缀
4.3 Pinia store
- 名:模块名,如
useUserStore - 状态:
xxx(如token,profile) - 动作:
xxx(如login,logout,fetchMenu)
5. 测试策略(后期可加,本期不做)
- 单元测试:Vitest + Vue Test Utils(测试 composables 和工具函数)
- E2E 测试:Playwright(测关键流程:登录 → 进看板 → 切换主题)
- 视觉回归:Chromatic / Percy(主题切换不能破坏布局)
6. CI/CD 策略(后期可加)
- PR 必须通过 ESLint + TypeScript 类型检查
- 自动跑 build,失败禁止 merge
- 每次发版生成 changelog
7. 演进路线(避免后期推倒重来)
- 当前:模块化 + 主题系统 + 4 套主题
- 3 个月内:加入 E2E 测试 + 性能监控
- 6 个月内:支持微前端拆分(独立 module 可独立部署)
- 12 个月内:加入低代码能力(列表列配置化 → 可视化配置)
所有开发必须遵守本文件。 任何架构变更必须先更新本文件,再改代码。