206 lines
14 KiB
Markdown
206 lines
14 KiB
Markdown
---
|
||
name: module-management-page
|
||
overview: 基于新数据库结构与开发规范,从零重建 module-management 页面(替换当前占位页),并把路由 /system/metadata 改为 /system/module-management。页面以「左侧模块树 + 右侧多 Tab 配置」组织,覆盖 b_module 及其字段/分组/列表/编辑/查询/权限/多语言配置,复用现有通用接口与工具函数,不新增后端端点与服务文件。
|
||
design:
|
||
styleKeywords:
|
||
- Enterprise Admin
|
||
- Clean Professional
|
||
- Ant Design Vue
|
||
- Two-column Tree + Tabs
|
||
- Subtle Blue Accent
|
||
- Desktop-first
|
||
fontSystem:
|
||
fontFamily: PingFang SC, Microsoft YaHei
|
||
heading:
|
||
size: 16px
|
||
weight: 600
|
||
subheading:
|
||
size: 14px
|
||
weight: 500
|
||
body:
|
||
size: 13px
|
||
weight: 400
|
||
colorSystem:
|
||
primary:
|
||
- "#1677ff"
|
||
- "#4096ff"
|
||
- "#0958d9"
|
||
background:
|
||
- "#ffffff"
|
||
- "#f7f8fa"
|
||
- "#f0f5ff"
|
||
text:
|
||
- "#1f2329"
|
||
- "#8a8f99"
|
||
- "#ffffff"
|
||
functional:
|
||
- "#52c41a"
|
||
- "#ff4d4f"
|
||
- "#faad14"
|
||
- "#e5e7eb"
|
||
todos:
|
||
- id: update-route-menu
|
||
content: 修改 routes.js 与 AppSidebar.vue,将路由 /system/metadata 改为 /system/module-management(moduleCode 保留 m_metadata)
|
||
status: completed
|
||
- id: build-view-shell
|
||
content: 新建 index.vue 与 composables/useModuleManagement.js:左树右 Tabs 布局、草稿加载/保存编排、权限受控工具条
|
||
status: completed
|
||
dependencies:
|
||
- update-route-menu
|
||
- id: build-basic-tree
|
||
content: 实现 ModuleTreePanel 与 ModuleBasicInfoPanel:模块树增删改、基本信息表单与类型联动校验
|
||
status: completed
|
||
dependencies:
|
||
- build-view-shell
|
||
- id: build-field-group
|
||
content: 实现 ModuleFieldDefinitionPanel(describe 同步合并)与 ModuleGroupPanel(多级分组树)
|
||
status: completed
|
||
dependencies:
|
||
- build-view-shell
|
||
- id: build-list-edit-query
|
||
content: 实现 ModuleListPanel/ModuleEditPanel/ModuleQueryPanel,用 FmsTable 配置列表/编辑/查询场景
|
||
status: completed
|
||
dependencies:
|
||
- build-view-shell
|
||
- id: build-power-i18n
|
||
content: 实现 ModulePowerPanel 与 ModuleTranslationsPanel,维护操作权限与多语言文案
|
||
status: completed
|
||
dependencies:
|
||
- build-view-shell
|
||
- id: polish-verify
|
||
content: 用 [skill:antdv-next] 核对组件用法,补全 scoped scss 与空态,说明未执行构建/测试
|
||
status: completed
|
||
dependencies:
|
||
- build-basic-tree
|
||
- build-field-group
|
||
- build-list-edit-query
|
||
- build-power-i18n
|
||
---
|
||
|
||
## 用户需求
|
||
|
||
- 依据 `新数据库结构.md` 的 schema 从零重建「模块管理」页面(替换当前占位页 `index.vue`),覆盖 `b_module` 及其字段定义、字段分组、列表/编辑/查询配置、操作权限、多语言等完整配置能力。
|
||
- 路由由 `/system/metadata` 改为 `/system/module-management`(仅改路径与 `menuKey`,`moduleCode` 仍保留 `m_metadata` 以匹配数据库种子与权限)。
|
||
- 严格遵循既有设计决策:字段定义来自模块查询视图(经 `POST /data/describe` 同步,不可手工增删);子表新增行用前端本地临时负数 ID(`createTempId`),主表 `b_module` 保留 `nextIdApi` 取号;保存后重建草稿使临时 ID 被真实 ID 覆盖。
|
||
- 复用项目现有通用接口(`loadDataApi`/`saveObjectApi`/`nextIdApi`/`describeApi`)、`FmsTable`、antdv-next 组件,以及 `utils/dataChanges.js`、`utils/tempId.js`、`utils/i18n.js`,不新增后端端点与服务文件。
|
||
- 遵守开发规范:表格尽量用 `fms-table`,桌面端实现,scoped scss 复用现有 `--fms-*` token,不执行构建/测试。
|
||
|
||
## 核心功能
|
||
|
||
- 左侧模块树(目录/页面/数据三类,支持增删改与选中)。
|
||
- 右侧多 Tab:基本信息、字段定义(含视图同步)、字段分组、列表配置、编辑配置、查询配置、操作权限、多语言。
|
||
- 顶部工具条(保存/刷新)与权限受控按钮(create/update/delete 来自 `b_module_power`,sync 为同步字段)。
|
||
- 基于通用接口与工具函数的「按模块加载草稿 → 本地编辑 → 差异保存(整事务)」工作流。
|
||
|
||
## 技术栈
|
||
|
||
- 前端:Vue 3 `<script setup>` + Vite + Pinia;UI 组件库 **antdv-next**(项目已通过 `vite.config.js` 自动按需引入,禁止手动 import 已由 resolver 处理的组件);表格统一使用项目封装的 `FmsTable`。
|
||
- 后端:完全复用现有通用端点,不新增任何接口或服务文件。
|
||
- 状态/工具:`stores/permissions.js`(权限门控)、`utils/dataChanges.js`、`utils/tempId.js`、`utils/i18n.js`。
|
||
|
||
## 实施方法
|
||
|
||
整体采用「单一编排视图 + 子面板」架构:`ModuleManagementView`(`index.vue`)负责选中模块、加载全量草稿、保存编排;各 `components/*.vue` 面板只负责自身区块的展示与编辑,所有可变数据集中在视图层响应式 `draft` 中,保存时由编排层统一 `diffRows` + `saveObjectApi`。
|
||
|
||
### 数据编排(核心)
|
||
|
||
1. **加载草稿 `loadDraft(moduleId)`**:并发 `loadDataApi` 拉取该模块相关的 8 张表:`b_module`(按 id)、`b_module_field`、`b_module_field_group`、`b_module_field_list`、`b_module_field_edit`、`b_module_field_query`、`b_module_power`,以及 `b_i18n`(按 `module.`/字段键前缀过滤)。结果存入响应式 `draft`,并深拷贝一份 `snapshot` 供保存时差异比对。
|
||
2. **本地编辑**:面板直接 `push`/`splice`/`Object.assign` 修改 `draft` 中的数组与对象;子表新增行 `b_id = createTempId()`(负数字符串)。
|
||
3. **保存 `saveDraft()`**:
|
||
|
||
- 主表 `b_module` 新增:先 `nextIdApi()` 取真实 ID 写入 `draft.b_module.b_id`。
|
||
- 对每张表 `diffRows(draft[table], snapshot[table])` → `tableChange(table, diff)`,汇聚为 `requests[]`。
|
||
- 子表 insert 含临时负数 ID 时,调用 `allocateTemporaryIds([...所有子表 insert 行])` 由后端生成真实 ID 并就地替换;随后 `remapForeignKeys` 把 `b_field_id`/`b_group_id` 指向的临时 ID 同步映射到真实 ID。
|
||
- 单事务 `saveObjectApi(requests)`;成功后 `snapshot = cloneData(draft)`,临时 ID 已被真实 ID 覆盖。
|
||
|
||
4. **视图同步 `syncFields(module)`**:`describeApi(module.b_viewtable)` 返回列 `[{name,type,nullable,size}]`;按 `(b_module_id,b_field)` 合并——视图已有列保留原 `b_name/b_type/b_options/b_default_value` 不覆盖;视图新增列追加默认行(`createTempId`,`b_type` 由 SQL 类型映射:字符串→input、长文本→textarea、数值→number、金额→money、date→date、datetime→datetime、bit→switch);视图已删列保留配置但 `b_canuse=0`。该按钮受 `canPower('m_metadata','sync')` 门控,仅 `data` 且配置了 `b_viewtable` 时可用。
|
||
|
||
### 关键设计决策与权衡
|
||
|
||
- **集中草稿 + 差异保存**:复用现有 `dataChanges.js`,避免各面板各自拼请求,降低出错面;保存走 `saveobjt` 整事务,任一表失败全回滚,符合设计决策。
|
||
- **临时 ID 策略**:严格遵循记忆决策——子表用 `createTempId`,主表用 `nextIdApi`;FK 映射在保存前完成,杜绝脏引用。
|
||
- **FmsTable 复用**:列表/编辑/查询/权限/多语言等表格统一用 `FmsTable`,单元格编辑沿用 `TableDemo.vue` 的 `makeCellEditor` 模式(编辑行渲染控件、其余行纯文本),不重复实现表格能力,契合新规范。
|
||
- **约束校验前置**:`b_module_type` 与字段联动校验在表单层做(directory 不可配 route/viewtable/savetable;page 必配 route;data 不可菜单/不可 route 且必配 viewtable),保存前校验 `b_code` 正则 `^[a-z][a-z0-9_]{1,49},减少后端往返报错。
|
||
- **性能**:每模块仅加载自身数据,树节点选中才加载草稿;`describe` 仅在点击同步时调用;表格虚拟滚动(`FmsTable` 默认开启)支撑大数据量。
|
||
|
||
### 架构关系
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
View[ModuleManagementView index.vue] -->|load/save 编排| Draft[(响应式 draft + snapshot)]
|
||
View --> Tree[ModuleTreePanel]
|
||
View --> Tabs[Tab 区]
|
||
Tabs --> Basic[ModuleBasicInfoPanel]
|
||
Tabs --> Field[ModuleFieldDefinitionPanel 含 sync]
|
||
Tabs --> Group[ModuleGroupPanel]
|
||
Tabs --> List[ModuleListPanel]
|
||
Tabs --> Edit[ModuleEditPanel]
|
||
Tabs --> Query[ModuleQueryPanel]
|
||
Tabs --> Power[ModulePowerPanel]
|
||
Tabs --> I18n[ModuleTranslationsPanel]
|
||
Draft -.diffRows/tableChange.-> Save[saveObjectApi 单事务]
|
||
Field -.describeApi.-> Sync[视图列合并]
|
||
```
|
||
|
||
## 目录结构
|
||
|
||
仅修改 2 个文件、新建 1 个视图与 8 个面板组件(含 1 个编排 composable):
|
||
|
||
```
|
||
fms-vue/src/
|
||
├── router/routes.js # [MODIFY] path "/system/metadata"→"/system/module-management",
|
||
│ # name→system-module-management,meta.menuKey 同步,moduleCode 保留 "m_metadata"
|
||
├── layouts/components/AppSidebar.vue # [MODIFY] systemPages 的 key 改为 "/system/module-management"
|
||
└── views/module-management/
|
||
├── index.vue # [NEW] ModuleManagementView:左树+右 Tabs 布局、工具条、
|
||
│ # 草稿加载/保存编排、权限受控按钮(create/update/delete/sync)
|
||
├── composables/useModuleManagement.js # [NEW] 编排逻辑:loadDraft/saveDraft/syncFields、
|
||
│ # diffRows+tableChange+allocateTemporaryIds+remapForeignKeys、SQL 类型→b_type 映射
|
||
└── components/
|
||
├── ModuleTreePanel.vue # [NEW] 模块树(目录/页面/数据),选中/新增/删除,b_xh 排序
|
||
├── ModuleBasicInfoPanel.vue # [NEW] 基本信息表单:b_code/b_name/b_module_type/b_route/
|
||
│ # b_viewtable/b_savetable/b_keyfield/b_orderfield/b_canmenu/b_canuse/b_xh
|
||
│ # + 类型联动校验
|
||
├── ModuleFieldDefinitionPanel.vue # [NEW] 字段定义 FmsTable + 「同步字段」按钮(describe 合并)
|
||
├── ModuleGroupPanel.vue # [NEW] 字段分组树(b_module_field_group 自引用),列表/编辑共用
|
||
├── ModuleListPanel.vue # [NEW] 列表配置 FmsTable(b_module_field_list,引用 group)
|
||
├── ModuleEditPanel.vue # [NEW] 编辑配置 FmsTable(b_module_field_edit,required/readonly/disabled/group)
|
||
├── ModuleQueryPanel.vue # [NEW] 查询配置 FmsTable(b_module_field_query,component/operator)
|
||
├── ModulePowerPanel.vue # [NEW] 操作权限 FmsTable(b_module_power)
|
||
└── ModuleTranslationsPanel.vue # [NEW] 多语言 FmsTable(b_i18n,按 locale 分列编辑)
|
||
```
|
||
|
||
## 关键代码结构
|
||
|
||
- 编排 composable 暴露:`loadDraft(moduleId)`、`saveDraft()`、`syncFields()`、`draft`(响应式)、`currentModuleId`、`permissions`(canPower 结果);各面板通过 `props` 接收对应数组、`emits` 回传变更,避免跨面板直接耦合。
|
||
- `b_type` SQL 类型映射函数(放置于 composable):`mapSqlTypeToFieldType(typeName) → 'input'|'textarea'|'number'|'money'|'date'|'datetime'|'switch'`。
|
||
|
||
## 设计风格
|
||
|
||
企业级元数据管理后台,采用「左侧模块树 + 右侧多 Tab 配置」的经典后台布局,桌面端优先。视觉以 Ant Design Vue 设计语言为基底,主色沿用项目侧栏蓝 `#1677ff`,辅以 `--fms-*` 设计变量(边框 `#e5e7eb`、正文 `#1f2329`、次要文字 `#8a8f99`、表面 `#ffffff`/`#f7f8fa`)。整体克制、清晰、信息密度适中,重点突出当前选中模块与可编辑表格,hover/选中态用浅蓝底与蓝色描边强化。
|
||
|
||
## 页面结构(自上而下分区)
|
||
|
||
1. **顶栏工具条**:左侧显示当前模块名与 `b_code` 面包屑;右侧权限受控按钮——新增模块(create)、保存(update)、同步字段(sync)、删除(delete),按钮按 `m_metadata` 的 `b_module_power` 与 `canPower` 显隐禁用。
|
||
2. **主体双栏**:
|
||
|
||
- 左栏 `ModuleTreePanel`:模块树(目录可展开,页面/数据为叶子),顶部「新建目录/页面/数据」入口,节点 hover 显示删除。选中节点高亮蓝底。
|
||
- 右栏 Tab 区:基本信息 / 字段定义 / 字段分组 / 列表配置 / 编辑配置 / 查询配置 / 操作权限 / 多语言,共 8 个标签页,内容区统一白底卡片 + `FmsTable`。
|
||
|
||
3. **表单与表格**:基本信息用 antdv-next `Form`(标签右对齐、栅格两列);各配置 Tab 用 `FmsTable`,编辑行内联控件(Input/InputNumber/Select/Switch),非编辑行纯文本;分组树用 `FmsTree` 或 `Tree` 组件展示多级 `b_module_field_group`。
|
||
4. **空态**:未选中模块时主区展示引导空态(图标 + 「请选择或新建模块」),不显示报错。
|
||
|
||
## 交互与动效
|
||
|
||
- 树节点选中平滑高亮;Tab 切换保留各面板本地编辑(草稿集中在视图层,不随 Tab 卸载丢失)。
|
||
- 表格编辑行浅蓝底(`rgba(22,119,255,0.08)`),hover 行浅灰底;按钮、输入框 focus 蓝色描边过渡 0.2s。
|
||
- 保存成功 `message.success` 轻提示;删除/同步等有副作用操作使用 `Popconfirm` 二次确认。
|
||
- 响应式:固定双栏,左栏 260px 可随侧栏收起;右栏内容随容器宽度自适应,表格横向虚拟滚动。
|
||
|
||
## 可复用的智能体扩展
|
||
|
||
### Skill
|
||
|
||
- **antdv-next**
|
||
- 目的:在编写 `ModuleBasicInfoPanel` 表单、`FmsTable` 单元格编辑器、树与弹窗等 UI 时,查询 antdv-next 组件的 API、props/events/slots 与用法示例,确保组件用法正确。
|
||
- 预期结果:各面板正确使用 antdv-next 组件(Form/Select/Switch/Tree/Popconfirm/Tabs 等),避免属性误用;保证 UI 实现符合组件库规范且与项目自动引入配置兼容。 |