# 公式能力扩展 — 执行日志 > change: formula-capability-extension > created: 2026-06-12 > status: apply (Phase 5B-2 完成) --- ## 2026-06-12 | 项目初始化 & Phase 1 启动 | 时间 | 阶段 | 操作 | 结果 | |------|------|------|------| | 2026-06-12 | 初始化 | 创建 spec 文档目录结构 | docs/changes/ → code-copilot/changes/ 迁移 | | 2026-06-12 | Spec | 生成 spec.md | code-copilot/changes/formula-capability-extension/spec.md | | 2026-06-12 | Spec | 生成 tasks.md | code-copilot/changes/formula-capability-extension/tasks.md | | 2026-06-12 | Phase 1 | 调整计划:FormulaDependencyAnalyzer 提前到第一阶段 | 第一阶段仅做领域模型和依赖分析器 | | 2026-06-12 | Phase 1 | FormulaConfig 从 DTO 调整为领域模型 | 纯领域模型,不含持久化注解 | | 2026-06-12 | Phase 1 | 第一阶段禁止项明确 | 禁止 Aviator/CRUD Hook/PublishService/前端/API | --- ## 2026-06-12 | Phase 1 实现完成 | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | T1.1-T1.7 | 7 个源文件 + 1 个测试文件 | FormulaType/Mode, AggregateFunction, FormulaConfig, AggregateConfig, FormulaDependencyAnalyzer | | 2026-06-12 | 测试修复 #1 | @Tag("dev") 注解添加 | Maven surefire 默认不运行带标签的测试,增加 `dev` 后 Tests run: 0 | | 2026-06-12 | 测试修复 #2 | 测试发现配置 | 添加 surefire `dev` 配置解决 | | 2026-06-12 | 测试修复 #3 | 深度校验逻辑 | depthExactly3 测试:间接嵌套 depth=3 应通过,需修正 computeDepth 使用 maxDepth 比较 | | 2026-06-12 | 测试修复 #4 | buildPrereqAdjacency 方向修正 | 边方向应为 B→A(B 先计算,A 后计算),确保 Kahn 排序正确 | | 2026-06-12 | 测试修复 #5 | computeDepth 方向修正 | 改为使用 FormulaConfig.getDependsOn() 方向计算深度 | | 2026-06-12 | 测试修复 #6 | findCycleFrom 方向修正 | 转换为 dependsOn 邻接表后再做 DFS 环检测 | | 2026-06-12 | Phase 1 完成 | 14/14 测试通过 | 0 失败 0 错误 | --- ## 2026-06-12 | Phase 2A 表达式解析与校验 | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | T2A.1 | AviatorAdapter | 封装 Aviator 编译/执行,错误转 FormulaExecutionException | | 2026-06-12 | T2A.2 | ExpressionParser | 解析表达式提取变量,语法校验,依赖交叉检查 | | 2026-06-12 | T2A.3 | FormulaValidationService | 整合三层校验:语法/依赖一致性/DAG分析 | | 2026-06-12 | Phase 2A 完成 | 全部测试通过 | 公式校验链路打通 | --- ## 2026-06-12 | Phase 3A 执行引擎 | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | T3A.1 | ExpressionExecutor | Aviator 表达式执行封装,支持变量绑定 | | 2026-06-12 | T3A.2 | FormulaExecutionEngine | 按 DAG 拓扑顺序执行公式,支持 3 层嵌套 | | 2026-06-12 | T3A.3 | ExecutionResult | 执行结果模型:value/errors/elapsedMs | | 2026-06-12 | T3A.4 | FormulaErrorHandler | 策略模式错误处理,支持降级 | | 2026-06-12 | Phase 3A 完成 | 全部测试通过 | 禁止 AGGREGATE 静默跳过已修复 | --- ## 2026-06-12 | Phase 3B 聚合引擎 | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | T3B.1 | AggregateFunctionExecutor | 支持 SUM/COUNT/AVG/MAX/MIN | | 2026-06-12 | T3B.2 | AggregateEngine | 编排:获取数据→过滤→聚合→返回 | | 2026-06-12 | T3B.3 | AggregateResult | 结果模型:value/totalRowCount/matchedRowCount/errors | | 2026-06-12 | T3B.4 | AggregateValidation | 校验 aggregate config 完整性 + filter 语法 | | 2026-06-12 | Phase 3B 完成 | 130 tests 全部通过 | | --- ## 2026-06-12 | Phase 1-3B 架构审查 | 时间 | 审查项 | 结论 | |------|--------|------| | 2026-06-12 | FormulaConfig 扩展性 | ✅ 通过 | | 2026-06-12 | AggregateConfig 兼容性 | ✅ 通过 | | 2026-06-12 | FormulaExecutionEngine 可扩展性 | ✅ 通过 | | 2026-06-12 | Phase4 集成风险 | ⚠️ 需要在 review 后确认 | | 2026-06-12 | 审查报告 R1 | FormulaExecutionEngine 不允许静默跳过 AGGREGATE → 已修复 | --- ## 2026-06-12 | Phase 4A Runtime 接入 | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | T4A.1 | FormulaRuntimeContext | 运行时上下文:tenantId/suiteCode/sourceObjectCode/fieldValues | | 2026-06-12 | T4A.2 | DbAggregateDataProvider | DB 数据提供者,通过 AiBusinessObjectRelation 映射 | | 2026-06-12 | T4A.3 | FormulaPublishValidator | 发布时公式校验拦截器 | | 2026-06-12 | T4A.4 | AggregateDataProvider 接口 | 数据源抽象接口 | | 2026-06-12 | Phase 4A 完成 | 157 tests 全部通过 | 不假设 relationCode = targetObjectCode | --- ## 2026-06-12 | Phase 4B 持久化接入 | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | T4B.1 | LowcodeFieldSchema.formulaConfig | 字段 Schema 增加 formulaConfig 字段 | | 2026-06-12 | T4B.2 | GenTableColumn.formulaConfig | 数据库实体增加 formula_config 列 | | 2026-06-12 | T4B.3 | DB Migration V1.0.67 | gen_table_column 增加 formula_config TEXT | | 2026-06-12 | T4B.4 | StoredFormulaRuntime | STORED 模式:保存时计算并持久化 | | 2026-06-12 | T4B.5 | VirtualFormulaRuntime | VIRTUAL 模式:读取时动态计算 | | 2026-06-12 | Phase 4B 完成 | 169 tests 全部通过 | | --- ## 2026-06-12 | 技术债修复 R2 | 时间 | 修复项 | 说明 | |------|--------|------| | 2026-06-12 | I1: FormulaExecutionEngine 强制注入 DataProvider | 构造器注入改为强制参数 | | 2026-06-12 | I2: AggregateEngine 接入 FormulaRuntimeContext | 支持运行时上下文传递 | | 2026-06-12 | I3: 抽取 AbstractFormulaRuntime | 消除 Stored/Virtual 88% 代码重复 | | 2026-06-12 | R2 完成 | 169 tests 全部通过 | --- ## 2026-06-12 | Phase 5A Formula API | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | T5A.1 | FormulaController | 4 个 REST 端点 | | 2026-06-12 | T5A.2 | POST /api/ai/business/formula/validate | 公式语法校验 | | 2026-06-12 | T5A.3 | POST /api/ai/business/formula/preview | 公式预览计算 | | 2026-06-12 | T5A.4 | POST /api/ai/business/formula/dependency | 依赖分析 | | 2026-06-12 | T5A.5 | GET /api/ai/business/formula/functions | 可用函数列表 | | 2026-06-12 | T5A.6 | 8 个 DTO | 独立 DTO,OpenAPI 注解 | | 2026-06-12 | Phase 5A 完成 | 177 tests 全部通过 | | --- ## 2026-06-12 | Phase 5B-1 CALC 公式配置 UI | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | 前端调研 | 前端目录结构 & 改造点 | BusinessFieldPropertyPanel.vue 增加公式面板 | | 2026-06-12 | UI 实现 | 公式配置折叠面板 | FormulaType 选择 / FormulaMode 切换 / 表达式输入 / 依赖字段选择 | | 2026-06-12 | 校验集成 | 前端调用 POST /formula/validate | 语法校验 + 结果展示 | | 2026-06-12 | 预览集成 | 前端调用 POST /formula/preview | 样例值输入 + 计算结果展示 | | 2026-06-12 | 保存链路 | formulaConfig → LowcodeFieldSchema | 公式配置保存到字段 Schema | | 2026-06-12 | Phase 5B-1 完成 | allFields 数据适配 | | --- ## 2026-06-12 | UAT 验收 | UAT | 场景 | 结果 | |-----|------|------| | UAT-01 | STORED 公式:amount = price * quantity | ✅ PASS | | UAT-02 | VIRTUAL 公式:amount = price * quantity | ✅ PASS | | UAT-03 | 三层语法校验:price ** | ✅ PASS | | UAT-04 | 循环依赖:A = B+1, B = A+1 | ✅ PASS | | UAT-05 | 删除依赖字段 quantity → 发布阻断 | ⚠️ PARTIAL (GAP) | --- ## 2026-06-12 | UAT-05 修复 | 时间 | 修复 | 说明 | |------|------|------| | 2026-06-12 | FormulaDependencyAnalyzer.validateDependencyFields() | 新增静态方法,校验 dependsOn 字段存在性 | | 2026-06-12 | FormulaPublishValidator.collectFieldNames() | 收集 Schema 中所有字段名 | | 2026-06-12 | FormulaPublishValidatorTest.MissingDependencies | 新增 4 个测试:单缺失/多缺失/全存在/公式依赖公式 | | 2026-06-12 | 测试回归修复 | validCalc 和 chainedFormulas 测试 schema 补全缺失字段 | | 2026-06-12 | UAT-05 修复完成 | 181 tests 全部通过 | --- ## 2026-06-12 | Phase 5B-2 AGGREGATE 公式配置 UI | 时间 | 任务 | 产出 | 说明 | |------|------|------|------| | 2026-06-12 | UI 实现 | AGGREGATE 公式面板 | 聚合函数选择(SUM/COUNT/AVG/MAX/MIN) + 关联对象 + 目标字段 + 过滤条件 | | 2026-06-12 | 关联对象选择 | aggregateRelationOptions computed | 从 allFields 中筛选 REFERENCE 类型字段 | | 2026-06-12 | 保存链路 | buildFormulaConfigPayload | AGGREGATE 类型写入 config.aggregate | | 2026-06-12 | 表单状态 | createFieldForm / onFormulaTypeChange | 初始化和重置 aggregate 字段 | | 2026-06-12 | Phase 5B-2 完成 | 181 tests 全部通过 | 仅修改 BusinessFieldPropertyPanel.vue | --- ## 2026-06-12 | Phase 5B-2 UAT 验收 | UAT | 场景 | 结果 | |-----|------|------| | UAT-AGG-01 | SUM 聚合:totalAmount = SUM(order.amount) | ✅ PASS (后端+UI) | | UAT-AGG-02 | COUNT 聚合:orderCount = COUNT(order.id) | ✅ PASS (后端+UI) | | UAT-AGG-03 | AVG 聚合:avgAmount = AVG(order.amount) | ✅ PASS (后端+UI) | | UAT-AGG-04 | 过滤条件:filter status == 'ACTIVE' | ✅ PASS (后端+UI) | | UAT-AGG-05 | 关联对象缺失 | ⚠️ PARTIAL — AggregateValidation 存在但未集成到发布链路 | | UAT-AGG-06 | 目标字段缺失 | ⚠️ PARTIAL — 同上 | --- ## 当前状态总结 ### 测试统计 | 里程碑 | 测试数 | |--------|--------| | Phase 1 完成 | 14 | | Phase 1-3B | 130 | | Phase 4A | 157 | | Phase 4B | 169 | | Phase 5A | 177 | | UAT-05 修复 | 181 | | Phase 5B-2 | 181 | ### 已实现功能 - ✅ CALC 公式配置 (STORED/VIRTUAL) - ✅ AGGREGATE 公式配置 (SUM/COUNT/AVG/MAX/MIN + 过滤) - ✅ 表达式语法校验 (前端 + API + 发布三层) - ✅ 公式预览计算 - ✅ 循环依赖检测 - ✅ 嵌套深度校验 (max 3) - ✅ 依赖字段缺失检测 (发布阻断) - ✅ formulaConfig 持久化到 LowcodeFieldSchema / GenTableColumn - ✅ StoredFormulaRuntime / VirtualFormulaRuntime - ✅ AbstractFormulaRuntime (消除重复) - ✅ FormulaController (4 REST 端点) - ✅ DbAggregateDataProvider (通过 AiBusinessObjectRelation 映射) ### 已知 Gap - ⚠️ UAT-AGG-05/06: AggregateValidation 未集成到 FormulaPublishValidator - AggregateValidation 类存在且功能完整,但 publish 链路未调用 ### 未实现 (按计划禁止) - ❌ CONDITIONAL UI - ❌ Dependency Graph 可视化 - ❌ 跨对象公式 (V1 不支持) ### 修改文件清单 | 层级 | 文件 | 变更类型 | |------|------|----------| | 后端 domain | FormulaType.java | 新增 | | 后端 domain | FormulaMode.java | 新增 | | 后端 domain | AggregateFunction.java | 新增 | | 后端 domain | FormulaConfig.java | 新增 | | 后端 domain | AggregateConfig.java | 新增 | | 后端 domain | FormulaDependencyAnalyzer.java | 新增 | | 后端 domain | AggregateEngine.java | 新增 | | 后端 domain | AggregateFunctionExecutor.java | 新增 | | 后端 domain | AggregateResult.java | 新增 | | 后端 domain | AggregateValidation.java | 新增 | | 后端 domain | AggregateDataProvider.java | 新增 | | 后端 domain | DependencyAnalysisResult.java | 新增 | | 后端 domain | ExpressionExecutor.java | 新增 | | 后端 domain | ExecutionResult.java | 新增 | | 后端 domain | FormulaErrorHandler.java | 新增 | | 后端 service | AviatorAdapter.java | 新增 | | 后端 service | ExpressionParser.java | 新增 | | 后端 service | FormulaValidationService.java | 新增 | | 后端 service | FormulaPublishValidator.java | 新增 | | 后端 service | FormulaExecutionEngine.java | 新增 | | 后端 service | DbAggregateDataProvider.java | 新增 | | 后端 service | FormulaRuntimeContext.java | 新增 | | 后端 service | StoredFormulaRuntime.java | 新增 | | 后端 service | VirtualFormulaRuntime.java | 新增 | | 后端 service | AbstractFormulaRuntime.java | 新增 | | 后端 controller | FormulaController.java | 新增 | | 后端 dto | LowcodeFieldSchema.java | 修改 (+formulaConfig) | | 后端 dto | GenTableColumn.java | 修改 (+formulaConfig) | | 后端 db | V1.0.67__add_formula_config.sql | 新增 | | 后端 dependency | pom.xml (aviator) | 修改 | | 前端 | BusinessFieldPropertyPanel.vue | 修改 (+公式面板 +AGGREGATE UI) | | 前端 | src/api/formula.js | 新增 | --- ## 下一步 1. **修复 UAT-AGG-05/06 Gap**: 集成 AggregateValidation 到 FormulaPublishValidator 2. **Phase 5B-3**: CONDITIONAL 公式配置 UI 3. **Phase 5C**: Dependency Graph 可视化 --- ## 2026-06-12 | R1 修复 — AggregateValidation 集成 | 时间 | 修复 | 说明 | |------|------|------| | 2026-06-12 | AggregateDataException | 新增异常类,用于运行时数据提供者错误 | | 2026-06-12 | DbAggregateDataProvider | 6处 silent empty → throw AggregateDataException | | 2026-06-12 | AggregateFunctionExecutor | computeSum/computeAvg: all-null targetField → throw | | 2026-06-12 | AggregateEngine | execute(config,context) 捕获 AggregateDataException → ErrorResult | | 2026-06-12 | FormulaPublishValidator | 集成 AggregateValidation.validateFormula() | | 2026-06-12 | FormulaPublishValidator.validateAggregateFormulas() | 新增方法,遍历 AGGREGATE config 合并校验错误 | | 2026-06-12 | FormulaPublishValidatorTest.AggregateConfigValidation | 新增 5 个测试 | | 2026-06-12 | DbAggregateDataProviderTest | 7 个 invalid input 测试改为 assertThrows | | 2026-06-12 | R1 修复完成 | **186 tests, 0 failures, BUILD SUCCESS** | ### 风险状态 | 风险 | 状态 | |------|------| | R1: AggregateValidation 未集成 | ✅ 已关闭 | | R2: 缺失 relation 静默返回空 | ✅ 已关闭 (抛 AggregateDataException) | | R3: 缺失 targetField 静默跳过 | ✅ 已关闭 (抛 AggregateExecutionException) |