20260723173317

This commit is contained in:
oneao committed 2026-07-23 17:33:18 +08:00
1 parent 59b3ccfb1c
commit 5f73b54802
33 files changed
+3064 -2108

No files matched your search

@@ -0,0 +1,183 @@
---
name: module-management-full-implementation
overview: 基于新数据库结构.md和开发规范.md完整实现模块管理页面。左侧模块树+右侧7个子Tab,子Tab操作按钮靠左。不创建独立的service文件,数据加载/保存逻辑直接写在index.vue中。
todos:
- id: create-main-page
content: 重写 index.vue 主页面:左侧 a-tree 模块树 + 右侧 a-tabs 布局,编写全部数据加载/保存逻辑(loadDataApi、saveObjectApi、diff、typeFromSqlType)
status: completed
- id: create-basic-panel
content: 使用 [skill:antdv-next] 创建 ModuleBasicPanel.vue 基本信息表单,根据模块类型控制字段可见性,支持新增和编辑
status: completed
dependencies:
- create-main-page
- id: create-fields-panel
content: 创建 ModuleFieldsPanel.vue 字段定义面板,FmsTable 展示字段列表,实现「同步字段」功能,操作按钮靠左
status: completed
dependencies:
- create-main-page
- id: create-list-edit-query-panels
content: 创建 ModuleListConfigPanel.vue、ModuleEditConfigPanel.vue、ModuleQueryConfigPanel.vue 三个配置面板,FmsTable 展示数据,操作按钮靠左
status: completed
dependencies:
- create-main-page
- id: create-group-manager
content: 创建 FieldGroupManager.vue 共用分组管理弹窗,a-modal + a-tree 管理分组树增删改
status: completed
dependencies:
- create-list-edit-query-panels
- id: create-powers-i18n-panels
content: 创建 ModulePowersPanel.vue 权限配置面板和 ModuleI18nPanel.vue 多语言面板,FmsTable 管理数据,操作按钮靠左
status: completed
dependencies:
- create-main-page
---
## 用户需求
根据新数据库结构.md和开发规范.md,完整实现模块管理页面。当前页面是空占位,需要构建左侧模块树+右侧子Tab布局。
## 核心功能
### 主页面布局
- 左侧:使用 `a-tree` 展示模块树(directory/page/data 三级),选中节点加载详情
- 右侧:使用 `a-tabs` 展示子Tab,根据选中模块的 `b_module_type` 动态显示对应Tab
### 模块类型与Tab对应
| 模块类型 | 可见Tab |
| --- | --- |
| directory | 基本信息、权限配置、多语言 |
| page | 基本信息、权限配置、多语言 |
| data | 基本信息、字段定义、列表配置、编辑配置、查询配置、权限配置、多语言 |
### 各子Tab功能
1. **基本信息**:`a-form` 编辑 `b_module` 核心字段(b_code、b_name、b_module_type、b_parent_id、b_route、b_viewtable、b_savetable、b_keyfield、b_orderfield、b_canmenu、b_canuse、b_xh),根据模块类型控制字段可见性。新增模块先调 `nextIdApi`
2. **字段定义**:`FmsTable` 展示 `b_module_field`,不可手工增删行。提供「同步字段」按钮调用 `describeApi` 获取 `b_viewtable` 列结构并与已有字段合并(保留已有配置、追加新列、标记已删列为不可用)。可编辑 `b_name`、`b_type`、`b_default_value`、`b_options`、`b_canuse`
3. **列表配置**:`FmsTable` 展示 `b_module_field_list`,支持新增/删除行。可选字段来自 `b_module_field`(b_canuse=1)。`FieldGroupManager` 弹窗管理 `b_module_field_group` 分组树
4. **编辑配置**:`FmsTable` 展示 `b_module_field_edit`,支持新增/删除行。同样通过 `FieldGroupManager` 管理分组
5. **查询配置**:`FmsTable` 展示 `b_module_field_query`(b_component、b_operator 下拉选择),支持新增/删除行
6. **权限配置**:`FmsTable` 展示 `b_module_power`(b_code、b_name),支持新增/删除行
7. **多语言**:`FmsTable` 展示 `b_i18n`(b_key、b_locale、b_value),支持新增/删除行
### 操作按钮排列
所有子Tab面板内,新增、删除、保存等操作按钮**靠左对齐**(`justify-content: flex-start`)
### 数据架构(不创建独立 service 文件)
- `index.vue` 承担全部数据职责:加载模块树、加载完整配置、维护草稿、对比diff、调用 `saveObjectApi`
- 子组件只通过 `props` 接收数据,通过 `emit('update', newRows)` 上报变更
- `index.vue` 保存流程:`diffRows(draft, original)` → `allocateTemporaryIds` → `saveObjectApi`
## 技术方案
### 实现策略
**数据流集中管理**:`index.vue` 作为数据中枢,直接调用 `loadDataApi`、`saveObjectApi`、`nextIdApi`、`describeApi` 等通用接口。所有子组件是无状态的展示/编辑组件,仅通过 props/emit 与父组件通信。
### 数据流
```
index.vue 选中模块
→ loadDataApi 加载 b_module + 各子表(Promise.all)
→ cloneData 生成 originals(原始快照)和 drafts(编辑草稿)
→ 各子组件接收 drafts 对应部分,用户编辑后 emit('update', newRows)
→ index.vue 更新对应 draft
→ 用户点击「保存」
→ 遍历各子表 diffRows(draft, original)
→ allocateTemporaryIds 分配临时ID
→ 构建 saveObjectApi 请求数组
→ 提交保存 → 重新加载刷新 originals
```
### 关键设计决策
1. **无独立 service 文件**:所有 `loadDataApi`/`saveObjectApi` 调用直接写在 `index.vue` 的 `<script setup>` 中
2. **组件纯展示**:所有子组件只负责展示和编辑,不调用 API
3. **SQL 类型映射**(字段同步用):`typeFromSqlType()` 作为 `index.vue` 内的普通函数
4. **分组管理复用**:`FieldGroupManager.vue` 接收 groups 数组并通过 emit 返回变更,不直接操作 API
5. **b_module_field 不手工增删**:同步通过 `describeApi`,字段定义面板中只有编辑功能无新增/删除按钮
### 实现要点
- b_id 全部使用 `String()` 包裹进行比对
- 布尔字段为 int 0/1(b_canuse、b_visible、b_sortable、b_required、b_readonly、b_disabled、b_canmenu)
- 子表新增行用 `createTempId()`,保存前 `allocateTemporaryIds()` 换真实ID
- 主表新增模块用 `nextIdApi`
- 操作按钮在子Tab面板内靠左(`a-space` 或 flex 布局 `justify-content: flex-start`)
- 样式使用 SCSS scoped,遵循 `--fms-*` CSS 变量主题
## 目录结构
```
fms-vue/src/views/module-management/
├── index.vue # [MODIFY] 主页面
│ - 左侧 a-tree 模块树,右侧 a-tabs
│ - 全部数据加载/保存逻辑(loadDataApi、saveObjectApi、nextIdApi、describeApi)
│ - 维护 drafts 和 originals,构建 diff 和 saveObjectApi 请求
│ - typeFromSqlType() 字段类型映射函数
│ - 选中节点变更、Tab切换、保存按钮事件处理
└── components/
├── ModuleBasicPanel.vue # [NEW] 基本信息表单
│ - a-form 编辑 b_module 字段
│ - props: moduleId, data(object), loading
│ - emit: update(modifiedData)
│ - 根据 b_module_type 控制字段可见性
├── ModuleFieldsPanel.vue # [NEW] 字段定义表格
│ - FmsTable 展示 b_module_field 列表
│ - 工具栏「同步字段」+「保存」按钮靠左
│ - props: moduleId, fields(array), viewTable, loading
│ - emit: update(newFields), sync(viewTable)
│ - 不可新增/删除行,可编辑 b_name/b_type/b_default_value/b_options/b_canuse
├── ModuleListConfigPanel.vue # [NEW] 列表配置表格
│ - FmsTable 展示 b_module_field_list
│ - 工具栏新增/删除/保存按钮靠左
│ - props: moduleId, listConfig(array), fields(array), groups(array), loading
│ - emit: update(newListConfig), openGroupManager
│ - 字段选择器展示可用字段,分组列可点击打开分组管理
├── ModuleEditConfigPanel.vue # [NEW] 编辑配置表格
│ - FmsTable 展示 b_module_field_edit
│ - 工具栏新增/删除/保存按钮靠左
│ - props: moduleId, editConfig(array), fields(array), groups(array), loading
│ - emit: update(newEditConfig), openGroupManager
├── ModuleQueryConfigPanel.vue # [NEW] 查询配置表格
│ - FmsTable 展示 b_module_field_query
│ - 工具栏新增/删除/保存按钮靠左
│ - props: moduleId, queryConfig(array), fields(array), loading
│ - emit: update(newQueryConfig)
│ - b_component、b_operator 使用下拉选择
├── ModulePowersPanel.vue # [NEW] 权限配置表格
│ - FmsTable 展示 b_module_power
│ - 工具栏新增/删除/保存按钮靠左
│ - props: moduleId, powers(array), loading
│ - emit: update(newPowers)
├── ModuleI18nPanel.vue # [NEW] 多语言表格
│ - FmsTable 展示 b_i18n
│ - 工具栏新增/删除/保存按钮靠左
│ - props: moduleId, i18n(array), loading
│ - emit: update(newI18n)
│ - 支持按 b_locale 筛选
└── FieldGroupManager.vue # [NEW] 共用分组管理弹窗
- a-modal 内含 a-tree 展示分组树
- 支持新增/编辑/删除分组节点
- props: visible, groups(array), moduleId
- emit: update:visible, update(newGroups)
- 被 ModuleListConfigPanel 和 ModuleEditConfigPanel 引用
```
## 使用的扩展
### Skill
- **antdv-next**
- 目的:查询 a-tree、a-tabs、a-form、a-form-item、a-modal、a-select、a-input、a-input-number、a-switch、a-button、a-space、a-empty 等组件的 API 文档
- 预期结果:获取准确的 props/events/slots 用法,确保模板中 API 使用正确
### SubAgent
- **code-explorer**
- 目的:在实现过程中快速查找项目中 FmsTable 的 columns 配置模式、dataChanges.js 的 diffRows 调用方式、现有表单校验示例等
- 预期结果:获得准确的现有代码引用,确保新代码风格与项目一致
@@ -0,0 +1,292 @@
---
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: 获得准确的现有代码引用,确保新代码风格一致
@@ -0,0 +1,206 @@
---
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 实现符合组件库规范且与项目自动引入配置兼容。
@@ -0,0 +1,123 @@
---
name: module-management-subtable-layout
overview: 修复 module-management 模块管理页子表(字段/列表/表单/查询/权限/翻译)的布局:1) 让子表区域通过 flex:1 正确填满可用高度(表格宽高 100%);2) 缩小各子表列宽,避免列沾满整个页面。
todos:
- id: fix-container-height
content: 修复 index.vue 容器高度链,使子表区可纵向撑满
status: completed
- id: constrain-table-width
content: 调整 MetadataTablePanel 约束表格宽度跟随内容,避免列拉伸占满
status: completed
dependencies:
- fix-container-height
- id: shrink-column-widths
content: 缩小字段/列表/表单/权限/翻译/查询六个子表面板列宽至紧凑值
status: completed
dependencies:
- constrain-table-width
---
## 用户需求
module-management(模块配置)页面中涉及子表的地方布局不合理,需要修正:
1. 子表区域通过外层 `flex:1` 撑满可用高度,表格宽高 `100%`。
2. 各子表列宽缩小、不要过大,且不要拉伸占满整个页面。
## 产品概述
优化模块管理页各子表面板(字段定义、列表配置、表单配置、查询配置、操作权限、翻译)的布局与列宽。这些面板共用 `MetadataTablePanel` + 共享组件 `FmsTable`(基于 stk-table-vue),目标是让子表纵向铺满、列宽紧凑、不拉伸占满整页。基本信息(表单)不在本次范围。
## 核心功能
- 子表纵向填满:修复 index.vue 容器高度链,使表格区随内容区高度自适应铺满。
- 列宽紧凑化:缩小各子表列定义的 `width` 数值,避免列过宽。
- 表格不拉伸:确保列宽合计小于页面时,表格宽度跟随内容,不自动拉伸占满整页。
## 技术栈
- 前端:Vue 3 `<script setup>` + Vite + antdv-next + SCSS(scoped)
- 表格:共享组件 `FmsTable`(封装 `stk-table-vue` 的 `StkTable`),子表统一通过 `MetadataTablePanel` 使用
- 仅调整样式与列宽数值,不新增/修改任何后端接口或业务逻辑
## 实施方案
### 1. 高度链修复(主因)
当前 `.metadata-page` 是 grid,但只定义了 `grid-template-columns`,未定义行,导致 `.workspace` 高度塌缩为内容高度;其下游 `.config-tabs` 的 `height: calc(100% - 58px)` 与 `MetadataTablePanel` 的 `height:100%` / `.table-body` 的 `flex:1` 全部失效,表格区拿不到高度。
修复方式(仅 CSS):
- `.metadata-page` 增加 `grid-template-rows: minmax(0, 1fr)`,让第二列行撑满。
- `.workspace` 改为 `display:flex; flex-direction:column; height:100%`,使 header + tabs 纵向堆叠并铺满。
- `.workspace-spin` 及其 `.ant-spin-container`(deep)改为 `display:flex; flex-direction:column; flex:1; min-height:0`。
- `.config-tabs` 用 `display:flex; flex-direction:column; flex:1; min-height:0` 替代 `height: calc(100% - 58px)`。
- `MetadataTablePanel` 结构已正确(`.metadata-table-panel` flex 列 + 无 height prop 时 `height:100%`;`.table-body` `flex:1`;`FmsTable` 已是 `width/height:100%`),高度链补通后即可纵向铺满。
### 2. 宽度不拉伸约束
`FmsTable` 是共享组件(还被 authorization-management / i18n-management / dashboard 使用),**不可全局改宽**。在 `MetadataTablePanel` 内以 scoped `:deep` 选择器约束表格宽度跟随内容,确保列宽合计小于页面时不被拉伸占满:
```
.table-body {
flex: 1;
min-height: 0;
:deep(.fms-table) {
width: fit-content;
max-width: 100%;
height: 100%;
}
}
```
### 3. 列宽紧凑化
在各子表面板中把列 `width` 改为紧凑值,规则:顺序/开关类 `60–80`、短文本(编码/类型/字段名/标题/语言)`120–150`、中长文本(名称/默认值/提示/多语言键)`160–220`、长文本(说明/JSON/翻译内容)`220–300`。示例目标值:
- `ModuleFieldsPanel`:字段 130 / 默认名称 150 / 多语言键 200 / 字段类型 110 / 字典编码 130 / 默认值 150 / 说明 200 / 启用 64
- `ModuleListPanel`:节点类型 90 / 关联字段 170 / 上级分组 140 / 分组·列标题 160 / 标题多语言键 200 / 显示 64 / 顺序 70 / 列宽 70 / 显示类型 110 / 排序 64 / 表内编辑 80
- `ModuleEditPanel`:分组表(分组编码 140 / 默认标题 160 / 标题多语言键 200 / 顺序 70 / 启用 64);编辑表(字段 170 / 编辑器 100 / 表单分组 140 / 输入提示 160 / 必填·只读·禁用·Form 各 64 / 顺序 70 / 栅格 70 / 编辑器JSON 240)
- `ModulePowersPanel`:操作编码 140 / 默认名称 160 / 多语言键 220 / 顺序 70 / 启用 64
- `ModuleTranslationsPanel`:多语言键 260 / 语言 130 / 翻译内容 300
- `ModuleQueryPanel`:字段 180 / 查询组件 120 / 操作符 90 / 默认值 200 / 顺序 70 / 启用 64
## 实施注意
- 仅改样式与列 `width` 数值,不改动保存/同步/临时 ID/校验等任何业务逻辑,保留用户未提交改动。
- 不修改 `FmsTable.vue` 全局宽度,避免影响其他管理页。
- 浏览器核对(不自行 build):切换字段/列表/表单/查询/权限/翻译各 Tab 时表格纵向铺满、列不拉伸占满、必要时出现横向滚动而非撑满整页。
- 按开发规范,完成后不执行构建/测试,交付时说明未执行。
## 架构设计
布局容器链(自上而下高度传递):
```mermaid
graph TD
A[.metadata-page grid 行=1fr] --> B[.workspace flex column]
B --> C[.workspace-spin flex:1]
C --> D[header.workspace-header 固定]
C --> E[.config-tabs flex:1]
E --> F[.ant-tabs-tabpane height:100%]
F --> G[MetadataTablePanel height:100% flex column]
G --> H[.panel-toolbar 固定]
G --> I[.table-body flex:1]
I --> J[FmsTable width:fit-content height:100%]
```
## 目录结构
本次仅修改前端 module-management 下的样式与列宽,不影响后端与其他页面。
```
fms-vue/src/views/module-management/
├── index.vue # [MODIFY] 修复容器高度链:.metadata-page 增加 grid-template-rows;.workspace 改 flex column;.workspace-spin 与 .config-tabs 用 flex:1 替代 calc,确保子表纵向铺满
└── components/
├── MetadataTablePanel.vue # [MODIFY] 以 scoped :deep(.fms-table) 约束表格 width:fit-content / max-width:100% / height:100%,防止列拉伸占满整页
├── ModuleFieldsPanel.vue # [MODIFY] 缩小字段定义各列 width 至紧凑值
├── ModuleListPanel.vue # [MODIFY] 缩小列表列/字段节点各列 width 至紧凑值
├── ModuleEditPanel.vue # [MODIFY] 缩小表单分组表与编辑字段表各列 width 至紧凑值
├── ModulePowersPanel.vue # [MODIFY] 缩小操作权限各列 width 至紧凑值
├── ModuleTranslationsPanel.vue # [MODIFY] 缩小翻译各列 width 至紧凑值
└── ModuleQueryPanel.vue # [MODIFY] 缩小查询条件各列 width 至紧凑值
```
@@ -0,0 +1,125 @@
---
name: 重构元数据数据库结构
overview: 按 新数据库结构.md 重写 fms-api/config/migrations/000_reset_metadata.sql,使表结构完全符合目标 schema;b_user 表保持不变,迁移脚本末尾仅种子 m_system 与 m_metadata。
todos:
- id: rewrite-b-module-field
content: 重写 b_module_field:b_type/b_default_value/b_options 列与约束,删冗余列
status: pending
- id: add-b-module-field-group
content: 新增 b_module_field_group 表(含自引用树),取代 b_module_field_edit_group
status: pending
- id: refactor-b-module-field-list
content: 重构 b_module_field_list:引用分组表,移除 b_parent_id/b_kind/display/canedit
status: pending
dependencies:
- add-b-module-field-group
- id: refactor-b-module-field-edit
content: 重构 b_module_field_edit:引用分组表,精简编辑器列,统一 b_xh
status: pending
dependencies:
- add-b-module-field-group
- id: update-seed-data
content: 收敛种子数据仅保留 m_system 与 m_metadata
status: pending
dependencies:
- rewrite-b-module-field
- refactor-b-module-field-list
- refactor-b-module-field-edit
---
## 用户需求
根据 `新数据库结构.md` 重构元数据数据库结构,使表结构完全符合目标 schema;`b_user` 表保持不变;迁移脚本末尾的种子数据仅保留"系统管理"目录与"模块管理"模块,移除多语言管理与用户授权相关全部数据。
## 产品概述
本次为纯数据库结构重构,不涉及前后端功能页面。成果为重写 `fms-api/config/migrations/000_reset_metadata.sql` 迁移脚本,使其中所有元数据表(除 b_user 外)与目标设计文档逐一对应,并收敛种子数据。
## 核心改动
- `b_module_field`:重命名列并采用新控件类型集合,删除冗余列。
- `b_module_field_list`:移除自包含树(b_parent_id/b_kind/b_display_type/b_canedit),改为引用统一分组表 `b_module_field_group`。
- 新增 `b_module_field_group`:统一承载列表多级表头与编辑分组的布局分组树(取代旧的 `b_module_field_edit_group`)。
- `b_module_field_edit`:剔除编辑器细节列,改为引用分组表的 `b_group_id`,统一显示顺序列为 `b_xh`。
- `b_module_field_query`、`b_module_power`、`b_user_module`、`b_user_power`、`b_i18n` 已符合目标,无需改动。
- 种子数据仅保留 `m_system` 目录与 `m_metadata` 模块及其操作权限、管理员授权;删除 `m_i18n`、`m_authorization` 全部相关行。
## 技术栈
- 目标数据库:SQL Server(Druid 连接池,按机构独立库)。
- 变更载体:单文件 SQL 迁移脚本 `fms-api/config/migrations/000_reset_metadata.sql`,属于"RESET"脚本(执行前删除除 b_user 外的全部用户表、保留视图,再重建并插入种子)。
- 不涉及后端 Java / 前端 Vue 代码:已 grep 确认旧列名仅在迁移脚本内出现,通用接口为表/列透传,模块管理前端当前为空占位页。
## 实施方法
完全重写 `000_reset_metadata.sql` 的建表与种子部分,使每个元数据表逐字段对齐 `新数据库结构.md`。脚本开头的"删除旧表 + 保留视图 + 重置管理员会话上下文"逻辑保持不变(它依赖 b_user,符合"b_user 不改"约束)。
### 关键修改点(按目标文档)
**1. b_module_field(混合旧列拆分)**
- `b_field_type varchar(30) NOT NULL` → 重命名为 `b_type`,CHECK 改为 `('input','textarea','number','money','date','datetime','switch','select')`。
- `b_value nvarchar(500) NULL` → 重命名为 `b_default_value nvarchar(500) NULL`。
- `b_dict_code varchar(100) NULL` → 重命名为 `b_options nvarchar(max) NULL`,新增 `CHECK (b_options IS NULL OR ISJSON(b_options) = 1)`。
- 删除 `b_remark`、`b_inputdatetime` 两列。
- 保留 `b_id/b_module_id/b_field/b_name/b_i18n/b_canuse` 及外键、唯一索引 `(b_module_id, b_field)`、索引 `(b_module_id, b_canuse, b_id)`。
**2. b_module_field_group(新增,取代 b_module_field_edit_group)**
- 列:`b_id bigint NOT NULL`、`b_module_id bigint NOT NULL`、`b_parent_id bigint NULL`、`b_title nvarchar(100) NOT NULL`、`b_i18n varchar(150) NULL`、`b_xh int NOT NULL DEFAULT 0`、`b_canuse int NOT NULL DEFAULT 1`。
- 外键:`FK..._module` → b_module(b_id);`FK..._parent` → 自引用 b_module_field_group(b_id)。
- 约束:`CK..._canuse CHECK (b_canuse IN (0,1))`;索引 `IX (b_module_id, b_canuse, b_xh, b_id)`。
- 注意:旧的 `b_code` 列不再需要(被 b_id 稳定关联键取代),不保留。
**3. b_module_field_list(引用统一分组表)**
- 删除 `b_parent_id`、`b_kind`、`b_display_type`、`b_canedit` 及其自引用 FK `FK_b_module_field_list_parent`、shape CHECK `CK_b_module_field_list_kind` / `CK_b_module_field_list_shape` / `CK_b_module_field_list_canedit` / `CK_b_module_field_list_width`(宽度校验可保留为简单 `>0`)。
- 新增 `b_group_id bigint NULL`,`FK_b_module_field_list_group` → b_module_field_group(b_id)(同模块分组;为空时为顶层列)。
- 保留 `b_id/b_module_id/b_field_id/b_title/b_i18n/b_visible/b_xh/b_width/b_sortable` 及 CHECK `b_visible/b_sortable IN (0,1)`。
- 唯一索引 `UX (b_module_id, b_field_id)`;索引 `IX (b_module_id, b_group_id, b_xh, b_id)`。
**4. b_module_field_edit(通用编辑配置)**
- 删除 `b_editor`、`b_edit_format`、`b_editor_options`、`b_placeholder`、`b_canform`、`b_edit_group`、`b_edit_span` 七列。
- `b_edit_xh` → 重命名为 `b_xh`(DEFAULT 0)。
- 新增 `b_group_id bigint NULL`,`FK_b_module_field_edit_group` → b_module_field_group(b_id)。
- 保留 `b_id/b_module_id/b_field_id/b_required/b_readonly/b_disabled` 及对应 CHECK;唯一 `(b_module_id, b_field_id)`;索引 `(b_module_id, b_xh, b_id)`。
**5. 无需改动(已符合目标)**
- `b_module`(含模块类型校验、目录/页面/数据三类约束)、`b_module_field_query`、`b_module_power`、`b_user_module`、`b_user_power`、`b_i18n` 结构、约束、索引保持不变。
### 建表顺序(满足外键依赖)
`b_module` → `b_module_field_group` → `b_module_field` → `b_module_field_list` / `b_module_field_edit` / `b_module_field_query` → `b_module_power` → `b_user_module` / `b_user_power` → `b_i18n` → 种子插入。
说明:`b_module_field_group` 必须在 `b_module_field` 之前建(list/edit 的 group_id 引用它);`b_module_field_list` 与 `b_module_field_edit` 的 `b_field_id` 依赖 `b_module_field`。
### 种子数据(按"只保留元数据")
- 保留模块:`m_system`(directory,b_canmenu=1)、`m_metadata`(page,/system/metadata,b_canmenu=1)。
- 保留操作权限(b_module_power):`m_metadata` 的 create/update/delete/sync 四条。
- 保留授权(b_user_module / b_user_power):管理员对 `m_metadata` 的模块权限及上述四条操作权限。
- 移除:`m_i18n`、`m_authorization` 模块及其全部 `b_module_power`、`b_user_module`、`b_user_power` 行。
- 固定雪花种子 ID(9 开头)相应精简为 system/metadata 两套,避免与已删除模块 ID 冲突。
## 实施注意
- 脚本头部 DROP 逻辑保留:仅删用户表(排除 b_user)、保留视图,重置 admin 会话上下文(依赖 b_user,符合约束)。
- 保持 `SET XACT_ABORT ON` 与事务包裹,确保失败时回滚。
- 不引入任何前端/后端代码改动;现有通用接口对列名透传,无需适配。
- 按开发规范,不主动执行脚本或构建;交付时说明未执行,建议用户在选定的组织库(g3hd)手动执行验证。
## 目录结构
本次仅修改一个文件:
```
fms-api/config/migrations/
└── 000_reset_metadata.sql # [MODIFY] 重写建表与种子部分,对齐 新数据库结构.md:
# - b_module_field 列重命名/精简
# - 新增 b_module_field_group 取代 b_module_field_edit_group
# - b_module_field_list 改引用分组表、移除自包含树
# - b_module_field_edit 精简并引用分组表
# - 种子仅保留 m_system + m_metadata
# 头部 DROP 与 admin 上下文逻辑保持不变
```