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

7.7 KiB
Raw Blame History

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 已注明)