292 lines
16 KiB
Markdown
292 lines
16 KiB
Markdown
---
|
||
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: 获得准确的现有代码引用,确保新代码风格一致 |