7.7 KiB
7.7 KiB
FMS 删除规则改造待做
创建:设计阶段已闭合、实施未开始。明日开工照此清单执行。 设计依据:
FMS删除规则引擎设计.mdv2.0(权威实现规格)、FMS模块设计评审.mdv1.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.vuedeleteSelected(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 默认生效
注意事项(动工前再读一遍)
sql/fms_delete_rule.sql现有 L22 是drop table if exists s_rule——虽然确认无数据,重写后仍保留 drop+create 模式,但执行前先select count(*)确认一次- 规则引擎是当前最大缺口:现在界面上配的删除规则完全不生效(后端
s_rule相关零实现)。②完成后配置才有意义,①③可以和②并行 - 执行 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 - 改前端遵守
开发规范.md:改前先读、最小修改、不为兼容旧名留转发别名(调用方可控,直接迁移删旧代码) s_rule主键仍是雪花b_id(前端nextIdApi取号,与业务表一致);配置表不用 nextIdApi 的规则是「模块配置表用业务键」——s_rule无天然业务键,属例外(v2.0 §6.2 已注明)