spec.md 7.8 KB

业务域删除孤立对象优化

status: done created: 2026-08-04 complexity: 🟡中等

1. 背景与目标

应用中心删除业务应用时会保留可复用的业务对象。当业务域下最后一个应用删除后,业务对象仍存在,但应用中心没有独立的全局对象清理入口;此时删除业务域会提示“该业务套件已存在业务对象,不能删除”,用户无法完成业务域清理。

本变更将删除行为调整为显式清理:仍有子业务域、业务应用或访问入口时继续阻止删除;业务域仅剩未被有效应用使用的孤立对象时,在用户确认后清理对象关系、逻辑删除业务对象并逻辑删除业务域。业务数据表、历史设计版本和发布记录不做物理删除。

2. 代码现状(Research Findings)

2.1 相关入口与链路

  • forge-admin-ui/src/views/app-center/index.vueremoveSuite 从应用中心业务域树发起删除。
  • forge-admin-ui/src/views/app-center/suite.[suiteCode].vuedeleteSuite 从旧业务域详情页发起删除。
  • forge-admin-ui/src/api/business-app.jsdeleteBusinessSuite 调用 DELETE /ai/business/suite/{id}
  • BusinessSuiteController.delete 委托 BusinessSuiteService.delete 执行删除。

2.2 现有实现

  • BusinessApplicationService.delete 会逻辑删除应用对象关联,但明确保留业务对象,支持后续复用。
  • BusinessSuiteService.delete 按“子域 → 业务对象 → 访问入口 → 业务应用”顺序校验;只要 ai_business_object 中仍有未删除对象,就直接报“该业务套件已存在业务对象,不能删除”。
  • BusinessSuiteMapper.countObjectsBySuite 已显式过滤 del_flag = 0,问题不是已删除数据误计数,而是应用删除后的业务对象按现有产品语义仍被保留。
  • BusinessApplicationObjectService.validateAndConvert 要求业务应用和业务对象属于同一业务域;应用带对象/入口时也禁止直接迁移业务域。
  • ai_business_object_relation 是关系重建表,现有实现使用物理删除;ai_business_objectai_business_suite 使用主键墓碑逻辑删除。

2.3 发现与风险

  • 直接移除业务对象校验会留下仍可查询、且可能在同编码业务域重建后重新出现的孤立对象,不能采用。
  • 直接无提示级联删除业务对象会扩大现有删除接口语义,其他调用方可能在不知情时丢失设计入口,必须由调用方显式传入清理意图。
  • 业务对象理论上只能被同域应用引用,但删除前仍应按有效应用关联做防御性检查,避免历史脏数据导致误删共享对象。
  • 删除业务域不删除动态业务数据表,不物理清理设计版本、发布版本或运行日志;本轮只清理当前可见的域、对象和对象关系元数据。

3. 功能点

  • 删除业务域时优先校验子域、业务应用和访问入口,提示使用“业务域”术语。
  • 业务域存在业务对象且调用方未明确确认清理时,返回可操作的确认提示。
  • 调用方明确确认且对象未被有效业务应用引用时,事务内物理删除对象关系、逻辑删除业务对象和业务域。
  • 应用中心与旧业务域详情页根据对象数量显示清理影响,并传递显式清理参数。
  • 删除期间若仍有有效应用引用对象,则失败关闭,不清理对象或业务域。

4. 业务规则

  1. 存在未删除子业务域时不能删除。
  2. 存在未删除业务应用或访问入口时不能删除,无论是否传入清理参数。
  3. 存在业务对象时,只有 cleanupOrphanObjects=true 才允许进入孤立对象清理。
  4. 清理前若发现业务对象仍被未删除业务应用通过 ai_business_application_object 引用,则禁止删除。
  5. ai_business_object_relation 属于关系重建表,随业务域删除做物理清理;ai_business_objectai_business_suite 使用 del_flag = id 逻辑删除。
  6. 不删除业务对象对应的业务数据表,不物理删除历史版本、日志或运行数据。

5. 数据变更

操作 表名 字段/索引 说明
物理删除 ai_business_object_relation tenant_id + suite_code 关系重建表,避免同编码业务域重建后读取旧关系
逻辑删除 ai_business_object del_flag = id 仅清理目标业务域当前未删除对象
逻辑删除 ai_business_suite del_flag = id 保持现有 MyBatis-Plus 删除语义

不新增 Flyway 脚本,不修改表结构或索引。

6. 接口变更

操作 接口 方法 变更内容
修改 /ai/business/suite/{id} DELETE 新增可选查询参数 cleanupOrphanObjects,默认 false;显式为 true 时可清理孤立对象

7. 影响范围

  • 后端 generator 插件:业务域删除服务、Mapper 接口和 XML、Controller 参数。
  • 前端管理端:业务域删除 API、应用中心和旧业务域详情页确认文案。
  • 不影响业务应用删除语义,不影响单个业务对象删除接口,不改数据库结构。

8. 风险与关注点

  • ⚠️ 逻辑删除属于设计态元数据状态流转,必须在同一事务内完成,任一步失败时整体回滚。
  • ⚠️ 清理参数默认关闭,避免旧调用方无提示级联清理对象。
  • ⚠️ 物理删除仅限 ai_business_object_relation 关系重建表;业务对象、业务域继续逻辑删除。
  • ⚠️ 不承诺删除动态业务表或历史记录,前端确认文案必须明确边界。

8.5 测试策略

  • 测试范围BusinessSuiteService.delete 的阻断顺序、显式确认、有效应用引用保护、关系清理和逻辑删除调用;Mapper XML 关键 SQL;前端 API 参数与删除确认文案;后端目标模块测试和前端构建。
  • 覆盖率目标:新增删除分支核心场景全部覆盖,不单独设置全模块覆盖率阈值。
  • 独立 Test Spec:是。

9. 待澄清

  • 无。依据当前产品已有“删除应用保留业务对象”语义,业务域删除采用显式确认清理孤立对象。

10. 技术决策

  • 不在 BusinessSuiteService 反向注入 BusinessObjectService,避免与 BusinessObjectService → BusinessSuiteService 形成循环依赖;批量清理由 BusinessSuiteMapper XML 完成。
  • 删除顺序固定为:依赖校验 → 对象有效应用引用校验 → 删除对象关系 → 逻辑删除对象 → 逻辑删除业务域。
  • 前端只在已加载汇总数据表明 objectCount > 0 时传 cleanupOrphanObjects=true;若并发新增对象导致数量变化,后端默认关闭策略会要求重新确认。

11. 执行日志

Task 状态 实际改动文件 备注
Task 1 已完成 BusinessSuiteServiceTest.java Red 因新删除协议缺失而失败,Green 6/6 通过
Task 2 已完成 Controller、Service、Mapper、Mapper XML 显式清理参数与事务内孤立对象清理
Task 3 已完成 前端 API、应用中心、旧业务域详情页 两处入口统一提示清理影响并传参
Task 4 已完成 Spec、Test Spec、Execution Log、memory 完成定向测试、全量回归、构建与静态检查

12. 审查结论

实现符合本 Spec:默认删除协议不会无提示清理对象;显式确认后只物理清理关系重建表,并逻辑删除对象与业务域。定向测试 6/6、前端构建和 XML/差异检查通过。generator 全量 569 个用例中有 2 个失败和 4 个错误,均位于本轮未修改的公式、Binding、扩展版本和运行配置测试,已记录为非本轮阻断项。

13. 确认记录(HARD-GATE)

  • 确认时间:2026-08-04
  • 确认人:用户直接提出修复业务域删除阻断问题;按最小安全范围执行。