Files
workspace/code/fms/FMS删除规则改造待做.md
T
2026-09-17 23:13:31 +08:00

74 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FMS 删除规则改造待做
> 创建:设计阶段已闭合、实施未开始。明日开工照此清单执行。
> 设计依据:`FMS删除规则引擎设计.md` **v2.0**(权威实现规格)、`FMS模块设计评审.md` v1.2(决策记录)。
> 前提确认:库中无存量规则/关系数据(`sql/` 种子脚本中 `s_relation` 零 insert),**全部按新结构直接建,不做迁移**。
## 已定案的设计决策(不需要再讨论)
| # | 决策 | 出处 |
| --- | --- | --- |
| 1 | `s_relation.b_on_delete` 单列四值:`restrict`(默认)/ `cascade` / `archive` / `none`;语义统一为「删除**被引用方**时,**引用方**怎么办」;被引用方由基数判定(many_to_one=目标 / one_to_many=源 / one_to_one=源) | 删除规则 v2.0 §3 |
| 2 | 引用保护退出 `s_rule`,由 `b_on_delete='restrict'`(默认)表达;「有引用时拒绝删除」假列及全部联动补丁删除 | 删除规则 v2.0 §3 |
| 3 | `s_rule` 新结构:`b_module_id` 直存、显式 `b_kind`(condition/sql)、去掉 `b_scope_type`/`b_scope_id`/`b_hook` | 删除规则 v2.0 §6.2 |
| 4 | 中间表模块挂业务域 `module` 节点下、与主表模块平级(规范已写入核心表结构设计 §4.3) | 评审 v1.2 问题四 |
| 5 | 模块管理分节改为「数据行为 / 访问控制」,只改 `configGroups` 分组,面板/路由/数据不动;与删除规则前端改造同批实施 | 评审 v1.2 问题二 |
## 待做清单(按执行顺序)
### ① 重写 SQL 脚本 —— 对应设计 v2.0 §6.1 / §6.2
现状:两个脚本还是 v1 结构(`b_on_delete` 默认 `none` 三值、`s_rule` 带 `b_scope_type`/`b_scope_id`/`b_hook`)。
- [ ] `sql/fms_delete_rule.sql` 重写:
- `s_relation.b_on_delete`:四值,**默认 `'restrict'`**(现脚本 L18 默认是 `'none'`)
- `s_rule` 按新结构重建:`b_module_id varchar(50) not null`、`b_kind varchar(20) not null`(condition / sql)、`b_predicate not null`、`b_message`、`b_canuse`、`b_xh`、审计四列;去掉 `b_scope_type`/`b_scope_id`/`b_hook`
- 索引:`ix_s_rule_module on s_rule (b_module_id, b_canuse, b_xh)`
- 保留脚本头「可重复执行」说明与执行方式注释
- [ ] `sql/fms_core.sql` 同步:L208 的 `b_on_delete` 注释与默认值、L228-256 的 `s_rule` 段整体替换(与 `fms_delete_rule.sql` 保持一致,注意两脚本职责分工——core 建全表、delete_rule 只做本特性增量,按现有模式来)
- [ ] 建表 SQL 的 `b_archived` / `b_archive_datetime` 通用列暂不加——它是 `archive` 行为的**运行时前提**(引用方表需有此列),到后端实现时再决定加在哪些业务表
### ② 后端引擎 —— 对应设计 v2.0 §6.4 / §6.5 / §6.6
- [ ] 新建 `DeleteRuleChecker`(检查器):`check(connection, 模块, ids, 小闭包)`
- 模块条件:清单内每个模块的 `s_rule`(`b_canuse=1`)逐条执行;condition → JSON AST 翻译参数化 SQL(AST 格式见 §6.3,嵌套 ≤8 层、节点 ≤100);sql → `:ids` 替换(OPENJSON 数组参数,绕开 2100 绑定变量上限),查出有结果即记错误,**全程写技术日志**(实际 SQL+参数+行数)
- 引用保护:清单内每条记录查它作为被引用方的 `restrict` 入边(`b_on_delete='restrict'` 且 `b_canuse=1`),引用方存在且不在清单内 → 记错误(带引用方单号)
- [ ] 新建 `DeleteRuleExecutor`(执行器):从 ids 出发沿 `b_on_delete ∈ {cascade, archive}` 的关系逐层展开删除清单(被删的是被引用方;已装过跳过防环;超 10 层报配置错误)
- [ ] `DataController` 加 `POST /data/deleteobj`:`{ moduleCode, ids, dryRun }`;dryRun 返回「将删除 X + Y」摘要;真删开事务**重跑检查**(预览通过不算数)→ archive 打标记 → 先子后父物理删 → 审计日志
- [ ] `DataSaveService.saveTable()` delete 分支接入(§6.5,**重要**):
- 真删前按表名反查模块(`b_savetable`),查不到跳过(日志表等)
- 同事务调检查器;**小闭包语义**:本次 saveobjt 所有 deletes 覆盖的 id 传给检查器,引用方也在被删之列不算外部引用
- 不过 → 抛 BusinessException → 整个 saveobjt 回滚
- [ ] 错误消息生成:condition 自动生成人话(带实际值 + 字段格式化:金额 ¥、日期格式);sql 规则用 `b_message` 的 `{列名}` 占位符填充;错误按规则归类、每类带数量和前几条示例
### ③ 前端改造 —— 对应设计 v2.0 §8 步骤 5 + 评审问题二
- [ ] `ModuleRelationPanel.vue`:删除相关从三栏位(`b_relation_type` / `b_on_delete` / `_hasRefRule`)收敛为 `b_relation_type` + `b_on_delete`(四值下拉,默认 restrict)
- 删掉:`_hasRefRule` 假列、`setRefRule`、改关系主键时作废旧键规则及提示(L326-334)、填不全四列禁用 checkbox
- `many_to_one` + `cascade` 不再界面禁用,改保存校验拦截(对齐「校验落后端」原则——若后端引擎做此校验,前端可只做提示)
- [ ] `ModuleRulePanel.vue`:去掉引用规则只读区 + `navigate` 跳转;列表只剩模块级规则(condition / sql)
- [ ] `ModuleRuleEditModal.vue` + `ruleUtils.js`:
- `parseRulePredicate` 三态推断改两态(读 `b_kind`,不再看首字符 `{`)
- 删掉 `relationScopeId` / `parseRelationScopeId` / `isCompleteRelationKey` / `REF_RULE_HINT` / `createRefRuleRow` / `RULE_SCOPE_RELATION`
- `createRuleRow` 带 `b_kind`;新增默认 `condition`
- [ ] `module-management/index.vue`:
- 删 `refRules` / `refRules_org` / `refRulesReverse` 三组数据及加载、diff、清理逻辑(L875-898 关系级规则清理段改为只清模块级)
- `configGroups` 分节调整:「数据行为 → 模块关联(含删除行为) / 删除规则 / 自动编码」「访问控制 → 权限」;section key 不动
- [ ] `FmsModuleListPage.vue` `deleteSelected`(L877):直删改两步——先 `deleteobj dryRun=true`,有错误弹错误列表,无错误弹确认框(含连带摘要),确认后真删
### ④ 验收检查
- [ ] 全局搜索无旧导出残留:`relationScopeId`、`createRefRuleRow`、`REF_RULE_HINT`、`b_scope_type`、`b_scope_id`、`_hasRefRule`、`setRefRule`
- [ ] `pnpm check`(lint + fmt + build)通过
- [ ] 跑受影响模块的前端测试;`ruleUtils` / 面板相关 spec 按新契约更新(测试约定见 `fms-vue/tests/README.md`:文件同名、中文用例名)
- [ ] 后端:`mvnw test`;引擎核心逻辑(检查器翻译、闭包语义、环检测)补测试
- [ ] 手工链路验证:配一条「审核中不可删」→ 列表删被拦(人话提示)→ 表单里删行同样被拦(saveobjt 回滚)→ cascade 关系连带展开预览 → restrict 默认生效
## 注意事项(动工前再读一遍)
1. **`sql/fms_delete_rule.sql` 现有 L22 是 `drop table if exists s_rule`**——虽然确认无数据,重写后仍保留 drop+create 模式,但执行前先 `select count(*)` 确认一次
2. 规则引擎是**当前最大缺口**:现在界面上配的删除规则完全不生效(后端 `s_rule` 相关零实现)。②完成后配置才有意义,①③可以和②并行
3. 执行 SQL 用 `RunSqlFile`:`java -cp "tools/migration/mssql-jdbc-13.4.0.jre11.jar" tools/migration/RunSqlFile.java ../sql/fms_delete_rule.sql --dry-run` 先 dry-run
4. 改前端遵守 `开发规范.md`:改前先读、最小修改、不为兼容旧名留转发别名(调用方可控,直接迁移删旧代码)
5. `s_rule` 主键仍是雪花 `b_id`(前端 `nextIdApi` 取号,与业务表一致);**配置表不用 nextIdApi 的规则是「模块配置表用业务键」**——`s_rule` 无天然业务键,属例外(v2.0 §6.2 已注明)