export const meta = { name: 'erp-p3-crosscut', description: 'P3贯穿性:统一审计日志/外部对接框架/可配置规则引擎/金额精度 4工作流并行(全新建+回传共享片段)', phases: [{ title: 'P3并行建设' }], } const COMMON = `黄金模板:web/FinancingController.java、聚合 web/FundPoolController.java、引擎 service/TriggerRuleEngine.java、前端 oa/pages/payment/financing.vue。 硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double算钱);②@RestController @RequestMapping("/api/oa/<资源>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400,中文);③仓库extends JpaRepository;④前端真实页接真后端(import { http },已解包ApiResp.data,token键oa.token),套MasterDataPage或el-table自定义;⑤无emoji(@element-plus/icons-vue)、无渐变(纯色蓝)、排版承载形态慎重;⑥类名表名加域前缀,grep确认不撞名(现有~120控制器)。 **关键纪律**:①**只新建文件**,凡需改共享文件(config/AuthInterceptor.java、data/oaModules.ts、service/TriggerRuleEngine.java、service/WorkflowService.java、config/WebConfig.java或注册Interceptor处、主类@EnableScheduling、application.yml)一律不自改,放进 sharedFileSnippets(file+anchor原文+change改法+why)由主代理串行合并;②**不运行gradle/npm**,逐文件自审语法;③改动须**加法式**,绝不破坏现有7条联动链与审批流。` const RESULT = { type: 'object', additionalProperties: false, properties: { workstream: { type: 'string' }, backendFiles: { type: 'array', items: { type: 'string' } }, frontendFiles: { type: 'array', items: { type: 'string' } }, authFinancePrefixes: { type: 'array', items: { type: 'string' } }, authSensitiveRead: { type: 'array', items: { type: 'string' } }, navEntries: { type: 'array', items: { type: 'object', additionalProperties: false, properties: { moduleId: { type: 'string' }, items: { type: 'array', items: { type: 'object', additionalProperties: false, properties: { key: { type: 'string' }, label: { type: 'string' }, kind: { type: 'string' }, path: { type: 'string' } }, required: ['key', 'label', 'kind', 'path'] } } }, required: ['moduleId', 'items'] } }, sharedFileSnippets: { type: 'array', items: { type: 'object', additionalProperties: false, properties: { file: { type: 'string' }, anchor: { type: 'string' }, change: { type: 'string' }, why: { type: 'string' } }, required: ['file', 'anchor', 'change', 'why'] } }, endpoints: { type: 'array', items: { type: 'string' } }, summary: { type: 'string' }, }, required: ['workstream', 'backendFiles', 'frontendFiles', 'authFinancePrefixes', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'endpoints', 'summary'], } const WS = [ { key: 'auditlog', label: '统一操作审计日志', prompt: `工作流【统一操作审计日志+哈希存证】(审计:多处合规/审计 MISSING 共用此基础设施)。全新建: ①domain/OperationAuditLog.java(操作审计:操作人/角色/方法/路径/资源类型/资源id/结果状态码/IP/时间戳/prevHash/hash)+仓库。 ②config/AuditLogInterceptor.java(HandlerInterceptor,afterCompletion 记录所有写请求 POST/PUT/PATCH/DELETE 到 /api/oa/**:谁/何时/方法/路径/响应码;哈希链:hash=sha256(prevHash+本条规范化字段),prevHash取上一条hash,形成不可篡改链)。 ③web/OperationAuditLogController.java(只读:GET 列表/详情/按操作人按资源查;**不提供任何删改端点**=不可删)。 前端挂 audit 模块"操作审计台账"页(接真后端,列出操作流水+哈希链状态)。 共享片段(回传勿自改):config/WebConfig.java(或 WebMvcConfigurer 注册 Interceptor 处)加 registry.addInterceptor(auditLogInterceptor) 的片段;AuthInterceptor 把 /api/oa/operation-audit-logs 加进 SENSITIVE_READ_PREFIXES;oaModules audit 模块导航。`, }, { key: 'integration', label: '外部对接框架', prompt: `工作流【外部对接框架】(审计:DataSyncLog 仅手工台账,无执行器/适配器/定时任务,三系统对接未实现)。全新建(加法式,不动现有DataSyncLog读): ①domain/ExternalSystemConfig.java(对接系统:名称/类型 财务T+/ERP/银企直连/政务/类型 出站入站/endpoint/启用)+仓库+web/ExternalSystemConfigController.java(CRUD)。 ②service/IntegrationExecutor.java + 适配器接口 SyncAdapter(模拟适配器 MockSyncAdapter:把一条同步任务标记为执行中→成功/失败,写回 DataSyncLog 状态;真实外部连接留 TODO 接口);web/IntegrationController.java(POST /integrations/sync/{dataSyncLogId} 手工触发执行一条同步;POST /integrations/run-pending 批量跑待同步)。 ③定时拉起:用 @Scheduled(fixedDelayString) 周期扫描待同步任务执行(若主类无 @EnableScheduling,把"在主类加 @EnableScheduling"作为共享片段回传)。 前端挂 datacenter 模块"外部对接配置"+"同步执行"页(接真后端,展示对接系统/手工触发同步/同步结果)。 共享片段(回传勿自改):主类 @EnableScheduling(如未启用);AuthInterceptor /api/oa/external-systems + /api/oa/integrations 写口收口;oaModules datacenter 导航。`, }, { key: 'ruleconfig', label: '可配置规则引擎', prompt: `工作流【可配置规则引擎】(审计:TriggerRuleEngine 硬编码中文关键词路由,非"可配置/规范化")。**加法式**,绝不破坏现有硬编码7条链: ①domain/RuleConfig.java(可配置联动规则:规则名/触发分类关键词 triggerTags/匹配字段 field/比较算子 op(>=/<=/==/contains)/阈值/动作 action/动作参数/启用/优先级)+仓库+web/RuleConfigController.java(CRUD)。 ②前端挂 appdev 模块"联动规则配置"页(管理员可视化增删规则,接真后端)。 ③共享片段(回传勿自改,关键):给 service/TriggerRuleEngine.java 的 fire(...) 末尾追加一段"**先跑硬编码规则(现状不动),再读 RuleConfigRepository 启用规则做补充匹配触发**"的片段(读规则→对当前实例字段求值→命中则执行 action + 写 AutomationLog,幂等用 (instanceId, "ruleconfig:"+规则id))。务必加法式:现有规则全部保留,RuleConfig 只新增可配置规则,不改现有 ruleKey。把"在 TriggerRuleEngine 注入 RuleConfigRepository + 在 fire 末尾调用 applyConfiguredRules(inst,...)"的精确锚点+片段回传。 AuthInterceptor /api/oa/rule-configs 写口收口(管理员)。`, }, { key: 'money', label: '金额精度收口', prompt: `工作流【金额精度收口】(审计:自动付款单出现 5.07、9.9999999997 等 double 精度伪值;parseNumber 走 double 未按 scale 规整)。 排查:grep 全后端 service/ 与 web/ 里仍用 double 做金额运算或 parseNumber 后未经 Money 规整的点(重点 service/TriggerRuleEngine.java、service/WorkflowService.java 的 parseNumber 及其金额下游;任何 new BigDecimal(double) / 直接 double 相加做金额)。 **不要自改共享文件**(TriggerRuleEngine/WorkflowService),把每处问题以 sharedFileSnippets 回传:file+anchor(问题原文)+change(改为 Money.of/Money.add/Money.sub 或 BigDecimal.valueOf+setScale(2,HALF_UP) 的修法)+why。若发现纯新建的辅助类能收口(如一个金额解析工具),可新建。 目标:金额解析与运算全程 BigDecimal+scale2,杜绝 5.07/9.9999999997 类浮点伪值。列出所有发现点与修法。`, }, ] phase('P3并行建设') const results = await parallel(WS.map((w) => () => agent( `你是资深全栈/架构工程师,为凯迪 ERP 平台做 P3 贯穿性基础设施。${w.prompt}\n\n${COMMON}\n\n返回结构化结果(sharedFileSnippets 要给精确 anchor 原文+change 改法)。`, { label: `P3:${w.key}`, phase: 'P3并行建设', schema: RESULT } ) )).then((a) => a.filter(Boolean)) return { built: results.length, results }