Files
workspace/code/fms/.codebuddy/plans/module-management-full-implementation_a1d841b2(未完成).md
T
2026-07-23 17:33:18 +08:00

292 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: module-management-full-implementation
overview: 基于新数据库结构.md和开发规范.md完整实现模块管理页面。左侧模块树+右侧7个子Tab(基本信息、字段定义、列表配置、编辑配置、查询配置、权限配置、多语言),子Tab操作按钮靠左。
todos:
- id: create-service
content: 创建 src/services/moduleManagement.js 服务层,封装 loadModuleTree、loadModuleConfig、saveModuleConfig、syncFields、typeFromSqlType 等方法
status: pending
- id: create-main-page
content: 重写 src/views/module-management/index.vue 主页面,实现左侧 FmsTree 模块树 + 右侧 a-tabs 动态Tab布局,集成数据加载与保存流程
status: pending
dependencies:
- create-service
- id: create-basic-panel
content: 使用 [skill:antdv-next] 创建 ModuleBasicPanel.vue 基本信息面板,表单编辑 b_module 字段,根据模块类型控制字段可见性
status: pending
dependencies:
- create-main-page
- id: create-fields-panel
content: 创建 ModuleFieldsPanel.vue 字段定义面板,FmsTable 展示字段列表,实现「同步字段」功能(调用 describeApi 合并视图列)
status: pending
dependencies:
- create-main-page
- id: create-list-edit-query-panels
content: 创建 ModuleListConfigPanel.vue、ModuleEditConfigPanel.vue、ModuleQueryConfigPanel.vue 三个配置面板,FmsTable 展示各自数据,操作按钮靠左
status: pending
dependencies:
- create-main-page
- id: create-group-manager
content: 创建 FieldGroupManager.vue 共用分组管理组件,弹窗内管理 b_module_field_group 树形分组增删改
status: pending
dependencies:
- create-list-edit-query-panels
- id: create-powers-i18n-panels
content: 创建 ModulePowersPanel.vue 权限配置面板和 ModuleI18nPanel.vue 多语言面板,FmsTable 管理 b_module_power 和 b_i18n 数据
status: pending
dependencies:
- create-main-page
---
## 用户需求
根据新数据库结构.md和开发规范.md,完整实现模块管理页面。当前模块管理页面只有一个空占位(`<el-button>`),需要构建完整的左侧模块树+右侧子Tab布局。
## 核心功能
### 主页面布局
- **左侧模块树**:以树形结构展示所有模块(directory/page/data),支持选中节点后在右侧加载详情
- **右侧详情区**:使用 `a-tabs` 展示子Tab,根据选中模块的 `b_module_type` 动态显示对应Tab
### 模块类型与Tab对应关系
| 模块类型 | 可用Tab |
| --- | --- |
| directory | 基本信息、权限配置、多语言 |
| page | 基本信息、权限配置、多语言 |
| data | 基本信息、字段定义、列表配置、编辑配置、查询配置、权限配置、多语言 |
### 各子Tab功能
1. **基本信息**:编辑 `b_module` 的核心字段(b_code、b_name、b_module_type、b_route、b_viewtable、b_savetable、b_keyfield、b_orderfield、b_parent_id、b_canmenu、b_canuse、b_xh),表单保存
2. **字段定义**:展示 `b_module_field` 列表,**不可手工增删**。提供「同步字段」按钮,调用 `describeApi` 获取 `b_viewtable` 的列结构,与已有字段合并(保留已有配置、追加新列、标记已删列为不可用)。支持编辑 `b_name`、`b_type`、`b_default_value`、`b_options`、`b_canuse`
3. **列表配置**:管理 `b_module_field_list`(字段列配置)和 `b_module_field_group`(多级表头分组)。表格展示列表配置行,支持新增/删除。分组管理弹窗支持树形分组增删改
4. **编辑配置**:管理 `b_module_field_edit`(编辑属性)和 `b_module_field_group`(编辑分组)。表格展示编辑配置行,支持新增/删除。共享分组管理组件
5. **查询配置**:管理 `b_module_field_query`,表格展示查询条件配置,支持新增/删除
6. **权限配置**:管理 `b_module_power`,表格展示操作权限(b_code、b_name),支持新增/删除
7. **多语言**:管理 `b_i18n`,表格展示翻译条目(b_key、b_locale、b_value),支持新增/删除
### 操作按钮排列
所有子Tab面板内,新增、删除、保存等操作按钮栏**靠左对齐**显示。
### 数据保存策略
- **主表 b_module**:选中模块后直接编辑表单并保存,新增模块先调用 `nextIdApi` 获取雪花ID
- **子表**(b_module_field/b_module_field_list等):新增行使用 `createTempId()` 生成临时负数ID,调用 `saveObjectApi` 统一保存变更
- **保存时**:使用 `diffRows()` 对比草稿与原始数据,通过 `tableChange()` 构建变更请求,多表变更一次提交到 `saveObjectApi`
## Tech Stack
- 前端框架:Vue 3(`<script setup>` SFCs)
- 状态管理:组件内部 ref/reactive(不引入额外 Pinia store)
- UI 组件库:antdv-next(自动导入)+ 项目封装组件(FmsTable、FmsTree、FmsSelect)
- 样式:SCSS scoped + CSS 变量主题(`--fms-*`)
- 数据获取:复用现有通用接口 `loadDataApi`、`saveObjectApi`、`nextIdApi`、`describeApi`
- 工具函数:`createTempId`(临时ID)、`diffRows`/`allocateTemporaryIds`/`remapForeignKeys`/`tableChange`/`hasChanges`(变更追踪)
## Implementation Approach
### 整体策略
采用**声明式数据驱动**模式:每个子Tab面板作为独立组件接收模块ID和完整配置数据,内部维护编辑态草稿(`cloneData`深拷贝),通过 `diffRows` 计算变更后交给父组件统一保存。
### 关键设计决策
1. **数据加载集中在 Service 层**:`moduleManagement.js` 封装 `loadModuleTree()`(加载树)、`loadModuleConfig(moduleId)`(加载单个模块的完整配置)、`saveModuleConfig(moduleId, changes)`(保存变更),各面板组件调用 Sem 方法获取和回存数据。
2. **字段同步采用合并策略**(与记忆 ID: 93228844 一致):调用 `describeApi(b_viewtable)` 获取视图列 → 按列名匹配已有 `b_module_field` → 视图中已存在的保留原配置不覆盖、新增列追加默认行、视图中不存在的已有字段标记 `b_canuse=0`。
3. **子Tab操作按钮左对齐**:每个面板组件内部在表格上方设置工具栏,使用 `justify-content: flex-start` 确保按钮靠左排列。
4. **分组管理复用**:列表配置和编辑配置共享 `b_module_field_group`,通过 `FieldGroupManager.vue` 组件统一管理分组树增删改。
5. **保存事务性**:所有变更通过 `saveObjectApi` 一次提交多表变更数组,后端在同一事务内执行,任何表失败整体回滚。
### Implementation Notes
- **b_id 全部字符串化**:后端返回的 bigint 在 `http.js` 拦截器中统一转为字符串,前端所有ID比较使用 `String()` 包裹
- **布尔字段为 int 0/1**:b_canuse、b_visible、b_sortable、b_required、b_readonly、b_disabled、b_canmenu 均使用 0/1
- **b_module_field 同步后不覆盖已有配置**:b_name、b_type、b_options 等由管理员手动维护的值在同步时保留
- **临时ID流转**:新增子表行 → `createTempId()` → 保存时 `allocateTemporaryIds()` 请求后端真实ID → 保存完成后 `loadAll` 重建草稿
## Architecture Design
```mermaid
flowchart TB
subgraph 主页面
A[index.vue<br/>左侧树 + 右侧Tab]
end
subgraph Service
S[moduleManagement.js<br/>loadModuleTree<br/>loadModuleConfig<br/>saveModuleConfig]
end
subgraph 组件
B1[ModuleBasicPanel<br/>基本信息表单]
B2[ModuleFieldsPanel<br/>字段定义表格+同步]
B3[ModuleListConfigPanel<br/>列表配置表格]
B4[ModuleEditConfigPanel<br/>编辑配置表格]
B5[ModuleQueryConfigPanel<br/>查询配置表格]
B6[ModulePowersPanel<br/>权限表格]
B7[ModuleI18nPanel<br/>多语言表格]
G[FieldGroupManager<br/>共用分组管理]
end
subgraph API
API1[loadDataApi]
API2[saveObjectApi]
API3[nextIdApi]
API4[describeApi]
end
A --> S
S --> API1
S --> API2
S --> API3
S --> API4
A --> B1
A --> B2
A --> B3
A --> B4
A --> B5
A --> B6
A --> B7
B3 --> G
B4 --> G
```
## Directory Structure
```
fms-vue/src/
├── services/
│ └── moduleManagement.js # [NEW] 模块管理服务层
│ # - loadModuleTree(): 加载所有模块并构建树形数据
│ # - loadModuleConfig(moduleId): 加载单个模块的完整配置
│ # (b_module + b_module_field + b_module_field_list
│ # + b_module_field_edit + b_module_field_query
│ # + b_module_field_group + b_module_power + b_i18n)
│ # - saveModuleConfig(moduleId, changes, oldData): 保存模块配置
│ # 对比草稿和原始数据,构建多表变更请求
│ # - syncFields(moduleId, viewTable): 同步字段
│ # 调用describeApi获取列结构并合并
│ # - typeFromSqlType(sqlType): SQL类型到b_type映射
├── views/
│ └── module-management/
│ ├── index.vue # [MODIFY] 主页面容器
│ │ # - 左侧 FmsTree 展示模块树(directory/page/data)
│ │ # - 右侧 a-tabs 根据 b_module_type 动态显示子Tab
│ │ # - 选中节点加载完整配置,传递给各子面板
│ │ # - 统一收集各面板变更并调用保存
│ └── components/
│ ├── ModuleBasicPanel.vue # [NEW] 基本信息面板
│ │ # - 表单编辑 b_module 核心字段
│ │ # - b_code/b_name/b_module_type/b_parent_id 必填
│ │ # - directory类型隐藏 route/viewtable/savetable
│ │ # - page类型必须填写 route,data类型必须填写 viewtable
│ │ # - 新增模块先调用 nextIdApi 获取ID
│ ├── ModuleFieldsPanel.vue # [NEW] 字段定义面板
│ │ # - FmsTable 展示 b_module_field 列表
│ │ # - 工具栏「同步字段」按钮 + 保存按钮(靠左)
│ │ # - 同步逻辑:describeApi获取列 → 合并已有字段
│ │ # - 不可手工新增/删除行,仅可编辑属性
│ ├── ModuleListConfigPanel.vue # [NEW] 列表配置面板
│ │ # - FmsTable 展示 b_module_field_list
│ │ # - 工具栏新增/删除/保存按钮(靠左)
│ │ # - 可选字段来自 b_module_field(b_canuse=1)
│ │ # - 分组列可打开 FieldGroupManager 弹窗
│ ├── ModuleEditConfigPanel.vue # [NEW] 编辑配置面板
│ │ # - FmsTable 展示 b_module_field_edit
│ │ # - 工具栏新增/删除/保存按钮(靠左)
│ │ # - 可选字段来自 b_module_field(b_canuse=1)
│ │ # - 分组列可打开 FieldGroupManager 弹窗
│ ├── ModuleQueryConfigPanel.vue # [NEW] 查询配置面板
│ │ # - FmsTable 展示 b_module_field_query
│ │ # - 工具栏新增/删除/保存按钮(靠左)
│ │ # - b_component和b_operator使用下拉选择
│ ├── ModulePowersPanel.vue # [NEW] 权限配置面板
│ │ # - FmsTable 展示 b_module_power
│ │ # - 工具栏新增/删除/保存按钮(靠左)
│ │ # - b_code 唯一校验
│ ├── ModuleI18nPanel.vue # [NEW] 多语言面板
│ │ # - FmsTable 展示 b_i18n
│ │ # - 工具栏新增/删除/保存按钮(靠左)
│ │ # - 支持 zh-CN/en-US 等语言切换筛选
│ └── FieldGroupManager.vue # [NEW] 共用分组管理组件
│ # - 弹窗内展示分组树(b_module_field_group)
│ # - 支持新增/编辑/删除分组节点
│ # - 被 ModuleListConfigPanel 和 ModuleEditConfigPanel 引用
```
## Key Code Structures
### moduleManagement.js 核心接口
```js
// 加载模块树(用于左侧树展示)
export async function loadModuleTree()
// 加载单个模块的完整配置(所有关联表数据)
export async function loadModuleConfig(moduleId)
// 返回: { module, fields, fieldList, fieldEdit, fieldQuery, groups, powers, i18n }
// 保存模块配置变更
export async function saveModuleConfig(moduleId, draftData, originalData)
// draftData 和 originalData 结构同 loadModuleConfig 返回值
// 内部使用 diffRows 对比各子表,构建 saveObjectApi 请求
// 同步字段:从 b_viewtable 拉取列结构,与已有字段合并
export async function syncFields(moduleId, viewTable, existingFields)
// SQL类型到 b_type 的映射
export function typeFromSqlType(sqlType)
// varchar/char/nvarchar → input, text/ntext → textarea
// int/bigint/decimal/numeric/float → number, money/smallmoney → money
// date → date, datetime/datetime2 → datetime, bit → switch
```
### 各面板组件统一 Props/Emits 模式
```js
// 所有面板组件遵循相同的接口约定
defineProps({
moduleId: { type: String, required: true }, // 当前模块ID
data: { type: Array, required: true }, // 面板对应的数据行数组
loading: { type: Boolean, default: false }, // 加载状态
})
const emit = defineEmits(['update']) // 数据变更时触发,传递新的行数组
```
### 数据流
```
index.vue 选中模块
→ loadModuleConfig(moduleId) 获取原始数据
→ cloneData 生成 draftData(编辑态草稿)
→ 各面板接收 draftData 对应部分,用户编辑后 emit('update', newRows)
→ index.vue 更新 draftData
→ 用户点击「保存全部」
→ saveModuleConfig(moduleId, draftData, originalData)
→ diffRows 对比各子表变更
→ allocateTemporaryIds 分配临时ID为真实ID
→ 构建 saveObjectApi 请求数组
→ 提交保存
→ 重新 loadModuleConfig 刷新原始数据
```
## Agent Extensions
### Skill
- **antdv-next**
- Purpose: 查询 antdv-next 组件库的 API 文档,确认 a-tree、a-tabs、a-form、a-modal、a-select、a-button、a-space 等组件的 props/events/slots 用法
- Expected outcome: 获取准确的组件属性定义和事件签名,确保模板中使用正确的 API
### SubAgent
- **code-explorer**
- Purpose: 在实现过程中需要快速搜索项目中的代码模式(如 FmsTable 使用方式、dataChanges.js 调用示例、现有表单校验模式等)时使用
- Expected outcome: 获得准确的现有代码引用,确保新代码风格一致