Files
workspace/code/fms/docs/refactor/模块管理功能设计.md
T
2026-07-19 21:57:40 +08:00

11 KiB
Raw Blame History

模块管理功能设计

范围:模块管理这一功能本身的设计定义,覆盖 模块、字段定义、菜单、多语言、权限 五大能力。 定位:本文档描述「模块管理页面能配置什么、各能力如何分工」,不描述通用 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 数据结构

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 权限项结构

// 模块声明
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 校验权限,不能只依赖前端隐藏。