548 lines
23 KiB
Markdown
548 lines
23 KiB
Markdown
# FMS 模块关系与权限边界重构计划
|
||
|
||
> 状态:草案,供评审
|
||
>
|
||
> 目标:明确模块树、菜单绑定、数据关系、权限和删除策略的边界,降低“模块关联”配置的理解成本,避免一个关系表同时承担多种语义。
|
||
|
||
## 一、结论先行
|
||
|
||
“模块关联”不应该同时承担菜单授权、模块父子关系、业务数据关系和删除规则。
|
||
|
||
本次计划采用以下分工:
|
||
|
||
| 问题 | 权威数据 | 说明 |
|
||
| --- | --- | --- |
|
||
| 模块业务组织层级 | `s_module.b_parent_id` | 表达业务域、模块分组和权限上下文边界 |
|
||
| 菜单导航层级 | `s_menu.b_parent_id` | 表达目录、页面和外链的导航树 |
|
||
| 菜单使用哪些模块 | `s_menu_module` | 菜单与模块的多对多绑定,保存明确的模块清单 |
|
||
| 用户拥有哪些权限 | `s_power`、`s_user_power` | 模块访问、业务动作和菜单入口权限 |
|
||
| 数据字段之间的引用关系 | `s_relation` | 只表达模块字段之间的结构关系 |
|
||
| 删除前的业务限制 | `s_delete_rule` | 用只读 SQL 检查状态、单据和跨表条件 |
|
||
| 关联记录如何处置 | 删除策略 | `restrict`、`cascade`、`none`,不参与菜单权限计算 |
|
||
|
||
因此:
|
||
|
||
1. **菜单权限不需要依赖 `s_relation`。**
|
||
2. **模块父子关系使用 `s_module.b_parent_id`,不从字段关系推导。**
|
||
3. **`s_relation` 建议保留为“数据关系”,但不再称为菜单权限意义上的模块关联。**
|
||
4. **删除策略继续存在,但从数据关系的菜单中剥离,统一放到删除策略入口。**
|
||
|
||
当前设计文档已经有这几张表的雏形:模块树使用 `s_module.b_parent_id`,菜单绑定使用 `s_menu_module`,数据关系使用 `s_relation`。[核心表设计](FMS新系统核心表结构设计.md) [模块设计评审](FMS模块设计评审.md)
|
||
|
||
## 二、当前问题
|
||
|
||
### 2.1 “模块关联”包含了三种不同关系
|
||
|
||
目前容易把下面三件事都叫作模块关联:
|
||
|
||
1. **组织关系**:海运模块下面有主单、箱、费用模块。
|
||
2. **数据关系**:箱表的 `order_id` 引用主单表的 `id`。
|
||
3. **授权关系**:某个菜单页面使用主单模块和箱模块,用户可以进入并操作这些模块。
|
||
|
||
它们的数学结构和运行规则不同:
|
||
|
||
| 关系 | 结构 | 典型约束 |
|
||
| --- | --- | --- |
|
||
| 模块组织 | 树 | 一个父节点、不能循环 |
|
||
| 数据关系 | 图 | 可以多对多、可以有多个入边 |
|
||
| 菜单绑定 | 多对多 | 一个页面可用多个模块,一个模块可被多个页面使用 |
|
||
| 权限授权 | 用户到权限点 | 不能因为数据引用就自动获得权限 |
|
||
|
||
如果用数据关系建立模块父子树,会遇到多个父节点、循环和跨业务域引用。例如“费用 → 客户”是数据引用,但费用模块并不是客户模块的子模块。把它用于权限继承会造成权限扩大。
|
||
|
||
### 2.2 删除策略和菜单权限没有共同语义
|
||
|
||
删除策略回答:
|
||
|
||
> 删除一条业务记录时,关联记录如何处理?什么条件下不允许删除?
|
||
|
||
权限回答:
|
||
|
||
> 用户能否进入页面、使用模块、执行动作、查看字段和查看哪些数据?
|
||
|
||
两者的计算入口、管理员和风险都不同。把删除配置放进菜单权限关联,会让配置人员误以为“菜单绑定”会影响删除,也会让关系面板出现过多不相关列。
|
||
|
||
### 2.3 当前代码已经有两个真实消费者
|
||
|
||
当前前端菜单管理使用 `s_menu_module` 保存菜单与模块的绑定;模块关系面板维护 `s_relation`。后端 `DataDeleteService` 会读取启用的 `s_relation`,展开 `cascade` 并检查 `restrict`。
|
||
|
||
这说明 `s_relation` 不是完全没有价值,但它的价值来自**数据删除和数据影响分析**,不是菜单授权。若以后改成每个模块完全由专用 SQL 删除,才可以进一步评估是否移除它。
|
||
|
||
## 三、目标模型
|
||
|
||
### 3.1 三棵树、两类关系
|
||
|
||
```text
|
||
模块组织树
|
||
s_module.b_parent_id
|
||
海运
|
||
├── 海运主单
|
||
├── 箱信息
|
||
└── 费用
|
||
|
||
菜单导航树
|
||
s_menu.b_parent_id
|
||
业务管理
|
||
└── 海运工作台
|
||
|
||
菜单与模块绑定
|
||
s_menu_module
|
||
海运工作台 ── 海运主单
|
||
海运工作台 ── 箱信息
|
||
海运工作台 ── 费用
|
||
|
||
数据字段关系
|
||
s_relation
|
||
箱信息.order_id ──> 海运主单.id
|
||
费用.order_id ──> 海运主单.id
|
||
```
|
||
|
||
模块树只表达业务组织。菜单树只表达导航。菜单页面使用哪些数据模块由 `s_menu_module` 明确保存。数据字段关系只用于数据层,不参与菜单树和权限树。
|
||
|
||
### 3.2 权限归属:模块为主,菜单为入口
|
||
|
||
权限应当**跟着模块**,菜单只负责提供入口。
|
||
|
||
```text
|
||
用户
|
||
└── 拥有权限点
|
||
├── menu.* → 能否进入菜单页面
|
||
├── module.* → 能否使用模块
|
||
└── action.* → 能否执行模块动作
|
||
|
||
菜单页面
|
||
└── s_menu_module → 页面使用哪些模块
|
||
|
||
模块
|
||
├── s_user_field_power → 字段能力
|
||
└── s_user_data_power → 数据范围
|
||
```
|
||
|
||
菜单绑定模块不等于授予模块权限。原因有三点:
|
||
|
||
1. 一个模块可能被多个菜单复用,权限应该保持一致;
|
||
2. 一个菜单可能使用主模块、明细模块和多个辅助模块,不适合把它们的权限合并成一个菜单权限;
|
||
3. 后端接口、导出、保存和业务动作可能绕过菜单入口,必须仍按模块权限和动作权限校验。
|
||
|
||
因此运行时按以下顺序判断:
|
||
|
||
1. 用户是否拥有当前菜单的 `menu.*` 权限;
|
||
2. 当前页面所需模块是否拥有 `module.*` 权限;
|
||
3. 当前请求的操作是否拥有对应的 `action.*` 或标准操作权限;
|
||
4. 查询和写入时继续追加字段权限和数据范围条件。
|
||
|
||
如果一个页面绑定多个模块,菜单权限只决定能否进入页面,每个模块仍单独判断。主模块或必需模块无权限时,页面应隐藏或拒绝进入;可选模块无权限时,可以隐藏对应面板。是否为“必需模块”属于页面配置,不由 `s_relation` 推导。
|
||
|
||
模块父子树可以作为管理员批量授权的操作范围,但第一期不建议运行时隐式继承:勾选父模块时可以在界面展开子模块,最终保存每个数据模块的明确授权行。这样新建子模块不会在用户不知情的情况下自动获得所有权限。
|
||
|
||
### 3.3 权限计算边界
|
||
|
||
权限计算分为五层:
|
||
|
||
1. `menu.*`:能否看到和进入菜单页面。
|
||
2. `module.*`:能否使用页面中的某个模块。
|
||
3. `action.*`:能否执行审核、结算等业务动作。
|
||
4. `s_user_field_power`:字段查看、编辑、查询和导出权限。
|
||
5. `s_user_data_power`:数据行范围。
|
||
|
||
菜单绑定多个模块时,不合并这些模块的权限;每个模块仍按自己的模块编码判断。数据关系也不自动传播权限。若管理员在界面上勾选一个模块分类节点,可以自动展开下级数据模块,但落库仍保存明确的模块权限或菜单绑定行。
|
||
|
||
### 3.4 用户授权页面如何呈现
|
||
|
||
管理员不需要直接理解 `s_relation`。授权页面以业务域和模块树呈现:
|
||
|
||
```text
|
||
海运(业务域,只做分组)
|
||
├── 海运主单(data)
|
||
├── 装箱信息(data)
|
||
└── 费用(data)
|
||
```
|
||
|
||
建议将授权页面分成三个视图:
|
||
|
||
#### 菜单入口
|
||
|
||
左侧显示菜单树,管理员选择“海运工作台”等页面,保存 `menu.*` 权限。
|
||
|
||
#### 模块能力
|
||
|
||
显示当前页面绑定的模块,以及完整的业务模块树。每个 `data` / `virtual` 模块显示:
|
||
|
||
- 是否可访问;
|
||
- 标准操作:查看、新增、编辑、删除、导出;
|
||
- 已配置的业务动作,例如审核、结算;
|
||
- 当前模块是否被哪些菜单使用。
|
||
|
||
选择“海运”父节点时,界面可以全选或取消全部子模块,并使用半选状态表示部分授权。这个操作只是批量生成明确的模块授权行,不保存“沿关系自动继承”的隐式规则。
|
||
|
||
#### 字段和数据范围
|
||
|
||
管理员先选择一个具体模块,再配置字段权限和数据范围。不要在“海运”父节点上混合展示主单、装箱和费用的字段,因为这些字段属于不同模块,数据范围也可能不同。
|
||
|
||
页面绑定关系可以提供一个“按页面补齐模块权限”的快捷操作:管理员选择菜单后,系统列出该页面使用的主模块、明细模块和辅助模块,管理员确认后一次性生成模块权限。这个操作是显式的授权动作,菜单绑定本身不自动授权。
|
||
|
||
页面确实依赖某个模块时,应在页面配置中标记该模块为必需模块;可选模块则在用户没有权限时隐藏对应面板。必需/可选属于页面使用配置,不从 `s_relation` 的数据关系推导。
|
||
|
||
授权效果示例:
|
||
|
||
| 用户 | 菜单入口 | 模块权限 | 页面效果 |
|
||
| --- | --- | --- | --- |
|
||
| 张三 | 海运工作台 | 主单、装箱 | 能进入页面,费用面板隐藏或不可用 |
|
||
| 李四 | 海运工作台 | 主单、装箱、费用 | 能使用完整页面 |
|
||
| 王五 | 无海运菜单 | 主单 | 不能从海运菜单进入,但模块接口仍按模块权限统一校验 |
|
||
|
||
页面是否显示可以由“菜单权限 + 至少一个可访问的必需模块”共同决定;真正的查询、保存、删除和动作权限仍必须在后端按模块执行。
|
||
|
||
### 3.5 默认使用“业务授权方案”,隐藏技术细节
|
||
|
||
如果每个用户都要先分配菜单,再逐个分配主单、装箱、费用和动作,业务管理员会觉得权限系统过于复杂。因此默认授权入口不直接展示三套独立权限表,而是展示业务人员能理解的授权方案:
|
||
|
||
```text
|
||
海运
|
||
├── 未授权
|
||
├── 只读
|
||
├── 经办
|
||
└── 主管
|
||
```
|
||
|
||
方案的含义由系统管理员预先定义。例如:
|
||
|
||
| 方案 | 菜单入口 | 海运主单 | 装箱信息 | 费用 |
|
||
| --- | --- | --- | --- | --- |
|
||
| 只读 | 海运工作台、海运单列表 | 查看、导出 | 查看 | 查看 |
|
||
| 经办 | 海运工作台、海运单列表 | 查看、新增、编辑、导出 | 查看、编辑 | 查看 |
|
||
| 主管 | 海运全部相关页面 | 全部标准操作和业务动作 | 全部标准操作 | 查看、编辑、导出、结算 |
|
||
|
||
管理员选择“海运·经办”后,界面先展示授权预览:
|
||
|
||
```text
|
||
将授予:
|
||
菜单:海运工作台、海运单列表
|
||
模块:海运主单(查看/新增/编辑/导出)
|
||
装箱信息(查看/编辑)
|
||
费用(查看)
|
||
```
|
||
|
||
确认后,在同一事务中写入菜单权限和模块/动作权限。这里的“方案”只是管理员操作的简化入口,运行时的真实权限仍然按模块、动作、字段和数据范围校验;菜单绑定不会在运行时隐式授予模块权限。
|
||
|
||
默认页面只展示业务名称和方案,不展示模块编码、字段编码和 `s_relation`。授权预览中的“主单、装箱、费用”依赖来自 `s_menu_module` 的页面模块清单,不从数据关系推导。
|
||
|
||
高级管理员可以展开“详细调整”:单独修改某个模块、动作、字段或数据范围。详细调整生成同一套底层权限记录,不另建一套与方案互相覆盖的规则。方案变更后,应显示变更前后差异并要求确认。
|
||
|
||
第一期不必新增复杂的角色继承体系。可以先把方案作为权限页面上的预置操作,直接物化为现有 `s_power` / `s_user_power` 等权限行。出现多个用户需要相同授权时,再把方案独立为可复用的权限模板。
|
||
|
||
## 四、目标表设计
|
||
|
||
### 4.1 `s_module`:模块组织树
|
||
|
||
继续使用现有字段:
|
||
|
||
- `b_id`:模块编码。
|
||
- `b_parent_id`:直接父模块,树关系的唯一权威来源。
|
||
- `b_depth`、`b_path`:由业务层维护的派生字段。
|
||
- `b_module_type`:`module`、`data`、`virtual`。
|
||
|
||
约束:
|
||
|
||
- `module` 可以包含下级 `module`、`data` 和 `virtual`。
|
||
- `data`、`virtual` 默认作为叶子节点。
|
||
- 不允许自指和循环。
|
||
- 移动模块时,在同一事务内更新当前节点及全部后代的 `b_depth`、`b_path`。
|
||
- 不从 `s_relation` 推导 `b_parent_id`。
|
||
|
||
### 4.2 `s_menu`、`s_menu_module`:菜单与模块绑定
|
||
|
||
`s_menu` 继续使用 `b_parent_id` 建立菜单树。
|
||
|
||
`s_menu_module` 继续使用联合主键:
|
||
|
||
```text
|
||
(b_menu_id, b_module_id)
|
||
```
|
||
|
||
绑定规则:
|
||
|
||
- `directory`、`external` 不强制绑定模块。
|
||
- `page` 可以绑定一个或多个 `data` / `virtual` 模块。
|
||
- `module` 类型只作为分类和上下文,不直接进入菜单模块绑定。
|
||
- UI 可以按模块树批量勾选,但保存时写入明确的 `s_menu_module` 行。
|
||
- 删除模块前检查并清理其菜单绑定,不能通过数据关系级联推断菜单绑定。
|
||
|
||
### 4.3 `s_relation`:数据关系
|
||
|
||
建议将管理页面名称改为“数据关系”,表继续使用字段级复合键:
|
||
|
||
```text
|
||
b_source_module_id
|
||
b_source_field
|
||
b_target_module_id
|
||
b_target_field
|
||
b_relation_type -- one_to_one / one_to_many / many_to_one
|
||
b_canuse
|
||
b_xh
|
||
```
|
||
|
||
它只回答:
|
||
|
||
> 哪个模块的哪个字段与另一个模块的哪个字段存在结构关系?
|
||
|
||
它不保存:
|
||
|
||
- 菜单编码。
|
||
- 用户编码。
|
||
- 权限编码。
|
||
- 模块树父节点。
|
||
- 菜单显示顺序。
|
||
|
||
#### 删除行为的处理
|
||
|
||
当前通用删除服务已经依赖 `b_on_delete`,因此建议采用兼容方案:
|
||
|
||
- 数据库中暂时保留 `s_relation.b_on_delete`。
|
||
- 关系面板只显示该列或提供跳转,不作为菜单权限关系编辑。
|
||
- 唯一可编辑入口放到“删除策略 → 关联删除处理”。
|
||
- 只保留 `restrict`、`cascade`、`none` 三值。
|
||
- 不根据 `b_relation_type` 自动推断删除行为。
|
||
|
||
如果后续确认所有模块都由专用 SQL 或存储过程删除,则可以迁移掉 `b_on_delete`,让 `s_relation` 只保留结构关系。
|
||
|
||
### 4.4 `s_delete_rule`:业务删除条件
|
||
|
||
`s_delete_rule` 只处理“什么情况下不允许删除”,不再保存数据关系键:
|
||
|
||
```text
|
||
b_id
|
||
b_module_id
|
||
b_sql -- 只读检查 SQL,命中行即拒绝删除
|
||
b_message
|
||
b_xh
|
||
b_canuse
|
||
```
|
||
|
||
适合配置:
|
||
|
||
- 已审核单据不能删除。
|
||
- 已开票记录不能删除。
|
||
- 已生成下游业务单据不能删除。
|
||
- 状态或跨表条件不满足时不能删除。
|
||
|
||
SQL 只做检查,不允许配置 SQL 直接修改或删除业务数据。实际物理删除继续由后端事务服务负责。
|
||
|
||
## 五、前端改造方案
|
||
|
||
### 5.1 模块管理页面
|
||
|
||
建议将业务能力分节调整为:
|
||
|
||
```text
|
||
基础
|
||
字段
|
||
界面
|
||
数据关系
|
||
删除策略
|
||
自动编码
|
||
权限
|
||
多语言
|
||
```
|
||
|
||
其中:
|
||
|
||
- “数据关系”只维护字段关系。
|
||
- “删除策略”包含“关联删除处理”和“删除 SQL 规则”。
|
||
- “权限”只维护 `s_power`,不展示删除配置。
|
||
- “数据关系”只对 `data` 模块开放。
|
||
|
||
### 5.2 数据关系面板
|
||
|
||
保留:
|
||
|
||
- 新增关系。
|
||
- 源字段选择。
|
||
- 目标模块、目标字段选择。
|
||
- 关系类型。
|
||
- 启用/停用。
|
||
- 排序号。
|
||
- 当前模块作为源的关系编辑。
|
||
- 其他模块指向当前模块的关系只读展示。
|
||
|
||
调整:
|
||
|
||
- 面板标题从“模块关联”改为“数据关系”。
|
||
- 删除处理列改为只读并提供“前往删除策略”的入口,或者完全移入删除策略面板。
|
||
- 不出现菜单、权限、用户等字段。
|
||
- 保存前校验模块、字段存在,字段类型可匹配,关系不能重复。
|
||
|
||
### 5.3 菜单管理页面
|
||
|
||
- 左侧继续展示模块树。
|
||
- 勾选 `module` 分类节点时,展开其下的 `data` / `virtual` 模块。
|
||
- 保存时只提交 `s_menu_module` 的增删行。
|
||
- 菜单页面绑定的模块不反向修改模块树。
|
||
- 模块被多个菜单使用时,只维护多条菜单绑定,不复制模块。
|
||
|
||
### 5.4 权限面板
|
||
|
||
- 模块使用权限继续以 `module.{moduleCode}` 为主。
|
||
- 业务动作使用 `action.{moduleCode}.{action}`。
|
||
- 菜单权限只控制入口。
|
||
- 不因 `s_relation` 存在而自动给用户增加目标模块权限。
|
||
- 如果未来需要继承,只允许从 `s_module.b_parent_id` 的组织树计算,并明确配置继承边界;不使用字段关系推导。
|
||
|
||
## 六、删除实现取舍
|
||
|
||
### 6.1 当前阶段推荐方案
|
||
|
||
保留通用删除服务:
|
||
|
||
```text
|
||
模块删除
|
||
→ 根据 s_relation.b_on_delete 展开 cascade
|
||
→ 检查 restrict 外部引用
|
||
→ 执行 s_delete_rule SQL 检查
|
||
→ 同一事务内物理删除
|
||
```
|
||
|
||
这样适合模块数量较多、希望新增模块主要靠配置的场景。`s_relation` 为删除服务提供结构信息,`s_delete_rule` 为业务条件提供 SQL 出口,两者职责明确。
|
||
|
||
### 6.2 SQL 直接处理的适用边界
|
||
|
||
SQL 适合:
|
||
|
||
- 复杂查询和跨表判断。
|
||
- 固定模块的特殊清理逻辑。
|
||
- 数据库外键的 `CASCADE` / `NO ACTION`(物理结构稳定时)。
|
||
|
||
不建议:
|
||
|
||
- 让管理员配置任意 `DELETE SQL` 作为通用删除入口。
|
||
- 用 SQL 文本判断用户菜单权限。
|
||
- 用 SQL 关系自动推导模块父子和权限继承。
|
||
|
||
如果未来选择“完全模块专用 SQL 删除”,迁移顺序应是:先为每个模块补齐删除服务和测试,再停止通用删除服务读取 `s_relation`,最后删除 `b_on_delete`,不能先删元数据再补删除逻辑。
|
||
|
||
## 七、迁移步骤
|
||
|
||
### 阶段 0:盘点和校验
|
||
|
||
1. 统计现有 `s_relation` 行,确认每行的源模块、源字段、目标模块、目标字段真实存在。
|
||
2. 检查重复关系、自引用、无效模块和无效字段。
|
||
3. 盘点旧系统 `s_modulelink` 或其他模块链接数据,确认哪些是菜单绑定,哪些是数据关系,禁止直接整表迁移到 `s_relation`。
|
||
4. 统计菜单、模块、权限之间的现有绑定,找出没有模块权限但已有菜单入口的情况。
|
||
|
||
### 阶段 1:先改语义和界面
|
||
|
||
1. 将模块管理中的“模块关联”改为“数据关系”。
|
||
2. 移除它对菜单权限的描述。
|
||
3. 在菜单管理中明确展示 `s_menu_module` 绑定。
|
||
4. 增加“删除策略”分组,保证 `b_on_delete` 只有一个编辑入口。
|
||
5. 不立即删除数据库列和旧数据,保持兼容。
|
||
|
||
### 阶段 2:拆分权限计算
|
||
|
||
1. 路由和侧栏只根据菜单权限及菜单绑定判断入口。
|
||
2. 页面内模块操作根据 `s_power` / `s_user_power` 独立判断。
|
||
3. 字段和数据范围继续走独立权限表。
|
||
4. 全局搜索确认权限代码没有读取 `s_relation`。
|
||
|
||
### 阶段 3:收敛删除策略
|
||
|
||
1. 删除前条件统一读取 `s_delete_rule`。
|
||
2. 关联删除统一读取 `s_relation.b_on_delete`。
|
||
3. 删除列表入口和 `saveobjt` 使用同一删除服务。
|
||
4. 对 `cascade` 做环路、深度、重复记录和事务回滚测试。
|
||
5. 对 `restrict` 返回引用模块、字段和示例记录,便于用户处理。
|
||
|
||
### 阶段 4:清理旧概念
|
||
|
||
只有在兼容数据完成迁移后,才删除:
|
||
|
||
- 旧的菜单关系字段。
|
||
- 旧的引用规则或重复删除配置。
|
||
- 模块关联面板中的权限文案。
|
||
- 不再使用的关系推导逻辑。
|
||
|
||
## 八、验收标准
|
||
|
||
### 模块树
|
||
|
||
- 模块只能有一个直接父节点。
|
||
- 不能自引用或形成循环。
|
||
- 移动节点后,所有后代的 `b_path`、`b_depth` 正确。
|
||
- 数据字段关系不会改变模块树。
|
||
|
||
### 菜单和权限
|
||
|
||
- 一个菜单可以绑定多个模块。
|
||
- 一个模块可以被多个菜单复用。
|
||
- 勾选模块分类节点只是批量操作,保存后仍是明确绑定行。
|
||
- 只有菜单权限不能直接操作模块数据。
|
||
- 有数据关系的两个模块不会自动互相获得权限。
|
||
|
||
### 数据关系
|
||
|
||
- 关系字段存在且类型可匹配。
|
||
- 关系重复时保存失败。
|
||
- 反向关系可查看,但不会重复提交或误删。
|
||
- `s_relation` 不包含菜单、用户和权限字段。
|
||
|
||
### 删除
|
||
|
||
- `cascade` 能正确删除拥有关系的子记录。
|
||
- `restrict` 能阻止外部引用导致的父记录删除。
|
||
- `none` 不自动处理关联记录,并在配置界面显示风险提示。
|
||
- 删除 SQL 命中时整批回滚。
|
||
- 技术表使用 `target=direct` 时不读取模块关系。
|
||
- 任何检查失败时,不留下部分删除结果。
|
||
|
||
## 九、文件影响范围
|
||
|
||
### 数据库和脚本
|
||
|
||
- `sql/fms_core.sql`:确认 `s_module`、`s_menu`、`s_menu_module`、`s_relation`、`s_power` 的职责注释和字段。
|
||
- `sql/fms_delete_rule.sql`:只保留删除策略迁移和 `s_delete_rule` 初始化。
|
||
- 新增一份关系数据校验/迁移脚本,先报告问题,不直接静默修复。
|
||
|
||
### 前端
|
||
|
||
- `fms-vue/src/views/module/module-management/index.vue`:调整分节名称和数据关系/删除策略的编排。
|
||
- `ModuleRelationPanel.vue`:改名、缩减职责、移除权限语义。
|
||
- `ModuleRulePanel.vue`:作为删除 SQL 规则面板保留。
|
||
- `fms-vue/src/views/module/menu-management/index.vue`:继续以 `s_menu_module` 保存菜单绑定。
|
||
- `stores/permissions.js`:确认权限计算不读取 `s_relation`。
|
||
|
||
### 后端
|
||
|
||
- `DataDeleteService.java`:继续只把 `s_relation` 当作数据关系来源。
|
||
- `SqlPermissionService.java`:权限只读取权限表,不通过数据关系推导。
|
||
- 菜单接口和模块接口分别校验自己的树结构,不能共用一套父子关系处理。
|
||
|
||
## 十、需要确认的唯一决策
|
||
|
||
本计划默认保留通用删除服务,因此保留 `s_relation.b_on_delete` 作为底层删除策略字段,但把编辑入口移到“删除策略”。
|
||
|
||
如果决定所有业务模块都用专用 SQL 或存储过程处理删除,则可以选择另一条路线:
|
||
|
||
```text
|
||
s_relation 只保留数据结构关系
|
||
s_delete_rule 保留删除前检查
|
||
模块删除由各自服务/存储过程完成
|
||
```
|
||
|
||
这条路线的配置更少,但新增模块不能只靠元数据完成删除行为,需要额外编写和测试模块删除逻辑。
|
||
|
||
在当前 FMS 已经存在通用 `DataDeleteService`、模块数量较多的前提下,建议先采用默认方案:**保留数据关系,拆出权限语义,删除策略单独管理,暂不改成纯 SQL 删除。**
|
||
|
||
## 十一、原型演示
|
||
|
||
对应的交互原型位于 [权限分配原型.html](权限分配原型.html),直接用浏览器打开即可查看。
|
||
|
||
原型按常见企业系统的授权路径组织:
|
||
|
||
1. 左侧切换用户,顶部查看当前授权来源和保存状态。
|
||
2. 先选择海运、空运或财务业务域。
|
||
3. 默认选择“未授权、只读、经办、主管”等业务方案,右侧立即预览菜单入口、模块和动作。
|
||
4. 需要精细控制时,在海运业务中打开“详细权限调整”,分别配置菜单、模块、字段和数据范围。
|
||
5. 用“预览最终权限”查看后端实际会收到的授权结果,用“撤销修改”验证未保存变更不会直接生效。
|
||
|
||
原型中的角色方案只是降低管理员理解成本的操作入口,底层仍然落成菜单、模块和动作权限;业务域和模块之间的字段关系没有被用来推导权限。
|