20260719215738
This commit is contained in:
1 parent
35aa108a34
commit
cda7f16d3a
116 files changed
+11826
-3669
No files matched your search
@@ -0,0 +1,71 @@
|
||||
# 功能树与模块配置重构计划
|
||||
|
||||
## 1. 目标
|
||||
|
||||
本次重构解决两个问题:
|
||||
|
||||
1. 技术人员能够按业务结构定位页面下的主模块、明细模块和隐藏模块,不再依赖扁平列表逐个搜索。
|
||||
2. 字段和表单分组在同一个工作区维护,常用配置直接编辑,高级配置按需展开。
|
||||
|
||||
功能树不生成页面或 Tab。页面布局和模块组合继续由手写 Vue 页面负责。
|
||||
|
||||
## 2. 数据边界
|
||||
|
||||
| 数据 | 责任 |
|
||||
| --- | --- |
|
||||
| `s_function_node` | 目录、页面、技术分组和模块管理位置;菜单由可见节点投影 |
|
||||
| `s_module` | 查询对象、保存对象、业务主键和模块级状态 |
|
||||
| `s_module_field` | 列表、查询和表单字段配置 |
|
||||
| `s_module_group` | 表单字段分组 |
|
||||
|
||||
功能节点父子关系只表示管理位置,不定义保存事务或业务组合。页面节点可以绑定主模块,权限继续按菜单入口、模块和动作独立校验。
|
||||
|
||||
## 3. 实施阶段
|
||||
|
||||
### 阶段 A:功能树基础
|
||||
|
||||
- 创建 `s_function_node`,页面菜单允许直接绑定模块。
|
||||
- 写入“系统管理 / 模块管理 / 模块定义”最小种子。
|
||||
- 模块管理加载完整功能树,未被功能节点引用的模块进入“未归档模块”。
|
||||
- 搜索匹配节点名称、模块编码、模块名称、查询对象和保存对象,并保留祖先节点。
|
||||
|
||||
### 阶段 B:模块配置工作区
|
||||
|
||||
- 左侧用功能树代替分页模块表格。
|
||||
- 目录和页面节点只负责展开;模块节点打开右侧配置。
|
||||
- 保留模块启停快捷开关。
|
||||
- 提供“模块”和“菜单”两个显示开关,隐藏菜单层级时仍能直接定位模块。
|
||||
- 从当前树节点新建模块时自动带入归属位置,保存模块后同步创建树节点。
|
||||
- 右侧显示模块完整路径和模块编码。
|
||||
|
||||
### 阶段 C:字段设计器
|
||||
|
||||
- 合并“字段配置”和“表单分组”为一个“字段设计”Tab。
|
||||
- 左侧显示“全部字段、未分组、已配置分组”。
|
||||
- 分组支持新增、编辑、删除和排序。
|
||||
- 右侧字段表格直接编辑标题、控件、分组、列表显示、表单显示、必填和启停。
|
||||
- 字段表格一次只允许一行进入编辑态,高级属性在当前行下方展开,不使用字段抽屉。
|
||||
- 字段表格占满字段设计工作区剩余高度。
|
||||
- 保存仍复用模块、字段、分组一次事务提交。
|
||||
|
||||
### 阶段 D:菜单投影
|
||||
|
||||
- 完成现有静态菜单到功能树的迁移清单。
|
||||
- 侧边栏读取 `b_show_in_menu = 1` 的目录和页面,并按节点编码或页面路由与现有静态菜单合并。
|
||||
- 功能目录修改后刷新菜单投影;在迁移完成前保留未登记的静态菜单,避免功能入口丢失。
|
||||
- 所有菜单节点和路由核对完成后,再删除静态回退配置。
|
||||
|
||||
## 4. 验收标准
|
||||
|
||||
- 可以从“海运业务 / 海运业务单 / 装箱”路径定位主表和明细模块。
|
||||
- 隐藏模块不出现在业务菜单,但可在模块管理中定位。
|
||||
- 同一个模块可以被多个功能节点引用。
|
||||
- 页面和 Tab 不由配置自动生成。
|
||||
- 未归档模块始终可搜索和打开。
|
||||
- 字段常用属性无需逐个打开弹窗即可修改。
|
||||
- 删除分组时仍阻止删除被字段引用的分组。
|
||||
- 功能树、模块配置和权限的职责没有混用。
|
||||
|
||||
## 5. 当前迁移策略
|
||||
|
||||
当前版本已经完成阶段 A、B、C,并以兼容合并方式启动阶段 D。功能树中的可见目录和页面会立即投影到侧边栏;尚未登记的旧菜单继续使用静态配置。待现有菜单和路由全部登记并核对后,侧边栏再切换为完全由功能树驱动。
|
||||
@@ -0,0 +1,250 @@
|
||||
# 模块管理功能设计
|
||||
|
||||
> 范围:模块管理这一功能本身的设计定义,覆盖 **模块、字段定义、菜单、多语言、权限** 五大能力。
|
||||
> 定位:本文档描述「模块管理页面能配置什么、各能力如何分工」,**不描述**通用 `ModuleTable`/`ModuleForm` 的渲染实现,也不描述角色赋权页面(授权在另一处)。
|
||||
> 配套原型:`fms-vue/src/views/ModuleManageDemo.vue`(纯前端,仅作演示)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计目标与边界
|
||||
|
||||
模块管理是一个**配置中枢**,让实施人员用「填表」的方式定义一套业务功能,而不必改代码。它同时服务于四类下游消费者:
|
||||
|
||||
| 消费者 | 从模块管理取走什么 |
|
||||
| --- | --- |
|
||||
| 通用列表 `ModuleTable` | 字段清单、列标题、列表/表单开关、排序 |
|
||||
| 通用表单 `ModuleForm` | 字段控件类型、校验、表单分组 |
|
||||
| 菜单投影 | 哪些功能节点可见、显示什么名字 |
|
||||
| 权限内核 | 该模块声明了哪些操作(编码)可供授权 |
|
||||
|
||||
### 核心原则:各自负责各自
|
||||
|
||||
1. **权限负责「有什么操作」**,只声明编码目录,不持有任何界面文案。
|
||||
2. **多语言负责「所有界面显示名」**,是唯一文案数据源;但**只覆盖菜单 / 模块 / 字段三类显示名,不覆盖权限项**(权限名是给管理员看的配置标签,不是给终端用户的按钮文案)。
|
||||
3. **字段定义驱动列表与表单**,自身不关心权限、不关心翻译落点。
|
||||
4. **菜单是功能树的可投影子集**,不单独存一份菜单数据。
|
||||
|
||||
---
|
||||
|
||||
## 2. 模块(Module)
|
||||
|
||||
模块是配置的中心对象,聚合「数据源 + 字段 + 表单分组 + 操作目录」。
|
||||
|
||||
### 2.1 基本信息
|
||||
|
||||
| 项 | 说明 |
|
||||
| --- | --- |
|
||||
| 模块编码 `b_id` | 唯一主键,如 `M_BIZ`、`M_USER` |
|
||||
| 模块名称 | 在「多语言」中以 `module.<编码>` 维护(见 §5) |
|
||||
| 查询对象 `view_name` | 只读裸对象名(视图),如 `v_bs_business` |
|
||||
| 保存对象 `save_name` | 可写裸表名,如 `b_business`;只读模块允许为空 |
|
||||
| 业务主键 | 可选,用于展示与去重的业务字段,不代替系统主键 `b_id` |
|
||||
| 默认排序 | 如 `b_id DESC` |
|
||||
| 表单分组 | 见 §3.3 |
|
||||
|
||||
### 2.2 操作目录(权限项来源,见 §6)
|
||||
|
||||
模块声明它拥有哪些操作:`actions: [{ code, name }, ...]`。例如 `M_BIZ` 声明 `1=新增 … 7=导出`。
|
||||
|
||||
### 2.3 与其它能力的关联
|
||||
|
||||
```
|
||||
Module
|
||||
├─ fields[] → 驱动 ModuleTable / ModuleForm(§3)
|
||||
├─ groups[] → 组织 Form 分组(§3.3)
|
||||
├─ actions[] → 声明可被授权的操作编码(§6)
|
||||
└─ 被功能树 page/module 节点引用 → 投影进菜单(§4)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 字段定义(Field)
|
||||
|
||||
字段是模块下的最小元数据单元,**通用列表与通用表单都由字段配置驱动**。
|
||||
|
||||
### 3.1 字段属性
|
||||
|
||||
| 属性 | 说明 |
|
||||
| --- | --- |
|
||||
| 字段编码 `code` | 模块对前端暴露的稳定字段名,如 `b_ywno`、`b_amount` |
|
||||
| 标题 `caption` | 在「多语言」中以 `field.<模块>.<字段>` 维护,列表/表单共用 |
|
||||
| 数据类型 `dataType` | `string / text / number / select / date / boolean` |
|
||||
| 表单分组 `groupId` | 指向模块的分组,Form 按分组渲染 |
|
||||
| 列表显示 `showInList` | 是否作为列表列 |
|
||||
| 表单显示 `showInForm` | 是否在表单中出现 |
|
||||
| 必填 `required` | 表单校验 |
|
||||
|
||||
> 字段配置不保存查询操作符、不保存固定 SQL;高级查询运行时按字段类型给出合法操作符。
|
||||
|
||||
### 3.2 驱动关系
|
||||
|
||||
- **列表列** = `fields` 中 `showInList = true` 的子集,按所属分组/排序渲染列与标题。
|
||||
- **表单控件** = `fields` 中 `showInForm = true` 的子集,`dataType` 决定控件(文本/数字/下拉/日期/布尔),`required` 决定校验。
|
||||
|
||||
### 3.3 表单分组(Group)
|
||||
|
||||
模块下可设多个分组(如「主信息」「费用信息」),字段通过 `groupId` 归属分组。简单表单可不配置分组,落入默认分组。
|
||||
|
||||
---
|
||||
|
||||
## 4. 菜单(Menu / 功能树)
|
||||
|
||||
菜单**不是独立数据**,而是「功能树」中满足条件的节点投影。
|
||||
|
||||
### 4.1 功能树节点
|
||||
|
||||
统一功能树 `s_function_node` 组织全部入口,节点类型:
|
||||
|
||||
| 类型 | 含义 | 能否投影菜单 |
|
||||
| --- | --- | --- |
|
||||
| `directory` | 业务域/目录 | 可(`showInMenu`) |
|
||||
| `page` | 已注册手写页面,可绑定模块 | 可(`showInMenu`) |
|
||||
| `module` | 纯配置定位,供技术归类 | 否 |
|
||||
| `group` | 配置分组 | 否 |
|
||||
|
||||
### 4.2 菜单投影规则
|
||||
|
||||
一个节点真正出现在某角色的菜单里,需同时满足:
|
||||
|
||||
1. 节点类型 ∈ {`directory`, `page`};
|
||||
2. `showInMenu = true`;
|
||||
3. 当前角色对该节点拥有「查看」权限。
|
||||
|
||||
### 4.3 关键场景:同模块、不同页面、不同权限
|
||||
|
||||
多个 `page` 节点可绑定**同一个模块**(如 `M_BIZ` 被 `海运业务单 / 业务单查询 / 业务单审核` 三个页面引用)。它们共享字段与操作目录,但:
|
||||
|
||||
- 可见性各自独立(`业务单审核` 设 `showInMenu=false`,不进菜单);
|
||||
- 权限各自独立(操作员在「海运业务单」可提交,在「业务单审核」仅可审核)——授权由角色赋权页另配(不在本页面)。
|
||||
- 模块父子关系(含 `module` 节点)仅用于技术归类与定位,**不**定义保存事务、主子表外键或业务流程。
|
||||
|
||||
---
|
||||
|
||||
## 5. 多语言(i18n)
|
||||
|
||||
所有**界面显示名**唯一数据源,以稳定 `i18nKey` 为中心,多种语言并列。
|
||||
|
||||
### 5.1 覆盖范围(仅三类显示名)
|
||||
|
||||
| 命名空间 | i18nKey 规则 | 示例 |
|
||||
| --- | --- | --- |
|
||||
| 菜单/功能树 | `menu.<节点id>` | `menu.page_biz` |
|
||||
| 模块 | `module.<模块编码>` | `module.M_BIZ` |
|
||||
| 字段 | `field.<模块>.<字段code>` | `field.M_BIZ.b_ywno` |
|
||||
|
||||
> **权限项名称不在此列**(见 §6 说明)。
|
||||
|
||||
### 5.2 数据结构
|
||||
|
||||
```js
|
||||
i18nData = {
|
||||
"menu.page_biz": { "zh-CN": "海运业务单", "en-US": "Sea Business Orders", "zh-TW": "海運業務單" },
|
||||
"field.M_BIZ.b_ywno": { "zh-CN": "业务单号", "en-US": "Order No.", "zh-TW": "業務單號" }
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- 实体本身**只持有 `i18nKey`,不持有任何文案**,显示一律走 `t(i18nKey)`。
|
||||
- 回退顺序:当前语言 → `zh-CN` → `i18nKey` 本身。
|
||||
- 切换语言时,功能树、字段标题、菜单预览实时联动。
|
||||
|
||||
### 5.3 管理界面要求
|
||||
|
||||
- 按命名空间类型筛选(菜单 / 模块 / 字段)。
|
||||
- 以「Key + 各语言列」并列编辑;某语言留空即回退简体。
|
||||
- **缺失翻译检测**:非默认语言留空时标红,并汇总「N 条缺失」,提示补录。
|
||||
|
||||
---
|
||||
|
||||
## 6. 权限(Permission)
|
||||
|
||||
权限负责**声明一个模块有哪些可授权操作**,仅此而已。
|
||||
|
||||
### 6.1 权限项结构
|
||||
|
||||
```js
|
||||
// 模块声明
|
||||
actions: [
|
||||
{ code: 1, name: "新增" },
|
||||
{ code: 5, name: "审核" },
|
||||
{ code: 7, name: "导出" }
|
||||
]
|
||||
```
|
||||
|
||||
- `code`:稳定操作编码,前端与后端统一引用(如 `5` 永远代表「审核」)。**授权与校验只认 `code`,不认名字。**
|
||||
- `name`:管理员可读的默认标签,仅一份(简体)。它是「这个编码是干嘛的」的配置注释,**不是终端用户的按钮文案**。
|
||||
|
||||
### 6.2 为什么不进多语言
|
||||
|
||||
- 授权逻辑只认 `code`,名字不参与校验,因此没有翻译必要。
|
||||
- 界面上的按钮文案常与权限名不同(权限叫「审核」,按钮可能写「通过」),把权限名塞进 i18n 反而把「权限定义」与「按钮文案」错误耦合。
|
||||
- 结论:**权限定义自洽于 `{code, name}`,与多语言彻底解耦**;终端用户看到的按钮文案由各自页面/组件自行在多语言里维护。
|
||||
|
||||
### 6.3 与授权层的关系(边界)
|
||||
|
||||
- 本页面**只负责声明**操作目录(`code` 集合)。
|
||||
- 真正的「角色 → 节点 → 允许哪些 `code`」赋权在**另一页面**配置,不在模块管理内。
|
||||
- 模块管理里的菜单预览可用一份写死的授权结果做示意,但不在此维护。
|
||||
|
||||
### 6.4 扩展约定
|
||||
|
||||
- 模块新增一个权限项(如 `8=核销`),授权层无需改结构,直接照单收编码即可——两层天然对齐。
|
||||
|
||||
---
|
||||
|
||||
## 7. 五者关系总览
|
||||
|
||||
```
|
||||
功能树 (directory/page/module/group)
|
||||
│ page 节点绑定 模块
|
||||
▼
|
||||
模块 (Module: 查询/保存对象, 字段, 分组, 操作目录)
|
||||
├─ 字段 ─────────────► 驱动 ModuleTable / ModuleForm
|
||||
├─ 分组 ─────────────► 组织 Form
|
||||
└─ 操作目录(code) ────► 权限内核(角色赋权页另行消费)
|
||||
▲
|
||||
│ 各自只声明,不持有文案
|
||||
│
|
||||
多语言 (i18nKey → 多语言值) ──► 菜单名 / 模块名 / 字段标题 的唯一文案源
|
||||
(权限名不在内)
|
||||
|
||||
菜单 = 功能树中 showInMenu=1 且角色有查看权限的节点投影
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 与当前原型(Demo)的对应关系
|
||||
|
||||
| 设计项 | 原型位置 | 备注 |
|
||||
| --- | --- | --- |
|
||||
| 功能树四类节点 | `functionTree` | 已是响应式可编辑 |
|
||||
| 模块基本信息/字段/分组 | `modules` | `M_MODULE/M_USER/M_BIZ/M_FEE` |
|
||||
| 字段驱动列表/表单 | `字段配置` Tab | 列表/表单/必填开关 |
|
||||
| 菜单投影 | `菜单预览` Tab | 按角色 + 语言渲染 |
|
||||
| 多语言 | `多语言` Tab | Key + 三语,含缺失标红 |
|
||||
| 权限目录 | `权限项` Tab | `code + name`,可增删 |
|
||||
|
||||
### 与原型的对齐情况
|
||||
|
||||
原型已按本文设计落地:
|
||||
|
||||
- **多语言仅覆盖菜单 / 模块 / 字段三类显示名**;`action.*` 条目已从 `i18nData` 彻底移除,权限项名不再进多语言(符合 §6)。
|
||||
- **权限项仅含 `{code, name}`**,`name` 为管理员可读标签,不在多语言维护;新增权限项不再生成 i18nKey。
|
||||
- **字段多语言可在字段配置处点击设置**:标题单元格带多语言按钮,点击打开该字段的简体/English/繁體编辑框(i18nKey 形如 `field.<模块>.<字段>`)。
|
||||
- **字段 `i18nKey` 统一为 `field.<模块>.<字段>`**,与模块/菜单 `<id>` 前缀、整体「命名空间.容器.标识」规则一致。
|
||||
- 授权 `roleNodePerm` 仍为写死 mock,仅用于菜单预览示意,符合 §6.3 边界(角色赋权在另一页面,不在模块管理内)。
|
||||
|
||||
---
|
||||
|
||||
## 9. 数据模型概览(落库参考)
|
||||
|
||||
| 表 | 用途 |
|
||||
| --- | --- |
|
||||
| `s_module` | 模块定义(查询/保存对象、排序) |
|
||||
| `s_module_field` | 字段配置(编码、标题键、类型、列表/表单/必填、分组) |
|
||||
| `s_module_group` | 表单分组 |
|
||||
| `s_function_node` | 功能树(目录/页面/分组/模块定位) |
|
||||
| `s_i18n` | 多语言键值(key → 各语言值),覆盖菜单/模块/字段 |
|
||||
| 权限相关表 | 独立系统表,不属于 Table/Form 渲染配置 |
|
||||
|
||||
> 角色与权限内核使用独立系统表,不写入模块渲染配置;后端按 `module_id` + 操作 `code` 校验权限,不能只依赖前端隐藏。
|
||||
@@ -0,0 +1,81 @@
|
||||
# 阶段一:模块管理
|
||||
|
||||
## 目标
|
||||
|
||||
在不开发通用 `ModuleTable`、`ModuleForm` 的前提下,完成可通过页面操作验证的模块管理纵向闭环。
|
||||
|
||||
## 本阶段范围
|
||||
|
||||
- 建立模块、字段、表单分组、选项来源和功能节点的数据库结构。
|
||||
- 写入模块管理自身的种子配置。
|
||||
- 复用现有通用查询、分页和事务保存接口。
|
||||
- 提供手写的功能树与模块详情工作区。
|
||||
- 支持模块基本信息、字段设计、表单分组、菜单绑定和功能树位置维护。
|
||||
- 统一将 SQL Server `bigint` 作为字符串返回前端,避免雪花 ID 精度丢失。
|
||||
|
||||
## 数据库对象
|
||||
|
||||
| 对象 | 用途 |
|
||||
| --- | --- |
|
||||
| `dbo.s_module` | 模块定义 |
|
||||
| `dbo.s_module_field` | 模块字段配置 |
|
||||
| `dbo.s_module_group` | 表单分组配置 |
|
||||
| `dbo.s_option_source` | 固定或模块查询选项来源 |
|
||||
| `dbo.s_option_item` | 固定选项明细 |
|
||||
| `dbo.s_function_node` | 目录、页面、技术分组和模块位置 |
|
||||
|
||||
数据库脚本位于:
|
||||
|
||||
`fms-api/src/main/resources/db/migration/001_module_management.sql`
|
||||
|
||||
脚本可以重复执行,首次执行时创建配置表并写入 `s_module` 模块种子数据。
|
||||
|
||||
## 页面入口
|
||||
|
||||
- 菜单:`系统管理 / 模块管理`
|
||||
- 路由:`/system/modules`
|
||||
|
||||
页面采用左侧功能树、右侧模块详情的桌面工作布局(不兼容移动端)。未被功能节点引用的模块统一进入“未归档模块”。详情包含:
|
||||
|
||||
- 基本信息。
|
||||
- 字段设计,字段与表单分组在同一工作区维护。
|
||||
- 功能树中的菜单绑定和隐藏子模块位置。
|
||||
|
||||
功能树可以在页面内维护目录、页面、模块绑定和隐藏子模块。目录与页面的 `b_show_in_menu` 配置会投影到侧边栏,并与尚未迁移的静态菜单合并,避免迁移期间丢失入口。
|
||||
|
||||
## 接口边界
|
||||
|
||||
本阶段没有新增模块管理 CRUD 接口,继续复用:
|
||||
|
||||
- `/api/data/page`
|
||||
- `/api/data/loaddata`
|
||||
- `/api/data/saveobjt`
|
||||
- `/api/data/nextid`
|
||||
|
||||
模块、字段和分组通过一次 `saveobjt` 请求在同一事务中保存,功能树节点独立保存。删除模块时同时清理功能节点引用;存在下级功能节点时禁止直接删除。
|
||||
|
||||
## 页面验收步骤
|
||||
|
||||
1. 使用机构 `G3HD` 登录新系统。
|
||||
2. 进入“系统管理 / 模块管理”。
|
||||
3. 确认能够看到内置的“模块管理”模块。
|
||||
4. 打开该模块,检查基本信息、5 个字段配置和 1 个表单分组。
|
||||
5. 在功能树管理中新增一个临时目录和页面节点。
|
||||
6. 新建一个临时模块,填写裸查询对象名、裸保存对象名、可选业务主键字段和默认排序;页面不应出现主键策略和保存模式。
|
||||
7. 为临时模块新增字段、表单分组和功能树位置并保存。
|
||||
8. 将一个页面菜单绑定到临时模块,并在它下面增加隐藏子模块。
|
||||
9. 重新进入临时模块,确认字段、分组和树形位置能够完整加载。
|
||||
10. 修改字段标题或排序并保存,重新加载后确认修改生效。
|
||||
11. 删除临时模块,确认模块、字段、分组和无下级节点的功能树引用一起删除。
|
||||
12. 确认内置的 `s_module` 模块不能从页面删除。
|
||||
|
||||
## 本阶段暂不包含
|
||||
|
||||
- 通用 `ModuleTable`。
|
||||
- 通用 `ModuleForm`。
|
||||
- 独立的选项来源管理页面。
|
||||
- 正式模块权限内核。
|
||||
- 结构化模块查询接口。
|
||||
- 业务模块迁移。
|
||||
|
||||
这些能力在模块管理页面验证配置模型稳定后继续建设。
|
||||
Reference in new issue
Block a user