SNAPSHOT W7 已部署稳定态 — 凯迪ERP+OA一体化平台 (MET 73.3%)
恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。 == 此快照内容 == - 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091) - 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static) - 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB) - 交接文档 go.md + go-code-reference/endpoints/entities/database.md - 多代理建设脚本 .claude/wf-*.js == 状态 == - 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板) - 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用 - W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成) - 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456 == 排除(gitignore, 可再生) == node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui) 完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules) 时间戳: 20260615-191517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "oa",
|
||||
"runtimeExecutable": "bash",
|
||||
"runtimeArgs": [
|
||||
"-c",
|
||||
"cd /Users/qiu/Desktop/ERP/oa-backend && exec /Users/qiu/Desktop/ERP/.jdks/jdk-17.0.19+10/Contents/Home/bin/java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091"
|
||||
],
|
||||
"port": 8091,
|
||||
"autoPort": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
export const meta = {
|
||||
name: 'erp-audit-lean',
|
||||
description: '精简合规审计:29机构sonnet覆盖审计(只R1功能覆盖,无验证/链/批判),快速量化MET/PARTIAL/MISSING+剩余缺口',
|
||||
phases: [{ title: '功能覆盖审计' }],
|
||||
}
|
||||
|
||||
const IMPL = `现系统:后端 ~717 控制器(oa-backend/src/main/java/com/kaidi/oa/web)、~697 实体、前端模块页(ofbiz-framework/plugins/modern-ui/app/src/oa/pages)。活体 http://127.0.0.1:8091 登录 POST /api/oa/auth/login {"loginName":"admin","password":"123456"} 取token带 Authorization: Bearer。经P0-P3+W1+W2+W3三批深建(W3刚补完156缺口)。注意:子资源控制器base路径无GET属正常(子路径如/events /summary可达),勿据此判MISSING。`
|
||||
|
||||
const FINDINGS = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
dept: { type: 'string' }, suborg: { type: 'string' },
|
||||
modules: { type: 'array', items: {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
module: { type: 'string' },
|
||||
verdict: { type: 'string', enum: ['MET', 'PARTIAL', 'MISSING', 'LOGIC_GAP'] },
|
||||
evidence: { type: 'string', description: '控制器/实体/页面/端点证据; MISSING写无' },
|
||||
gap: { type: 'string', description: '缺什么; MET留空' },
|
||||
severity: { type: 'string', enum: ['none', 'low', 'med', 'high'] },
|
||||
},
|
||||
required: ['module', 'verdict', 'evidence', 'gap', 'severity'],
|
||||
} },
|
||||
},
|
||||
required: ['dept', 'suborg', 'modules'],
|
||||
}
|
||||
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const FILES = [
|
||||
'01_创新研发中心__产品开发部','02_创新研发中心__申报服务部','03_创新研发中心__知识产权部','04_创新研发中心__实验室',
|
||||
'05_设计研究中心__咨询可研院','06_设计研究中心__规划设计部','07_设计研究中心__工程监理部',
|
||||
'08_制造管理中心__环保设备制造中心','09_制造管理中心__生物质肥料制造中心',
|
||||
'10_工程管理中心__质安部','11_工程管理中心__资料室','12_工程管理中心__专利工法办','13_工程管理中心__成本控制部',
|
||||
'14_运营管理中心__城镇污水运营中心','15_运营管理中心__工业废水运营中心',
|
||||
'16_市场部__经营部','17_市场部__办事处','18_市场部__分公司',
|
||||
'19_支付中心__结算中心','20_支付中心__财务部','21_支付中心__金融办',
|
||||
'22_内控部__法务风险部','23_内控部__审计监察部',
|
||||
'24_品牌推广部__宣传部','25_品牌推广部__项目文化',
|
||||
'26_行政__综合部','27_行政__信息部','28_行政__办公室','29_行政__后勤',
|
||||
]
|
||||
|
||||
phase('功能覆盖审计')
|
||||
const findings = await parallel(FILES.map((fn) => () =>
|
||||
agent(
|
||||
`你是 ERP 需求合规审计员。先 Read 需求切片 ${SLICE}/${fn}.txt。${IMPL}
|
||||
对该机构需求里【每个功能模块(## 标题)】,grep/读码/活体取证判定现系统实现度:MET(真工作流+联动落地)/PARTIAL(有承载缺部分子功能)/LOGIC_GAP(有页缺关键逻辑联动)/MISSING(无实现)。基于真实代码不臆测,给每个模块一条结论+证据+缺口+severity。`,
|
||||
{ label: `审:${fn.split('__')[1]}`, phase: '功能覆盖审计', schema: FINDINGS, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
// 汇总
|
||||
const counts = { MET: 0, PARTIAL: 0, LOGIC_GAP: 0, MISSING: 0 }
|
||||
const gaps = []
|
||||
for (const f of findings) {
|
||||
for (const m of (f.modules || [])) {
|
||||
counts[m.verdict] = (counts[m.verdict] || 0) + 1
|
||||
if (m.verdict !== 'MET') gaps.push({ area: `${f.dept}/${f.suborg}`, module: m.module, verdict: m.verdict, gap: m.gap, severity: m.severity })
|
||||
}
|
||||
}
|
||||
const total = counts.MET + counts.PARTIAL + counts.LOGIC_GAP + counts.MISSING
|
||||
log(`审计完成: MET${counts.MET} PARTIAL${counts.PARTIAL} LOGIC${counts.LOGIC_GAP} MISS${counts.MISSING} / 共${total}`)
|
||||
return { units: findings.length, counts, total, metPct: total ? (counts.MET * 100 / total).toFixed(1) : 0, gaps }
|
||||
@@ -0,0 +1,312 @@
|
||||
export const meta = {
|
||||
name: 'erp-req-compliance-audit',
|
||||
description: 'ERP xlsx 需求 vs 现系统:三轮全量合规审计(功能覆盖/逻辑流程链/对抗复验)+完整性批判,产出合规报告与缺口清单',
|
||||
phases: [
|
||||
{ title: 'R1功能覆盖' },
|
||||
{ title: 'R1对抗验证' },
|
||||
{ title: 'R2逻辑流程链' },
|
||||
{ title: 'R3完整性批判' },
|
||||
{ title: 'R3缺口复验' },
|
||||
{ title: '汇总报告' },
|
||||
],
|
||||
}
|
||||
|
||||
// ---- 现系统实现面(给审计员定位用,避免空跑) ----
|
||||
const IMPL_MAP = `【前端模块 33(定义 ofbiz-framework/plugins/modern-ui/app/src/data/oaModules.ts,路由 src/router/,页面 src/oa/**、src/components/erp/**)】
|
||||
orgview组织视图 collab协同工作 appdev应用定制平台 report报表中心 goal目标管理 meeting会议管理 knowledge知识社区 doccollab文档协作 culture文化建设 hr-HR管理 masterdata主数据中心 contract合同中心 payment资金支付中心 sealcenter用章中心 archive档案知识中心 intel统一情报中心 crm统一CRM bidding统一招投标 ehs统一EHS rd研发创新中心 budget预算成本中心 datacenter数据中心 ops运营管理中心 mfg制造管理中心 finance财务管理 lab实验室 design设计研究中心 supervision工程监理 audit审计监察 itasset信息中心 admin行政后勤中心 legal法务合规中心 mobile移动工作台
|
||||
【后端控制器 ~90(oa-backend/src/main/java/com/kaidi/oa/web/*.java)】
|
||||
Account Alert Announcement AppMonitoring ArchiveComment Archive AuditProject Auth Automation BankAccount Bid BizRecord Blog BomAnalysis BomItem Budget BusinessBi Certification CollabDoc CompanySubject Contract ContractChange ContractMilestone ContractTemplate CostCenter CrawlJob CrawlSource Customer DataCenter DataSyncLog Declaration DeclarationStep DeclarationTemplate Delegation Dept DesignChange DesignDoc Discussion Document Evidence Expert Favorite Feed File Folder FormInstance FormTemplate FundPool Handover HealthRecord Intel InventoryItem Invoice ItAsset LabInstrument LabSample LeaderTrip Meeting MeetingMinute MeetingRoom Message Mobile Opportunity OpportunityFollowup Patent Payment PersonnelCert PolicyApplication Policy PriceItem Project ProjectTask QmsRecord RdExpense RdProject Report ReportDefinition Role SafetyCheck ScheduleEvent Seal SealUse Search Setting StandardCost Supervision Supplier Survey Task User Voucher WastewaterClient WaterQualityRecord WaterTrace WorkOrder WorkPlan
|
||||
【关键逻辑引擎】service/WorkflowService.java(审批流转/条件分支) service/TriggerRuleEngine.java(办结后下游自动联动) domain/AutomationLog(联动留痕)
|
||||
【活体】http://127.0.0.1:8091 登录 POST /api/oa/auth/login {"loginName":"admin","password":"123456"} 取 token,带 Authorization: Bearer <token>`
|
||||
|
||||
const REPO = `前端 ofbiz-framework/plugins/modern-ui/app/src ;后端 oa-backend/src/main/java/com/kaidi/oa`
|
||||
|
||||
// ---- schemas ----
|
||||
const FINDINGS = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
dept: { type: 'string' }, suborg: { type: 'string' },
|
||||
modules: {
|
||||
type: 'array', items: {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
module: { type: 'string' },
|
||||
verdict: { type: 'string', enum: ['MET', 'PARTIAL', 'MISSING', 'LOGIC_GAP'] },
|
||||
evidence: { type: 'string', description: '具体文件:行/路由/控制器端点/实体字段;MISSING写"无"' },
|
||||
gap: { type: 'string', description: '缺什么或逻辑哪里不符;MET留空' },
|
||||
severity: { type: 'string', enum: ['none', 'low', 'med', 'high'] },
|
||||
},
|
||||
required: ['module', 'verdict', 'evidence', 'gap', 'severity'],
|
||||
},
|
||||
},
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['dept', 'suborg', 'modules', 'summary'],
|
||||
}
|
||||
|
||||
const VERIFY = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
revised: {
|
||||
type: 'array', items: {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
module: { type: 'string' },
|
||||
finalVerdict: { type: 'string', enum: ['MET', 'PARTIAL', 'MISSING', 'LOGIC_GAP'] },
|
||||
overturned: { type: 'boolean', description: '是否推翻初判' },
|
||||
evidence: { type: 'string' },
|
||||
gap: { type: 'string' },
|
||||
},
|
||||
required: ['module', 'finalVerdict', 'overturned', 'evidence', 'gap'],
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ['revised'],
|
||||
}
|
||||
|
||||
const CHAIN = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
chain: { type: 'string' },
|
||||
verdict: { type: 'string', enum: ['MET', 'PARTIAL', 'MISSING', 'LOGIC_GAP'] },
|
||||
steps: {
|
||||
type: 'array', items: {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
step: { type: 'string' },
|
||||
status: { type: 'string', enum: ['有', '部分', '缺'] },
|
||||
evidence: { type: 'string' },
|
||||
},
|
||||
required: ['step', 'status', 'evidence'],
|
||||
},
|
||||
},
|
||||
gap: { type: 'string' },
|
||||
severity: { type: 'string', enum: ['none', 'low', 'med', 'high'] },
|
||||
},
|
||||
required: ['chain', 'verdict', 'steps', 'gap', 'severity'],
|
||||
}
|
||||
|
||||
const CRITIC = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
suspiciousMet: { type: 'array', items: { type: 'string' }, description: '被判 MET 但可疑、需重查的功能模块' },
|
||||
underCovered: { type: 'array', items: { type: 'string' }, description: '整体覆盖不足、需补审的机构/领域' },
|
||||
note: { type: 'string' },
|
||||
},
|
||||
required: ['suspiciousMet', 'underCovered', 'note'],
|
||||
}
|
||||
|
||||
const VERDICT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
real: { type: 'boolean', description: 'true=缺口属实(确实未实现/逻辑确缺);false=其实已实现,缺口不成立' },
|
||||
note: { type: 'string' },
|
||||
evidence: { type: 'string' },
|
||||
},
|
||||
required: ['real', 'note', 'evidence'],
|
||||
}
|
||||
|
||||
const REPORT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
overallVerdict: { type: 'string' },
|
||||
coveragePct: { type: 'number' },
|
||||
counts: {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: { met: { type: 'number' }, partial: { type: 'number' }, missing: { type: 'number' }, logicGap: { type: 'number' } },
|
||||
required: ['met', 'partial', 'missing', 'logicGap'],
|
||||
},
|
||||
reportMarkdown: { type: 'string', description: '完整 markdown 合规报告(含覆盖统计、按机构表、5条流程链状态、按严重度的缺口清单、整改建议)' },
|
||||
},
|
||||
required: ['overallVerdict', 'coveragePct', 'counts', 'reportMarkdown'],
|
||||
}
|
||||
|
||||
// ---- 审计单元(29 个二级机构;各代理读自己的需求切片文件)----
|
||||
const SLICE_DIR = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const units = [
|
||||
{ n: 1, dept: '创新研发中心', sub: '产品开发部', file: `${SLICE_DIR}/01_创新研发中心__产品开发部.txt` },
|
||||
{ n: 2, dept: '创新研发中心', sub: '申报服务部', file: `${SLICE_DIR}/02_创新研发中心__申报服务部.txt` },
|
||||
{ n: 3, dept: '创新研发中心', sub: '知识产权部', file: `${SLICE_DIR}/03_创新研发中心__知识产权部.txt` },
|
||||
{ n: 4, dept: '创新研发中心', sub: '实验室', file: `${SLICE_DIR}/04_创新研发中心__实验室.txt` },
|
||||
{ n: 5, dept: '设计研究中心', sub: '咨询可研院', file: `${SLICE_DIR}/05_设计研究中心__咨询可研院.txt` },
|
||||
{ n: 6, dept: '设计研究中心', sub: '规划设计部', file: `${SLICE_DIR}/06_设计研究中心__规划设计部.txt` },
|
||||
{ n: 7, dept: '设计研究中心', sub: '工程监理部', file: `${SLICE_DIR}/07_设计研究中心__工程监理部.txt` },
|
||||
{ n: 8, dept: '制造管理中心', sub: '环保设备制造中心', file: `${SLICE_DIR}/08_制造管理中心__环保设备制造中心.txt` },
|
||||
{ n: 9, dept: '制造管理中心', sub: '生物质肥料制造中心', file: `${SLICE_DIR}/09_制造管理中心__生物质肥料制造中心.txt` },
|
||||
{ n: 10, dept: '工程管理中心', sub: '质安部', file: `${SLICE_DIR}/10_工程管理中心__质安部.txt` },
|
||||
{ n: 11, dept: '工程管理中心', sub: '资料室', file: `${SLICE_DIR}/11_工程管理中心__资料室.txt` },
|
||||
{ n: 12, dept: '工程管理中心', sub: '专利工法办', file: `${SLICE_DIR}/12_工程管理中心__专利工法办.txt` },
|
||||
{ n: 13, dept: '工程管理中心', sub: '成本控制部', file: `${SLICE_DIR}/13_工程管理中心__成本控制部.txt` },
|
||||
{ n: 14, dept: '运营管理中心', sub: '城镇污水运营中心', file: `${SLICE_DIR}/14_运营管理中心__城镇污水运营中心.txt` },
|
||||
{ n: 15, dept: '运营管理中心', sub: '工业废水运营中心', file: `${SLICE_DIR}/15_运营管理中心__工业废水运营中心.txt` },
|
||||
{ n: 16, dept: '市场部', sub: '经营部', file: `${SLICE_DIR}/16_市场部__经营部.txt` },
|
||||
{ n: 17, dept: '市场部', sub: '办事处', file: `${SLICE_DIR}/17_市场部__办事处.txt` },
|
||||
{ n: 18, dept: '市场部', sub: '分公司', file: `${SLICE_DIR}/18_市场部__分公司.txt` },
|
||||
{ n: 19, dept: '支付中心', sub: '结算中心', file: `${SLICE_DIR}/19_支付中心__结算中心.txt` },
|
||||
{ n: 20, dept: '支付中心', sub: '财务部', file: `${SLICE_DIR}/20_支付中心__财务部.txt` },
|
||||
{ n: 21, dept: '支付中心', sub: '金融办', file: `${SLICE_DIR}/21_支付中心__金融办.txt` },
|
||||
{ n: 22, dept: '内控部', sub: '法务风险部', file: `${SLICE_DIR}/22_内控部__法务风险部.txt` },
|
||||
{ n: 23, dept: '内控部', sub: '审计监察部', file: `${SLICE_DIR}/23_内控部__审计监察部.txt` },
|
||||
{ n: 24, dept: '品牌推广部', sub: '宣传部', file: `${SLICE_DIR}/24_品牌推广部__宣传部.txt` },
|
||||
{ n: 25, dept: '品牌推广部', sub: '项目文化', file: `${SLICE_DIR}/25_品牌推广部__项目文化.txt` },
|
||||
{ n: 26, dept: '行政', sub: '综合部', file: `${SLICE_DIR}/26_行政__综合部.txt` },
|
||||
{ n: 27, dept: '行政', sub: '信息部', file: `${SLICE_DIR}/27_行政__信息部.txt` },
|
||||
{ n: 28, dept: '行政', sub: '办公室', file: `${SLICE_DIR}/28_行政__办公室.txt` },
|
||||
{ n: 29, dept: '行政', sub: '后勤', file: `${SLICE_DIR}/29_行政__后勤.txt` },
|
||||
]
|
||||
log(`审计单元 ${units.length} 个(二级机构);开始 R1 功能覆盖审计`)
|
||||
|
||||
function auditPrompt(u) {
|
||||
return `你是 ERP 需求合规审计员。审计单元:${u.dept} / ${u.sub}。
|
||||
第一步:用 Read 工具读取本单元的需求规格文件(xlsx 原文逐功能模块):${u.file}
|
||||
${IMPL_MAP}
|
||||
代码位置:${REPO}
|
||||
|
||||
任务:对该需求文件里【每一个功能模块(## 标题)】,判定现系统是否实现且逻辑正确。必须用 grep/读码找真实证据(文件:行 / 路由 / 控制器端点 / 实体字段 / 前端页面),可调活体接口佐证。判定档:
|
||||
- MET 完整实现且逻辑符合需求
|
||||
- PARTIAL 有页面/接口但只覆盖一部分子功能
|
||||
- LOGIC_GAP 有承载页但关键逻辑/自动联动/自动采集/校验缺失(表面有、逻辑空)
|
||||
- MISSING 无任何对应实现
|
||||
严禁臆测;找不到证据一律 MISSING。gap 写清缺什么。severity 按业务重要性(high/med/low/none)。需求文件里每个功能模块都要给一条结论。`
|
||||
}
|
||||
|
||||
function verifyPrompt(u, gaps) {
|
||||
return `对抗验证员。审计单元 ${u.dept}/${u.sub}。先 Read 需求切片文件:${u.file}
|
||||
下面是对若干功能模块的"非达标"初判,你的职责是**尽力反驳**——在代码里努力找出它其实已实现(可能换了名字/并入别的模块/在别的控制器)。能找到确凿证据就翻案(overturned=true)给出 finalVerdict 与 evidence;找不到则维持并确认 gap。
|
||||
【待验证初判】
|
||||
${gaps.map((g) => `- 【${g.module}】初判 ${g.verdict}:${g.gap}`).join('\n')}
|
||||
${IMPL_MAP}
|
||||
代码位置:${REPO}
|
||||
对每条给最终判定。基于真实代码,不放水也不冤枉。`
|
||||
}
|
||||
|
||||
// ===== R1: 功能覆盖审计 → 对抗验证(pipeline,无屏障)=====
|
||||
const r1 = await pipeline(
|
||||
units,
|
||||
(u) => agent(auditPrompt(u), { label: `审计:${u.sub}`, phase: 'R1功能覆盖', schema: FINDINGS, model: 'sonnet' }),
|
||||
(finding, u) => {
|
||||
if (!finding) return null
|
||||
const gaps = (finding.modules || []).filter((m) => m.verdict !== 'MET')
|
||||
if (!gaps.length) return finding
|
||||
return agent(verifyPrompt(u, gaps), { label: `验证:${u.sub}`, phase: 'R1对抗验证', schema: VERIFY, model: 'sonnet' })
|
||||
.then((v) => {
|
||||
if (v && Array.isArray(v.revised)) {
|
||||
const map = new Map(v.revised.map((r) => [r.module, r]))
|
||||
finding.modules = finding.modules.map((m) => {
|
||||
const r = map.get(m.module)
|
||||
return r ? { ...m, verdict: r.finalVerdict, evidence: r.evidence || m.evidence, gap: r.gap } : m
|
||||
})
|
||||
}
|
||||
return finding
|
||||
})
|
||||
}
|
||||
)
|
||||
const r1ok = r1.filter(Boolean)
|
||||
log(`R1 完成:${r1ok.length}/${units.length} 单元有结果`)
|
||||
|
||||
// ===== R2: 逻辑/流程链审计(xlsx 强调的"逻辑要求")=====
|
||||
const CHAINS = [
|
||||
{ key: '工程业务流程', desc: '查网→制作标书→开标→领取中标通知书→签订总包合同→施工前准备→施工图审查→材料等分包合同→办理施工许可证→季度考评→竣工备案→资料存档。逐环节核对是否有承载与流转。' },
|
||||
{ key: '合同流程', desc: '供应商入库→系统取模板合同(IT维护更新)→线上填写→自动化比对→合约部在线审核→进入OA审批→通知合同专员下载并上传盖章电子合同(电子签自动进入盖章系统)。重点查模板取用、自动化比对、用印联动。' },
|
||||
{ key: '资金确认', desc: '项目部向甲方请款→财务资金到账确认→开票→应付入账。查请款单、到账确认、发票、应付凭证联动。' },
|
||||
{ key: '支付流程', desc: '供应商→人材机审核确认→支付申请→打款→写入财务系统。查支付申请审批、打款、写财务。' },
|
||||
{ key: '资料流程', desc: '项目部→办事处→资料室→工程中心→法务→董事长→档案室。查多级流转归档链。' },
|
||||
{ key: '流程驱动/自动触发', desc: '数据中心统一数据库、流程驱动:条件生成后系统自动触发成本风险检查/生产排程/财务记账等后续流程(规范化/自动化/AI化)。重点查 TriggerRuleEngine 是否有真实下游联动规则。' },
|
||||
{ key: '跨模块数据自动采集', desc: '申报条件自查自动从财务/HR/知识产权/项目模块提取数据生成达标清单;研发费用归集证据链自动化。查是否真有跨模块自动取数而非人工录入。' },
|
||||
{ key: 'BOM差异自动核算', desc: '成控部:物料清单(BOM)差异能自动核算以控制成本。查 BomAnalysis/标准成本/实际对比逻辑。' },
|
||||
{ key: '三系统数据打通', desc: 'OA/财务T+/ERP 数据共享、财务系统打通(支付中心写入财务、做账数据共享)。查是否有数据同步/共享机制(DataSyncLog/DataCenter)。' },
|
||||
]
|
||||
log(`R2:逻辑/流程链审计 ${CHAINS.length} 条`)
|
||||
const r2 = await parallel(CHAINS.map((c) => () =>
|
||||
agent(
|
||||
`你是端到端逻辑链审计员。审计链:【${c.key}】。
|
||||
需求(xlsx):${c.desc}
|
||||
${IMPL_MAP}
|
||||
代码位置:${REPO}
|
||||
任务:在代码里逐环节核对该链是否端到端打通且具备自动联动。重点读 service/TriggerRuleEngine.java、service/WorkflowService.java、相关控制器的级联写入、前端承载页与跳转。给出每个环节 有/部分/缺 + 证据,并给整链 verdict(MET/PARTIAL/MISSING/LOGIC_GAP)+gap+severity。基于真实代码,不臆测。`,
|
||||
{ label: `链:${c.key}`, phase: 'R2逻辑流程链', schema: CHAIN, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
log(`R2 完成:${r2.length}/${CHAINS.length} 条链`)
|
||||
|
||||
// ===== 汇总缺口 =====
|
||||
const allGaps = []
|
||||
for (const f of r1ok) {
|
||||
for (const m of (f.modules || [])) {
|
||||
if (m.verdict !== 'MET') allGaps.push({ area: `${f.dept}/${f.suborg}`, module: m.module, verdict: m.verdict, gap: m.gap, severity: m.severity || 'low', evidence: m.evidence })
|
||||
}
|
||||
}
|
||||
for (const c of r2) {
|
||||
if (c.verdict !== 'MET') allGaps.push({ area: `逻辑链`, module: c.chain, verdict: c.verdict, gap: c.gap, severity: c.severity || 'med', evidence: (c.steps || []).map((s) => `${s.step}:${s.status}`).join(';') })
|
||||
}
|
||||
log(`累计缺口 ${allGaps.length} 条`)
|
||||
|
||||
// ===== R3a: 完整性批判 =====
|
||||
const coverageSummary = r1ok.map((f) => {
|
||||
const c = { MET: 0, PARTIAL: 0, MISSING: 0, LOGIC_GAP: 0 }
|
||||
for (const m of (f.modules || [])) c[m.verdict] = (c[m.verdict] || 0) + 1
|
||||
return `${f.dept}/${f.suborg}: MET${c.MET} PART${c.PARTIAL} MISS${c.MISSING} LOGIC${c.LOGIC_GAP}`
|
||||
}).join('\n')
|
||||
const critic = await agent(
|
||||
`你是合规审计的完整性批判员。下面是各机构覆盖统计与现系统实现面。请指出:(1) 哪些被判 MET 的领域可疑、需重查(suspiciousMet);(2) 哪些机构/领域整体覆盖明显不足、可能漏审(underCovered)。
|
||||
【覆盖统计】
|
||||
${coverageSummary}
|
||||
${IMPL_MAP}
|
||||
需求共 29 个二级机构、285 功能模块行 + 5 条业务流程链。只列真正存疑项。`,
|
||||
{ phase: 'R3完整性批判', schema: CRITIC, model: 'sonnet' }
|
||||
)
|
||||
|
||||
// ===== R3b: 对抗复验 high/med 缺口(尽力推翻)=====
|
||||
const hi = allGaps.filter((g) => g.severity === 'high' || g.severity === 'med')
|
||||
log(`R3 复验 high/med 缺口 ${hi.length} 条(对抗式尝试推翻)`)
|
||||
const reverified = await parallel(hi.map((g) => () =>
|
||||
agent(
|
||||
`对抗复验员。有人声称下面这条是系统缺口,你的职责是**尽力推翻它**——在代码里努力证明它其实已实现或逻辑其实存在。
|
||||
缺口:领域[${g.area}] 模块/链[${g.module}] 判定[${g.verdict}] 描述[${g.gap}]
|
||||
${IMPL_MAP}
|
||||
代码位置:${REPO}
|
||||
用 grep/读码彻查。real=true 表示确认缺口属实(找不到实现);real=false 表示其实已实现(给出证据)。`,
|
||||
{ label: `复验:${g.module}`, phase: 'R3缺口复验', schema: VERDICT, model: 'sonnet' }
|
||||
).then((v) => ({ ...g, survives: v ? v.real : true, reNote: v ? v.note : '复验失败默认保留', reEvidence: v ? v.evidence : '' }))
|
||||
)).then((a) => a.filter(Boolean))
|
||||
const survivedGaps = reverified.filter((g) => g.survives)
|
||||
const overturnedGaps = reverified.filter((g) => !g.survives)
|
||||
log(`复验结果:缺口属实 ${survivedGaps.length},被推翻(其实已实现) ${overturnedGaps.length}`)
|
||||
|
||||
// ===== 汇总报告 =====
|
||||
const counts = { met: 0, partial: 0, missing: 0, logicGap: 0 }
|
||||
for (const f of r1ok) for (const m of (f.modules || [])) {
|
||||
if (m.verdict === 'MET') counts.met++
|
||||
else if (m.verdict === 'PARTIAL') counts.partial++
|
||||
else if (m.verdict === 'MISSING') counts.missing++
|
||||
else if (m.verdict === 'LOGIC_GAP') counts.logicGap++
|
||||
}
|
||||
|
||||
const synthInput = {
|
||||
coverageSummary,
|
||||
counts,
|
||||
chains: r2.map((c) => ({ chain: c.chain, verdict: c.verdict, gap: c.gap })),
|
||||
critic,
|
||||
survivedGaps: survivedGaps.map((g) => ({ area: g.area, module: g.module, verdict: g.verdict, gap: g.gap, severity: g.severity })),
|
||||
overturnedCount: overturnedGaps.length,
|
||||
}
|
||||
const report = await agent(
|
||||
`你是首席合规审计官。基于以下三轮审计的汇总数据,产出一份权威《xlsx 需求合规审计报告》(中文 markdown)。
|
||||
要求报告包含:① 总体结论与合规率(coveragePct=MET/总模块行 估算);② 功能覆盖统计(MET/PARTIAL/LOGIC_GAP/MISSING 计数);③ 按二级机构覆盖表;④ 5 条业务流程链 + 4 项跨模块逻辑的达标状态;⑤ 经对抗复验仍属实的缺口清单(按 high→med→low 排序,含所在领域与缺什么);⑥ 完整性批判指出的存疑/欠审项;⑦ 整改优先级建议(先补 high)。客观、可执行、不夸大。
|
||||
【数据(JSON)】
|
||||
${JSON.stringify(synthInput).slice(0, 60000)}`,
|
||||
{ phase: '汇总报告', schema: REPORT, model: 'sonnet' }
|
||||
)
|
||||
|
||||
return {
|
||||
units: units.length,
|
||||
counts,
|
||||
chains: r2.map((c) => ({ chain: c.chain, verdict: c.verdict })),
|
||||
gapsTotal: allGaps.length,
|
||||
highMedReverified: reverified.length,
|
||||
survived: survivedGaps.length,
|
||||
overturned: overturnedGaps.length,
|
||||
critic,
|
||||
survivedGaps,
|
||||
report,
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
export const meta = {
|
||||
name: 'erp-fullbuild-w1',
|
||||
description: '长尾全建W1:23个未建深的二级机构并行从0建缺失深水功能(新建文件+回传共享片段)',
|
||||
phases: [{ title: '长尾机构并行建设' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板(照抄风格):实体 domain/Financing.java、控制器 web/FinancingController.java(CRUD+业务动作+@Transactional级联)、服务 service/MrpService.java、聚合只读 web/FundPoolController.java(无实体跨表聚合)、前端 oa/pages/payment/financing.vue(MasterDataPage接真API)与 repayment.vue(自定义工作流页)。
|
||||
硬约束:①金额一律BigDecimal+com.kaidi.oa.common.Money.of/add/sub/nz(无裸double算钱;乘法BigDecimal.multiply再Money.of);②日期String(YYYY-MM-DD),算天/折旧用java.time.LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源复数>"),返回com.kaidi.oa.common.ApiResp.ok(),请求体record,找不到抛com.kaidi.oa.common.NotFoundException,校验抛com.kaidi.oa.common.ApiException(400/409,中文),状态迁移/级联写@Transactional;④仓库extends org.springframework.data.jpa.repository.JpaRepository<X,Long>派生查询;⑤前端真实页接你的真后端(import { http } from 相对路径的 api/http;http.get/post/patch/del已解包ApiResp.data;token键oa.token),列表CRUD套 pages/masterdata/MasterDataPage.vue,工作流/联动/看板页用el-table+el-dialog+el-card自定义;**现有 settingListStore('xxx') 假数据页要改接你新建的真后端**;⑥无emoji(图标@element-plus/icons-vue)、无渐变(纯色蓝主调#2f6fed)、排版/间距/承载形态慎重(美观+简单易用);⑦类名/表名按域加前缀,先 grep 确认与现有~136控制器/实体零撞名。
|
||||
**关键纪律**:①**只新建文件**或改你这个机构自己的页;凡需改共享文件(config/AuthInterceptor.java、data/oaModules.ts、service/TriggerRuleEngine.java、service/WorkflowService.java)一律**不自改**,放进 sharedFileSnippets(file+anchor原文+change改法+why)由主代理串行合并;②**不运行gradle/npm**(并行争用),逐文件仔细自审语法(import齐全/类型匹配/record字段一致/@Entity@Table+getter-setter完整/Vue标签与import配平);③加法式,绝不破坏现有7条联动链与审批流。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { 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: ['unit', 'backendFiles', 'frontendFiles', 'authFinancePrefixes', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'endpoints', 'summary'],
|
||||
}
|
||||
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const UNITS = [
|
||||
{ dept: '创新研发中心', sub: '产品开发部', mod: 'rd', file: `${SLICE}/01_创新研发中心__产品开发部.txt` },
|
||||
{ dept: '创新研发中心', sub: '申报服务部', mod: 'rd', file: `${SLICE}/02_创新研发中心__申报服务部.txt` },
|
||||
{ dept: '创新研发中心', sub: '知识产权部', mod: 'rd', file: `${SLICE}/03_创新研发中心__知识产权部.txt` },
|
||||
{ dept: '设计研究中心', sub: '咨询可研院', mod: 'design', file: `${SLICE}/05_设计研究中心__咨询可研院.txt` },
|
||||
{ dept: '设计研究中心', sub: '规划设计部', mod: 'design', file: `${SLICE}/06_设计研究中心__规划设计部.txt` },
|
||||
{ dept: '制造管理中心', sub: '环保设备制造中心', mod: 'mfg', file: `${SLICE}/08_制造管理中心__环保设备制造中心.txt` },
|
||||
{ dept: '制造管理中心', sub: '生物质肥料制造中心', mod: 'mfg', file: `${SLICE}/09_制造管理中心__生物质肥料制造中心.txt` },
|
||||
{ dept: '工程管理中心', sub: '质安部', mod: 'ehs', file: `${SLICE}/10_工程管理中心__质安部.txt` },
|
||||
{ dept: '工程管理中心', sub: '资料室', mod: 'archive', file: `${SLICE}/11_工程管理中心__资料室.txt` },
|
||||
{ dept: '工程管理中心', sub: '专利工法办', mod: 'rd', file: `${SLICE}/12_工程管理中心__专利工法办.txt` },
|
||||
{ dept: '工程管理中心', sub: '成本控制部', mod: 'budget', file: `${SLICE}/13_工程管理中心__成本控制部.txt` },
|
||||
{ dept: '运营管理中心', sub: '城镇污水运营中心', mod: 'ops', file: `${SLICE}/14_运营管理中心__城镇污水运营中心.txt` },
|
||||
{ dept: '运营管理中心', sub: '工业废水运营中心', mod: 'ops', file: `${SLICE}/15_运营管理中心__工业废水运营中心.txt` },
|
||||
{ dept: '市场部', sub: '经营部', mod: 'crm', file: `${SLICE}/16_市场部__经营部.txt` },
|
||||
{ dept: '市场部', sub: '办事处', mod: 'crm', file: `${SLICE}/17_市场部__办事处.txt` },
|
||||
{ dept: '市场部', sub: '分公司', mod: 'crm', file: `${SLICE}/18_市场部__分公司.txt` },
|
||||
{ dept: '内控部', sub: '审计监察部', mod: 'audit', file: `${SLICE}/23_内控部__审计监察部.txt` },
|
||||
{ dept: '品牌推广部', sub: '宣传部', mod: 'culture', file: `${SLICE}/24_品牌推广部__宣传部.txt` },
|
||||
{ dept: '品牌推广部', sub: '项目文化', mod: 'culture', file: `${SLICE}/25_品牌推广部__项目文化.txt` },
|
||||
{ dept: '行政', sub: '综合部', mod: 'hr', file: `${SLICE}/26_行政__综合部.txt` },
|
||||
{ dept: '行政', sub: '信息部', mod: 'itasset', file: `${SLICE}/27_行政__信息部.txt` },
|
||||
{ dept: '行政', sub: '办公室', mod: 'admin', file: `${SLICE}/28_行政__办公室.txt` },
|
||||
{ dept: '行政', sub: '后勤', mod: 'admin', file: `${SLICE}/29_行政__后勤.txt` },
|
||||
]
|
||||
|
||||
log(`长尾全建W1:${UNITS.length} 个机构并行建设`)
|
||||
phase('长尾机构并行建设')
|
||||
const results = await parallel(UNITS.map((u) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP 平台【把这个二级机构的深水功能从现状补建到真实可用】:${u.dept} / ${u.sub}。
|
||||
第一步 Read 需求规格:${u.file}
|
||||
第二步 grep/读码盘点该机构现状(很可能只有扁平 CRUD 或 settingListStore 假数据页,缺真实工作流/状态机/自动联动/跨模块取数)。
|
||||
第三步 建缺失的【深水功能】——为需求文件里每个功能模块补上它描述的真实能力(状态机流转/审批/自动计算/跨模块聚合取数/预警/台账),新建 实体+仓库+控制器(+服务) 与 真实前端页(接真后端);把现有 settingListStore 假数据页改接你的真后端。优先做该机构最核心、最能体现"真实工作流而非空壳"的 3-6 个模块,做深做真,而非每个模块都浅尝。
|
||||
前端页挂到模块 '${u.mod}'(在 oaModules 对应模块加 children,作为 sharedFileSnippets 回传,不自改)。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果:新建文件、需合并的鉴权前缀(含金额/机密读→authSensitiveRead;财务写→authFinancePrefixes)、导航条目(moduleId='${u.mod}')、共享文件片段、关键端点、summary(说明做深了哪几个模块)。`,
|
||||
{ label: `建:${u.sub}`, phase: '长尾机构并行建设', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
return { built: results.length, total: UNITS.length, results }
|
||||
@@ -0,0 +1,87 @@
|
||||
export const meta = {
|
||||
name: 'erp-fullbuild-w2',
|
||||
description: '长尾全建W2:29机构并行深化剩余PARTIAL/MISSING子功能(新建文件+回传共享片段)',
|
||||
phases: [{ title: '深化剩余缺口' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:web/FinancingController.java(CRUD+业务动作+@Transactional级联)、web/DevProjectController.java(状态机+审批自动展开WBS)、聚合 web/FundPoolController.java、前端 oa/pages/payment/repayment.vue(自定义工作流页)。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double算钱);②日期String(YYYY-MM-DD)+LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源复数>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400/409,中文),状态迁移/级联@Transactional;④仓库extends JpaRepository派生查询;⑤前端真实页接真后端(import { http },已解包ApiResp.data,token键oa.token),列表套MasterDataPage,工作流/看板用el-table+el-dialog+el-card;⑥无emoji(@element-plus/icons-vue)、无渐变(纯色蓝#2f6fed)、排版慎重;⑦类名表名加域前缀,grep确认与现有~250控制器零撞名。
|
||||
**关键纪律**:①**只新建文件**或改你机构自己的页;共享文件(AuthInterceptor/oaModules/TriggerRuleEngine/WorkflowService)**不自改**,放 sharedFileSnippets(file+anchor+change+why);②**不运行gradle/npm**,逐文件自审语法;③加法式,不破坏现有链与审批流;④Vue 里 :row-class-name 等箭头回调的 { row } 必须写成 ({ row }: { row: any }) 避免隐式any。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { 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: ['unit', 'backendFiles', 'frontendFiles', 'authFinancePrefixes', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'endpoints', 'summary'],
|
||||
}
|
||||
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const GAPS = '/Users/qiu/Desktop/ERP/requirements/_xlsx_audit_round2.json'
|
||||
const UNITS = [
|
||||
['创新研发中心','产品开发部','rd','01_创新研发中心__产品开发部'],
|
||||
['创新研发中心','申报服务部','rd','02_创新研发中心__申报服务部'],
|
||||
['创新研发中心','知识产权部','rd','03_创新研发中心__知识产权部'],
|
||||
['创新研发中心','实验室','lab','04_创新研发中心__实验室'],
|
||||
['设计研究中心','咨询可研院','design','05_设计研究中心__咨询可研院'],
|
||||
['设计研究中心','规划设计部','design','06_设计研究中心__规划设计部'],
|
||||
['设计研究中心','工程监理部','supervision','07_设计研究中心__工程监理部'],
|
||||
['制造管理中心','环保设备制造中心','mfg','08_制造管理中心__环保设备制造中心'],
|
||||
['制造管理中心','生物质肥料制造中心','mfg','09_制造管理中心__生物质肥料制造中心'],
|
||||
['工程管理中心','质安部','ehs','10_工程管理中心__质安部'],
|
||||
['工程管理中心','资料室','archive','11_工程管理中心__资料室'],
|
||||
['工程管理中心','专利工法办','rd','12_工程管理中心__专利工法办'],
|
||||
['工程管理中心','成本控制部','budget','13_工程管理中心__成本控制部'],
|
||||
['运营管理中心','城镇污水运营中心','ops','14_运营管理中心__城镇污水运营中心'],
|
||||
['运营管理中心','工业废水运营中心','ops','15_运营管理中心__工业废水运营中心'],
|
||||
['市场部','经营部','crm','16_市场部__经营部'],
|
||||
['市场部','办事处','crm','17_市场部__办事处'],
|
||||
['市场部','分公司','crm','18_市场部__分公司'],
|
||||
['支付中心','结算中心','payment','19_支付中心__结算中心'],
|
||||
['支付中心','财务部','finance','20_支付中心__财务部'],
|
||||
['支付中心','金融办','payment','21_支付中心__金融办'],
|
||||
['内控部','法务风险部','legal','22_内控部__法务风险部'],
|
||||
['内控部','审计监察部','audit','23_内控部__审计监察部'],
|
||||
['品牌推广部','宣传部','culture','24_品牌推广部__宣传部'],
|
||||
['品牌推广部','项目文化','culture','25_品牌推广部__项目文化'],
|
||||
['行政','综合部','hr','26_行政__综合部'],
|
||||
['行政','信息部','itasset','27_行政__信息部'],
|
||||
['行政','办公室','admin','28_行政__办公室'],
|
||||
['行政','后勤','admin','29_行政__后勤'],
|
||||
]
|
||||
|
||||
log(`长尾全建W2:${UNITS.length} 机构并行深化剩余缺口`)
|
||||
phase('深化剩余缺口')
|
||||
const results = await parallel(UNITS.map(([dept, sub, mod, fn]) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP【深化】二级机构:${dept} / ${sub}。本机构已有不少控制器(W1/P0-P3已建),你的任务是**补齐审计判为 PARTIAL/MISSING/LOGIC_GAP 的剩余子功能**,把"有承载浅逻辑"做深到"真工作流"。
|
||||
第一步 Read 需求规格:${SLICE}/${fn}.txt
|
||||
第二步 Read 第二轮审计缺口清单(找你这个机构 area 的 survivedGaps):${GAPS}
|
||||
第三步 grep/读码盘点本机构已有控制器/实体(避免重复建,改名加前缀)。
|
||||
第四步 针对审计点名的剩余缺口,新建 实体+仓库+控制器(+服务) 与真实前端页,把每条 PARTIAL 做深(状态机/审批/自动计算/跨模块取数/预警/条码追溯/版本/依赖/批次序列号等需求描述的真能力)。优先做 high 缺口。把假数据页改接真后端。前端挂模块 '${mod}'。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果(导航 moduleId='${mod}';共享前缀/导航/片段照纪律回传)。summary 说明补深了哪几条审计缺口。`,
|
||||
{ label: `深化:${sub}`, phase: '深化剩余缺口', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
return { built: results.length, total: UNITS.length, results }
|
||||
@@ -0,0 +1,101 @@
|
||||
export const meta = {
|
||||
name: 'erp-p0-domain-build',
|
||||
description: 'P0 剩余4整域(工程监理/结算复核/法务合规/实验室)并行从0建:各建新后端+前端文件,回传集成片段',
|
||||
phases: [
|
||||
{ title: 'P0域并行建设' },
|
||||
],
|
||||
}
|
||||
|
||||
const REF = `黄金模板(照抄风格/约定):
|
||||
- 后端实体 oa-backend/src/main/java/com/kaidi/oa/domain/Financing.java、RepaymentPlan.java
|
||||
- 后端仓库 repository/FinancingRepository.java、RepaymentPlanRepository.java
|
||||
- 后端控制器 web/FinancingController.java(CRUD + 业务动作 + 跨域联动 + @Transactional删除级联)
|
||||
- 前端 ofbiz-framework/plugins/modern-ui/app/src/oa/pages/payment/financing.vue(MasterDataPage接真API)、repayment.vue(自定义联动页)
|
||||
- 鉴权数组 config/AuthInterceptor.java 的 FINANCE_PREFIXES / SENSITIVE_READ_PREFIXES
|
||||
- 路由约定 requirements/ROUTE-CONVENTION.md(前端只在 data/oaModules.ts 对应模块 children 加条目→路由自动生成)`
|
||||
|
||||
const RULES = `硬约束(务必遵守):
|
||||
1. 金额一律 BigDecimal + com.kaidi.oa.common.Money.of()收口(无乘法用 BigDecimal.multiply 再 Money.of);日期字段用 String(YYYY-MM-DD),到期/天数算用 java.time.LocalDate/ChronoUnit。
|
||||
2. 控制器 @RestController @RequestMapping("/api/oa/<资源复数>"),返回 com.kaidi.oa.common.ApiResp.ok(...);请求体用 record;找不到抛 com.kaidi.oa.common.NotFoundException,校验失败抛 com.kaidi.oa.common.ApiException(400,"中文");DELETE 加 @Transactional 且级联清子表(参考 Financing.delete)。
|
||||
3. 仓库 extends org.springframework.data.jpa.repository.JpaRepository<X,Long>,派生查询如 findByStatus/findByXxxIdOrderBy...。
|
||||
4. **绝不编辑共享文件**(AuthInterceptor.java / oaModules.ts / router)——只新建文件,并把需要加的鉴权前缀与导航条目以结构化结果回传,由主代理中央合并。
|
||||
5. 前端真实页放 oa/pages/<moduleId>/<key>.vue:列表CRUD套 pages/masterdata/MasterDataPage.vue(传 load/create/update/remove,用 import { http } from '../../api/http',http.get/post/patch/del 已解包 ApiResp.data);联动/工作流类用 el-table+el-button 自定义页(参考 repayment.vue)。**绝不用 settingListStore 假数据**——必须接你新建的真后端。
|
||||
6. 铁律:无 emoji(图标用 @element-plus/icons-vue)、无渐变色(纯色蓝主调)、排版/间距/承载形态慎重(美观+简单易用)。
|
||||
7. 类名/表名按域加前缀避免与现有~90控制器/实体重名(先 grep 确认不撞名)。
|
||||
8. **绝不运行 ./gradlew / npm(多域并行会争用同一构建目录与守护进程)**——只写文件并逐文件仔细自审语法(import 齐全、类型匹配、record 字段与用法一致、@Entity/@Table/getter-setter 完整),编译由主代理统一执行修错。`
|
||||
|
||||
const DOMAINS = [
|
||||
{
|
||||
key: 'supervision', name: '工程监理部', moduleId: 'supervision',
|
||||
slice: '/Users/qiu/Desktop/ERP/requirements/_req_slices/07_设计研究中心__工程监理部.txt',
|
||||
brief: `审计10行9MISS整域空白。建监理域:监理项目(SupervisionProject:编号/项目/合同/总监/规模/阶段/状态)、监理记录(SupervisionInspection:旁站/巡视/平行检验/监理通知 类型+部位+结论+问题+整改状态)、计量支付(MeasurementPayment:期次/申报量/核定金额/审批状态)、竣工验收(CompletionAcceptance)。与现有 Project、DesignDoc(图纸版本)、SafetyCheck/QmsRecord 关联(存 projectId/contractId 外键即可)。已有 web/SupervisionLogController/SupervisionController 勿覆盖,新建 SupervisionProjectController 等承载新实体。前端挂 supervision 模块。`,
|
||||
},
|
||||
{
|
||||
key: 'settlement', name: '结算复核/资金风控(结算中心)', moduleId: 'payment',
|
||||
slice: '/Users/qiu/Desktop/ERP/requirements/_req_slices/19_支付中心__结算中心.txt',
|
||||
brief: `审计:无 settlement/reconciliation 端点、复核工作流缺。建:结算单(Settlement:类型 付款/收款/内部, 金额, 关联付款单/合同, 状态 待复核/复核中/已复核/已驳回, 复核人1 reviewer1, 复核人2 reviewer2 双人复核)+复核动作端点(/{id}/review 记录复核人与意见,双人复核齐才置已复核)、银行对账(Reconciliation:银行账户, 对账日, 银行流水余额, 账面余额, 差额自动算, 状态)、资金计划(FundPlan:期间/计划流入/计划流出/预测余额)。风控:大额(阈值,如>100万)与重复(同收款方同金额近7天)付款拦截——做一个 /settlements/risk-check 端点对一笔拟付款返回风险标记。银企直连标注为外部对接项(留接口不实做)。前端挂 payment 模块(结算复核/银行对账/资金计划 三页)。`,
|
||||
},
|
||||
{
|
||||
key: 'legal', name: '法务合规/内控矩阵', moduleId: 'legal',
|
||||
slice: '/Users/qiu/Desktop/ERP/requirements/_req_slices/22_内控部__法务风险部.txt',
|
||||
brief: `审计:名为内控部却无内控矩阵,仅借用 Contract/Seal。建专属实体:合规义务库(ComplianceObligation:法规/义务/责任部门/到期/状态)、内控矩阵(InternalControlMatrix:流程/风险点/控制措施/控制类型 预防/检查/控制频率/责任人/有效性)、诉讼仲裁(LitigationCase:案号/案由/对方/我方角色 原告/被告/金额/阶段/承办律师/结果)、法律咨询(LegalConsult:咨询事项/部门/法律意见/状态)、风险评估(RiskAssessment:风险/可能性/影响/等级/应对)。各配控制器。前端挂 legal 模块(合规义务/内控矩阵/诉讼仲裁/法律咨询/风险评估 页)。`,
|
||||
},
|
||||
{
|
||||
key: 'lab', name: '实验室', moduleId: 'lab',
|
||||
slice: '/Users/qiu/Desktop/ERP/requirements/_req_slices/04_创新研发中心__实验室.txt',
|
||||
brief: `审计:样品/任务/试剂/报告多数 MISSING。已有 LabSample/LabInstrument 控制器可复用关联,勿覆盖。新建:检测任务(TestTask:样品id/检测项目/方法/仪器/检测人/结果值/判定 合格-不合格-OOS偏差/状态)、检测方法库(TestMethod:方法编号/名称/标准依据/适用样品)、试剂耗材(Reagent:名称/批号/有效期/库存量/单位; 出入库扣减)、检测报告(TestReport:报告编号/样品/结论/模板/电子签名人/签发状态)。样品全流程状态流转(收样→分配→检测→复核→报告→留样/处置)在 TestTask/LabSample 状态字段体现。前端挂 lab 模块(检测任务/方法库/试剂耗材/检测报告 页)。`,
|
||||
},
|
||||
]
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
domain: { type: 'string' },
|
||||
backendFiles: { type: 'array', items: { type: 'string' } },
|
||||
frontendFiles: { type: 'array', items: { type: 'string' } },
|
||||
authFinancePrefixes: { type: 'array', items: { type: 'string' }, description: '需加入 FINANCE_PREFIXES 的 /api/oa/xxx(含金额/资金写口)' },
|
||||
authSensitiveRead: { type: 'array', items: { type: 'string' }, description: '需加入 SENSITIVE_READ_PREFIXES 的 /api/oa/xxx(含金额/机密/PII读口)' },
|
||||
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'],
|
||||
},
|
||||
},
|
||||
endpoints: { type: 'array', items: { type: 'string' }, description: '关键端点(供活体冒烟)' },
|
||||
compiles: { type: 'boolean', description: '是否已在本机 ./gradlew compileJava 自检通过' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['domain', 'backendFiles', 'frontendFiles', 'authFinancePrefixes', 'authSensitiveRead', 'navEntries', 'endpoints', 'compiles', 'summary'],
|
||||
}
|
||||
|
||||
phase('P0域并行建设')
|
||||
const results = await parallel(DOMAINS.map((d) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP 平台【从0建设一个整域】:${d.name}。
|
||||
第一步 Read 需求规格:${d.slice}
|
||||
建设要点:${d.brief}
|
||||
|
||||
${REF}
|
||||
|
||||
${RULES}
|
||||
|
||||
交付:在仓库真实创建后端(实体/仓库/控制器)与前端页面文件并写入磁盘;前端页面必须接你新建的真后端 API。**不要运行 gradle/npm**(并行会争用构建),改为逐文件仔细自审语法。
|
||||
返回结构化结果:列出新建文件、需主代理合并到 AuthInterceptor 的前缀、需加到 oaModules 对应模块的导航条目、关键端点、summary。compiles 字段填你"语法自审是否有把握"。`,
|
||||
{ label: `建域:${d.key}`, phase: 'P0域并行建设', schema: RESULT }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
return { built: results.length, results }
|
||||
@@ -0,0 +1,92 @@
|
||||
export const meta = {
|
||||
name: 'erp-p1-build',
|
||||
description: 'P1核心能力阻断:财务内核/MRP-BOM/合同闭环/存疑MET正名 4工作流并行(各只动自有文件,共享文件回传片段中央合并)',
|
||||
phases: [{ title: 'P1并行建设' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板与约定(照抄风格):实体 domain/Financing.java、控制器 web/FinancingController.java(CRUD+业务动作+@Transactional级联)、前端 oa/pages/payment/financing.vue(MasterDataPage接真API)与 repayment.vue(自定义联动页)。
|
||||
硬约束:①金额一律 BigDecimal + com.kaidi.oa.common.Money.of/add/sub/nz(无裸double算钱;乘法用BigDecimal.multiply再Money.of);②日期 String(YYYY-MM-DD),算天/折旧用 java.time.LocalDate/ChronoUnit;③控制器 @RestController @RequestMapping("/api/oa/<资源复数>"),返回 com.kaidi.oa.common.ApiResp.ok(),请求体 record,找不到抛 NotFoundException,校验抛 ApiException(400/409,中文),状态迁移/级联写 @Transactional;④仓库 extends JpaRepository<X,Long> 派生查询;⑤前端真实页接你的真后端(import { http } from 该页相对路径的 api/http;http.get/post/patch/del 已解包ApiResp.data;token键 oa.token),列表CRUD套 pages/masterdata/MasterDataPage.vue,工作流/联动页用 el-table+el-dialog;⑥无emoji(图标@element-plus/icons-vue)、无渐变(纯色蓝主调)、排版间距承载形态慎重(美观+简单易用);⑦类名/表名加域前缀,先 grep 确认与现有~94控制器/实体零撞名。
|
||||
**关键纪律(避免并行冲突)**:
|
||||
- 你**只能新建文件**或编辑**你工作流明确拥有**的现有文件;
|
||||
- 凡需改动**共享文件**(config/AuthInterceptor.java、data/oaModules.ts、service/TriggerRuleEngine.java、service/WorkflowService.java、web/WorkOrderController.java、web/ContractController.java、web/CustomerController.java、web/OpportunityController.java),**一律不要自己改**,把"目标文件+精确改法(插入位置锚点+代码片段)"放进 sharedFileSnippets 字段,由主代理中央串行合并;
|
||||
- **不要运行 gradle/npm**(并行争用),逐文件仔细自审语法。`
|
||||
|
||||
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', description: '要插入/替换处的唯一锚点文本(现有代码原文)' },
|
||||
change: { type: 'string', description: '具体改法:在锚点后插入/替换为...的完整代码片段' },
|
||||
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: 'fin', label: '财务内核',
|
||||
prompt: `工作流【财务内核】。审计:凭证无状态机/红冲、应收应付不自动生成核销、报销无预算校验、税务整模块缺、资产无折旧计提。
|
||||
你拥有并可编辑:web/VoucherController.java + domain/Voucher.java(加凭证状态机:草稿→已审核→已过账 + 红冲冲销动作)。
|
||||
新建(新文件):①税务 domain/TaxFiling.java(税种/所属期/计税依据/税率/应纳税额/状态)+仓库+web/TaxFilingController.java;②固定资产 domain/FixedAsset.java(资产编号/名称/原值/累计折旧/净值/折旧方法 年限平均/月折旧额/状态)+仓库+web/FixedAssetController.java(含 /{id}/depreciate 按月计提:本月折旧=原值/(年限*12),累计折旧累加,净值=原值-累计,折旧达原值即提完);③应收应付 domain/ArApItem.java(类型 应收/应付/关联合同或发票/金额/已核销/未核销/状态)+仓库+web/ArApController.java(含 /{id}/writeoff 核销:核销额累加,全核销置已结清)。
|
||||
报销预算校验:做 web/ExpenseClaimController.java 或在新建的报销实体里,提交报销时查对应 Budget 剩余(读 BudgetRepository),超预算 ApiException(409,中文)。前端挂 finance 模块(凭证/税务/固定资产/应收应付/报销 真实页)。
|
||||
共享文件(回传片段勿自改):若要让付款办结自动生成应付/凭证,给 service/TriggerRuleEngine.java 的片段;AuthInterceptor 财务前缀;oaModules finance 模块导航。`,
|
||||
},
|
||||
{
|
||||
key: 'mfg', label: 'MRP/BOM',
|
||||
prompt: `工作流【MRP/BOM】。审计:MRP净需求(读库存/在途/在制)缺、BOM差异的actualCost/actualQty手填未从工单/领料自动回填。
|
||||
你拥有并可编辑:web/BomAnalysisController.java(把差异核算的实际量/实际成本改为可从工单领料自动回填的端点)。
|
||||
新建(新文件):①web/MrpController.java + service/MrpService.java:MRP净需求运算——给一个生产需求(产品+数量),按 BomItem 多级展开毛需求,减去 InventoryItem 现有库存、在途(采购在途,可先建字段或读现有)、在制,得净需求与建议采购/生产量;返回逐物料 {物料,毛需求,现有,在途,在制,净需求,建议}。②领料/工单回填:domain/MaterialIssue.java(工单领料:workOrderId/物料/数量/单价/金额)+仓库+web/MaterialIssueController.java,领料写入后可被 BOM差异核算读取做 actualQty/actualCost 自动回填。
|
||||
前端挂 mfg 模块(MRP运算/领料 真实页)与 budget/contract 无关。
|
||||
共享文件(回传片段勿自改):若需 WorkOrderController 暴露在制量,给片段;AuthInterceptor;oaModules mfg 模块导航。`,
|
||||
},
|
||||
{
|
||||
key: 'contract', label: '合同闭环',
|
||||
prompt: `工作流【合同闭环】。审计(LOGIC_GAP):模板bodyTemplate无页面消费、自动化条款比对不存在、电子签/外部盖章未集成。
|
||||
你拥有并可编辑:web/ContractTemplateController.java(确保能取模板正文 bodyTemplate)。
|
||||
新建(新文件):①web/ClauseCompareController.java + service/ClauseCompareService.java:自动化条款比对——给一份合同草稿正文与模板编号,逐条比对(按句/关键条款:金额/工期/质保/违约/付款方式),输出偏差清单 {条款,模板值/草稿值,偏差类型 缺失/修改/新增,风险级别}。可用文本规则(关键词+数值抽取)实现,不需LLM。②电子签/外部盖章:web/EsignController.java——/contracts/{id}/esign 发起电子签(置状态待签→已签,记录签署人/时间/外部签章流水号),外部盖章系统对接标注为对接项留接口。
|
||||
前端:在 contract 模块新建"模板起草"(选模板→bodyTemplate填充→生成草稿)、"条款比对"(贴草稿→比对→偏差表)、"电子签"页,接真后端。
|
||||
共享文件(回传片段勿自改):若合同起草要写 Contract,给 web/ContractController.java 片段(新增"从模板起草"端点);AuthInterceptor;oaModules contract 模块导航。`,
|
||||
},
|
||||
{
|
||||
key: 'met', label: '存疑MET正名',
|
||||
prompt: `工作流【存疑MET正名】。审计:①分公司/办事处无机构级目录与数据隔离(只是opportunity一个自由文本orgUnit);②生物质 autoInventory 联动是控制器私有方法,不走TriggerRuleEngine、无ruleKey/AutomationLog/幂等。
|
||||
新建(新文件):①机构目录 domain/OrgBranch.java(机构编号/名称/类型 总部/分公司/办事处/上级/地区/负责人/状态)+仓库+web/OrgBranchController.java(CRUD),让分公司/办事处成为真实机构主数据;前端在 crm 或 masterdata 模块建"机构目录(分公司/办事处)"页。②前端建"分支机构经营看板"页:按 OrgBranch 维度聚合商机/客户(调现有 /opportunities /customers 带 orgUnit 过滤),体现机构级视图。
|
||||
共享文件(回传片段勿自改,关键):
|
||||
- service/TriggerRuleEngine.java + web/WorkOrderController.java:把"已入库工单→自动生成成品库存"从 WorkOrderController 私有方法改为经 TriggerRuleEngine 正规联动(ruleKey 如 workorder.done.inventory + AutomationLog 留痕 + existsByInstanceIdAndRuleKey 幂等),与其余7条正规链同源。给出精确锚点+片段。
|
||||
- 若 CustomerController/OpportunityController 需加 orgUnit/branchId 过滤,给片段。
|
||||
AuthInterceptor(org-branches 写口收口);oaModules 导航。`,
|
||||
},
|
||||
]
|
||||
|
||||
phase('P1并行建设')
|
||||
const results = await parallel(WS.map((w) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP 平台做 P1 深度增强。${w.prompt}\n\n${COMMON}\n\n返回结构化结果:新建文件、你已编辑的自有文件、需中央合并的共享文件片段(sharedFileSnippets:file+anchor原文+change改法+why)、鉴权前缀、导航条目、关键端点、summary。`,
|
||||
{ label: `P1:${w.key}`, phase: 'P1并行建设', schema: RESULT }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
return { built: results.length, results }
|
||||
@@ -0,0 +1,78 @@
|
||||
export const meta = {
|
||||
name: 'erp-p2-build',
|
||||
description: 'P2重要能力:跨模块自动取数/报表看板/AI服务层/移动可服务部分 4工作流并行(全新建文件+回传共享片段)',
|
||||
phases: [{ title: 'P2并行建设' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:控制器 web/FinancingController.java、聚合只读 web/FundPoolController.java(无实体、跨表聚合走ApiResp)、前端 oa/pages/payment/financing.vue(MasterDataPage)与 repayment.vue(自定义页)。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double算钱);②控制器@RestController @RequestMapping("/api/oa/<资源>"),返回ApiResp.ok(),record请求体,NotFoundException/ApiException(400,中文);③仓库extends JpaRepository;④前端真实页接真后端(import { http },http.get/post已解包ApiResp.data,token键oa.token),列表套MasterDataPage,看板/聚合用el-table/el-card自定义;⑤无emoji(@element-plus/icons-vue)、无渐变(纯色蓝主调)、排版承载形态慎重;⑥类名表名加域前缀,grep确认不撞名(现有~110控制器)。
|
||||
**关键纪律**:①**只新建文件**,凡需改共享文件(config/AuthInterceptor.java、data/oaModules.ts)一律不自改,放进 sharedFileSnippets(file+anchor原文+change改法+why)由主代理串行合并;②**不运行gradle/npm**(并行争用),逐文件自审语法。`
|
||||
|
||||
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' } },
|
||||
externalDeps: { type: 'string', description: '需外部资源才能完全生效的部分(如API Key/设备能力),据实说明' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['workstream', 'backendFiles', 'frontendFiles', 'authFinancePrefixes', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'endpoints', 'externalDeps', 'summary'],
|
||||
}
|
||||
|
||||
const WS = [
|
||||
{
|
||||
key: 'autofetch', label: '跨模块自动取数',
|
||||
prompt: `工作流【跨模块自动取数】(审计:数据中心"统一数据库/流程驱动自动取数"大面积缺,申报条件自查/研发费用归集证据链不自动)。全新建:
|
||||
①web/EligibilityCheckController.java + service/EligibilityCheckService.java:申报条件自查自动取数——给定申报类型(如高企),自动从 财务(RdExpenseRepository研发费用)、HR(PersonnelCertRepository人员证书/科技人员)、知识产权(PatentRepository专利软著)、项目(ProjectRepository已完成项目) 各仓库读数,按规则(研发费用占比/知识产权数量/科技人员占比)生成"达标/不达标"清单(每项:要求值/实际值/是否达标/差距/数据来源),不再人工录入。
|
||||
②web/RdExpenseTraceController.java:研发费用归集证据链——按 rdProjectId 聚合 RdExpense,列出每笔费用+来源单据引用,形成证据链汇总(项目/费用类型/金额合计/笔数)。
|
||||
均为只读聚合(参考 FundPoolController 跨表聚合不建实体)。前端挂 datacenter 模块(申报条件自查/研发费用证据链 看板页,接真后端)。`,
|
||||
},
|
||||
{
|
||||
key: 'dashboard', label: '报表看板',
|
||||
prompt: `工作流【报表看板】(审计:运营KPI/后勤成本/QHSE/财务多维看板缺)。全新建只读聚合控制器+前端看板页(参考FundPoolController聚合、el-card+el-table展示):
|
||||
①web/OpsKpiController.java:运营KPI看板——聚合 WaterQualityRecord(达标率)、WorkOrder(产量/完成率)、相关运营数据,出KPI卡片+趋势。
|
||||
②web/QhseDashboardController.java:QHSE指标看板——聚合 SafetyCheck/QmsRecord(隐患数/整改率/质量记录),出QHSE指标。
|
||||
③web/FinanceDashboardController.java:财务多维看板——聚合 Contract(合同额/已付/已开票)、Payment(付款)、Voucher、ArApItem(应收应付),出资金/往来/合同多维汇总。
|
||||
前端挂 report 或 datacenter 模块(运营KPI/QHSE/财务看板 页)。只读聚合不建实体。`,
|
||||
},
|
||||
{
|
||||
key: 'ai', label: 'AI服务层',
|
||||
prompt: `工作流【AI服务层】(审计:市场/行政/法务/财务多处点名AI,无统一LLM层)。全新建AI能力框架(可配置,无Key时优雅降级):
|
||||
web/AiController.java + service/AiService.java + 配置类:统一AI服务层,提供 POST /api/oa/ai/complete(body{scenario,prompt,context}) 调 LLM 返回文本;封装场景端点 /ai/draft(文案/话术起草)、/ai/classify(舆情情感分类)、/ai/summarize(摘要)、/ai/risk(风险提示)。
|
||||
实现:AiService 用 Spring 的 org.springframework.web.client.RestClient/RestTemplate(或 java.net.http.HttpClient) POST 到 Anthropic Messages API: https://api.anthropic.com/v1/messages, headers: x-api-key:<key>、anthropic-version:2023-06-01、content-type:application/json, body:{model, max_tokens:1024, messages:[{role:user,content:prompt}]}。model 从配置读,默认 "claude-haiku-4-5-20251001"(高性价比)。API Key 从 application.yml 的 oa.ai.api-key 或环境变量 ANTHROPIC_API_KEY 读;**未配置 Key 时不报错,返回 ApiResp.ok 一个降级结果{configured:false, text:"AI 服务未配置 API Key,请在 application.yml 配置 oa.ai.api-key 后启用", scenario}**,保证活体不崩。配置项写到 application.yml(oa.ai.api-key: "" 占位 + 注释)。前端挂 appdev 或 intel 模块一个"AI 助手"页(选场景+输入→调/ai/complete→显示结果,未配置Key时友好提示)。
|
||||
externalDeps 据实写明:需配置 Anthropic API Key 才能真正产出AI结果,否则降级提示。`,
|
||||
},
|
||||
{
|
||||
key: 'mobile', label: '移动端可服务部分',
|
||||
prompt: `工作流【移动端可服务部分】(审计:GPS打卡/扫码/离线/专项审批移动场景缺;其中GPS定位/扫码/离线属设备/前端能力,后端先把可服务的数据接口与审批队列建好)。全新建:
|
||||
①web/MobileCheckinController.java + domain/MobileCheckin.java(外勤打卡:用户/打卡类型 上班/外勤/拜访/经纬度lat/lng/地址/时间/备注)+仓库:打卡记录CRUD+按用户按日查询。经纬度由前端定位回填(设备能力),后端存储+台账。
|
||||
②web/MobileApprovalController.java:移动审批队列聚合——复用现有审批(读 FormInstance 当前办理人为当前用户的待办),输出精简的移动待办列表(标题/类型/发起人/金额/时间),供移动端专项审批。只读聚合。
|
||||
前端挂 mobile 模块(外勤打卡/移动审批 页,接真后端;打卡页用 navigator.geolocation 取经纬度,取不到则手填,优雅降级)。
|
||||
externalDeps 写明:GPS定位依赖浏览器/设备 geolocation、扫码依赖摄像头,属前端设备能力;离线依赖PWA/缓存,本期先做在线数据接口与审批队列。`,
|
||||
},
|
||||
]
|
||||
|
||||
phase('P2并行建设')
|
||||
const results = await parallel(WS.map((w) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP 平台做 P2 重要能力补建。${w.prompt}\n\n${COMMON}\n\n返回结构化结果(含 externalDeps 据实说明)。`,
|
||||
{ label: `P2:${w.key}`, phase: 'P2并行建设', schema: RESULT }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
return { built: results.length, results }
|
||||
@@ -0,0 +1,80 @@
|
||||
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 }
|
||||
@@ -0,0 +1,86 @@
|
||||
export const meta = {
|
||||
name: 'erp-w3-buildable',
|
||||
description: 'W3:29机构并行补可建(内部逻辑)剩余缺口,把PARTIAL推向MET(新建文件+回传共享片段)',
|
||||
phases: [{ title: '补可建缺口' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:web/FinancingController.java、web/DevProjectController.java(状态机+审批自动展开)、聚合 web/FundPoolController.java、前端 oa/pages/payment/repayment.vue。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double);②日期String+LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400/409中文),状态迁移/级联@Transactional;④仓库extends JpaRepository派生查询;⑤前端真页接真后端(import { http },已解包ApiResp.data,token键oa.token;**http 删除用 http.del() 不是 http.delete()**;**el-table-column 插槽写 #default="{ row }" 或 #default="{ row }: { row: any }",绝不套外括号**);⑥无emoji(@element-plus/icons-vue)、无渐变(纯色蓝#2f6fed);⑦类名表名加域前缀,grep确认与现有~436控制器零撞名。
|
||||
**关键纪律**:①**只新建文件**或改你机构自己的页;共享文件(AuthInterceptor/oaModules/TriggerRuleEngine/WorkflowService)不自改,放sharedFileSnippets;②不运行gradle/npm;③加法式不破坏现有链;④**逐文件自审Java语法**(import齐全[@PathVariable/@RequestBody/domain类]、ApiResp用record访问器.data()非.getData()、括号配平、record字段一致、实体setter存在)与**Vue语法**(插槽不套外括号、http.del、{row}加:{row:any})。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { type: 'string' },
|
||||
backendFiles: { type: 'array', items: { type: 'string' } },
|
||||
frontendFiles: { 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'] } },
|
||||
closedGaps: { type: 'array', items: { type: 'string' }, description: '本轮补完的缺口模块名' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['unit', 'backendFiles', 'frontendFiles', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'closedGaps', 'summary'],
|
||||
}
|
||||
|
||||
const GAPS = '/Users/qiu/Desktop/ERP/requirements/_xlsx_audit_round3.json'
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const UNITS = [
|
||||
['创新研发中心','产品开发部','rd','01_创新研发中心__产品开发部'],
|
||||
['创新研发中心','申报服务部','rd','02_创新研发中心__申报服务部'],
|
||||
['创新研发中心','知识产权部','rd','03_创新研发中心__知识产权部'],
|
||||
['创新研发中心','实验室','lab','04_创新研发中心__实验室'],
|
||||
['设计研究中心','咨询可研院','design','05_设计研究中心__咨询可研院'],
|
||||
['设计研究中心','规划设计部','design','06_设计研究中心__规划设计部'],
|
||||
['设计研究中心','工程监理部','supervision','07_设计研究中心__工程监理部'],
|
||||
['制造管理中心','环保设备制造中心','mfg','08_制造管理中心__环保设备制造中心'],
|
||||
['制造管理中心','生物质肥料制造中心','mfg','09_制造管理中心__生物质肥料制造中心'],
|
||||
['工程管理中心','质安部','ehs','10_工程管理中心__质安部'],
|
||||
['工程管理中心','资料室','archive','11_工程管理中心__资料室'],
|
||||
['工程管理中心','专利工法办','rd','12_工程管理中心__专利工法办'],
|
||||
['工程管理中心','成本控制部','budget','13_工程管理中心__成本控制部'],
|
||||
['运营管理中心','城镇污水运营中心','ops','14_运营管理中心__城镇污水运营中心'],
|
||||
['运营管理中心','工业废水运营中心','ops','15_运营管理中心__工业废水运营中心'],
|
||||
['市场部','经营部','crm','16_市场部__经营部'],
|
||||
['市场部','办事处','crm','17_市场部__办事处'],
|
||||
['市场部','分公司','crm','18_市场部__分公司'],
|
||||
['支付中心','结算中心','payment','19_支付中心__结算中心'],
|
||||
['支付中心','财务部','finance','20_支付中心__财务部'],
|
||||
['支付中心','金融办','payment','21_支付中心__金融办'],
|
||||
['内控部','法务风险部','legal','22_内控部__法务风险部'],
|
||||
['内控部','审计监察部','audit','23_内控部__审计监察部'],
|
||||
['品牌推广部','宣传部','culture','24_品牌推广部__宣传部'],
|
||||
['品牌推广部','项目文化','culture','25_品牌推广部__项目文化'],
|
||||
['行政','综合部','hr','26_行政__综合部'],
|
||||
['行政','信息部','itasset','27_行政__信息部'],
|
||||
['行政','办公室','admin','28_行政__办公室'],
|
||||
['行政','后勤','admin','29_行政__后勤'],
|
||||
]
|
||||
|
||||
log(`W3:${UNITS.length} 机构补可建缺口`)
|
||||
phase('补可建缺口')
|
||||
const results = await parallel(UNITS.map(([dept, sub, mod, fn]) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP【补完这个机构可建的剩余缺口】:${dept} / ${sub}。
|
||||
第一步 运行 python3 读取本机构的剩余缺口(只取 buildable 内部逻辑类):python3 -c "import json;d=json.load(open('${GAPS}'));[print('-',g['module'],':',g['gap']) for g in d['buildable'] if '${sub}' in g['area']]"
|
||||
第二步 Read 需求切片 ${SLICE}/${fn}.txt 对照。
|
||||
第三步 grep/读码确认现状(本机构已有很多控制器),针对上面列出的【可建缺口】补实现:缺的状态机端点/甘特或日历聚合API/结构化字段/跨模块联动/自动触发/趋势分析端点等,新建实体+仓库+控制器(+服务)与真实前端页,把 PARTIAL 推向真正可用。**跳过需外部系统的**(真PKI电子签CA/BIM/CAD/NLP向量/IoT/JPush推送/外部对接)——那些非本轮目标。优先 high/med 缺口。
|
||||
前端页挂模块 '${mod}'。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果(closedGaps列出补完的模块;导航 moduleId='${mod}')。`,
|
||||
{ label: `W3:${sub}`, phase: '补可建缺口', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
return { built: results.length, total: UNITS.length, results }
|
||||
@@ -0,0 +1,103 @@
|
||||
export const meta = {
|
||||
name: 'erp-w4-buildable',
|
||||
description: 'W4:29机构并行把剩余94个可建PARTIAL缺口推向MET(补状态机/聚合/联动/调度/自动取数;跳过需外部系统的24个)',
|
||||
phases: [{ title: '补可建缺口W4' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:web/FinancingController.java、web/DevProjectController.java(状态机+审批自动展开)、聚合 web/FundPoolController.java、调度 @Scheduled、前端 oa/pages/payment/repayment.vue。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double);②日期String+LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400/409中文),状态迁移/级联@Transactional;④仓库extends JpaRepository派生查询;⑤前端真页接真后端(import { http },已解包ApiResp.data,token键oa.token)。
|
||||
|
||||
**⚠️W3量产5大崩溃坑——本轮绝不再犯(逐条自查)**:
|
||||
[后端]①**Map.of()最多10对键值**(20参)——超过就编译失败"找不到合适的方法";多字段Map一律用 new java.util.LinkedHashMap<>() 逐.put()。
|
||||
②**SQLite保留字绝不做列名/字段名**:references/primary/order/group/key/values/index/table/column/check/default/constraint/references/desc/asc等;若业务字段必须叫这名,Java字段可留但**必须**加@Column(name="安全别名")映射物理列(并import jakarta.persistence.Column),否则建表DDL崩"near xxx: syntax error"。
|
||||
③**派生查询禁用ContainingIgnoreCase**(Hibernate6社区SQLite方言upper()类型校验崩,启动即挂)——一律用 Containing(SQLite的LIKE对ASCII本就大小写不敏感,中文无大小写,功能等价)。
|
||||
[前端]④**el-table-column插槽**:写 #default="{ row }" 或 #default="{ row }: { row: any }";**绝不写 typeof X[0] / typeof X.value[0] 注解**(vue-tsc过但vite编译/类型崩),绝不套外层括号。
|
||||
⑤**v-model必须是可写成员表达式**:绝不 v-model="!!expr" 或 v-model="fn()"(vite编译崩"must be a valid JavaScript member expression");需要派生可见性用 :model-value="!!x" @update:model-value="(v:boolean)=>{ if(!v) x=null }"。
|
||||
⑥**图标必须真存在于@element-plus/icons-vue**(MobilePhone不存在→用Iphone;不确定就用 Document/List/Money/DataLine 等常见图标);http删除用 http.del() 不是 http.delete()。
|
||||
⑦无emoji、无渐变(纯色蓝#2f6fed);类名表名加域前缀,grep确认与现有~553控制器/560实体零撞名。
|
||||
**关键纪律**:①只新建文件或改你机构自己的页;共享文件(AuthInterceptor/oaModules/TriggerRuleEngine/WorkflowService)不自改,放sharedFileSnippets;②不运行gradle/npm;③加法式不破坏现有链;④逐文件自审Java语法(import齐全[@PathVariable/@RequestBody/@Column/domain类]、ApiResp用record访问器.data()非.getData()、括号配平、record字段一致、实体setter存在、Map.of≤10对)与Vue语法(插槽不套外括号无typeof、v-model成员表达式、http.del、图标存在)。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { type: 'string' },
|
||||
backendFiles: { type: 'array', items: { type: 'string' } },
|
||||
frontendFiles: { 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'] } },
|
||||
closedGaps: { type: 'array', items: { type: 'string' } },
|
||||
skippedExternal: { type: 'array', items: { type: 'string' }, description: '本轮判定需外部系统而跳过的缺口' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['unit', 'backendFiles', 'frontendFiles', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'closedGaps', 'skippedExternal', 'summary'],
|
||||
}
|
||||
|
||||
const GAPS = '/Users/qiu/Desktop/ERP/requirements/_xlsx_audit_w3post.json'
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const UNITS = [
|
||||
['创新研发中心','产品开发部','rd','01_创新研发中心__产品开发部'],
|
||||
['创新研发中心','申报服务部','rd','02_创新研发中心__申报服务部'],
|
||||
['创新研发中心','知识产权部','rd','03_创新研发中心__知识产权部'],
|
||||
['创新研发中心','实验室','lab','04_创新研发中心__实验室'],
|
||||
['设计研究中心','咨询可研院','design','05_设计研究中心__咨询可研院'],
|
||||
['设计研究中心','规划设计部','design','06_设计研究中心__规划设计部'],
|
||||
['设计研究中心','工程监理部','supervision','07_设计研究中心__工程监理部'],
|
||||
['制造管理中心','环保设备制造中心','mfg','08_制造管理中心__环保设备制造中心'],
|
||||
['制造管理中心','生物质肥料制造中心','mfg','09_制造管理中心__生物质肥料制造中心'],
|
||||
['工程管理中心','质安部','ehs','10_工程管理中心__质安部'],
|
||||
['工程管理中心','资料室','archive','11_工程管理中心__资料室'],
|
||||
['工程管理中心','专利工法办','rd','12_工程管理中心__专利工法办'],
|
||||
['工程管理中心','成本控制部','budget','13_工程管理中心__成本控制部'],
|
||||
['运营管理中心','城镇污水运营中心','ops','14_运营管理中心__城镇污水运营中心'],
|
||||
['运营管理中心','工业废水运营中心','ops','15_运营管理中心__工业废水运营中心'],
|
||||
['市场部','经营部','crm','16_市场部__经营部'],
|
||||
['市场部','办事处','crm','17_市场部__办事处'],
|
||||
['市场部','分公司','crm','18_市场部__分公司'],
|
||||
['支付中心','结算中心','payment','19_支付中心__结算中心'],
|
||||
['支付中心','财务部','finance','20_支付中心__财务部'],
|
||||
['支付中心','金融办','payment','21_支付中心__金融办'],
|
||||
['内控部','法务风险部','legal','22_内控部__法务风险部'],
|
||||
['内控部','审计监察部','audit','23_内控部__审计监察部'],
|
||||
['品牌推广部','宣传部','culture','24_品牌推广部__宣传部'],
|
||||
['品牌推广部','项目文化','culture','25_品牌推广部__项目文化'],
|
||||
['行政','综合部','hr','26_行政__综合部'],
|
||||
['行政','信息部','itasset','27_行政__信息部'],
|
||||
['行政','办公室','admin','28_行政__办公室'],
|
||||
['行政','后勤','admin','29_行政__后勤'],
|
||||
]
|
||||
|
||||
log(`W4:${UNITS.length} 机构补94个可建PARTIAL缺口`)
|
||||
phase('补可建缺口W4')
|
||||
const results = await parallel(UNITS.map(([dept, sub, mod, fn]) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP【把这个机构剩余的"可建PARTIAL缺口"推向真正MET】:${dept} / ${sub}。
|
||||
第一步 运行 python3 取本机构的剩余可建缺口:python3 -c "import json;d=json.load(open('${GAPS}'));[print('['+g['severity']+']',g['module'],':',g['gap']) for g in d['buildable'] if '${sub}' in g['area']]"
|
||||
若上面输出为空,说明本机构无可建缺口,直接返回空结果(closedGaps=[])。
|
||||
第二步 Read 需求切片 ${SLICE}/${fn}.txt 对照理解。
|
||||
第三步 grep/读码确认现状(本机构已有很多控制器/实体),针对每条可建缺口补完真实现:缺的结构化实体(如测试计划TestPlan)/状态机端点/甘特或日历聚合API/自动计算逻辑(如标准成本从BOM+工艺路线展开)/跨模块联动写入(如发布BOM到生产)/规则引擎自动触发钩子/调度Job(@Scheduled自动下架/生成)/统计分析端点(上市周期/成功率/三维投入)等。新建实体+仓库+控制器(+服务)与真实前端页,把PARTIAL真正补全到可用。
|
||||
**优先 high>med>low**。**凡缺口本质需要外部系统的**(真CA电子签/数字证书/区块链存证、BIM碰撞、CAD/Revit解析、AI语义/知识图谱/向量、JPush/APNs推送网关、语音录入、IoT/SCADA、银企直连/税务直连)——放入skippedExternal数组并简述,本轮不做。
|
||||
前端页挂模块 '${mod}'。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果(closedGaps列出真正补完到MET的缺口模块名;skippedExternal列出跳过的;导航 moduleId='${mod}')。`,
|
||||
{ label: `W4:${sub}`, phase: '补可建缺口W4', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
const closed = results.reduce((s, r) => s + (r.closedGaps || []).length, 0)
|
||||
const skipped = results.reduce((s, r) => s + (r.skippedExternal || []).length, 0)
|
||||
const bf = results.reduce((s, r) => s + (r.backendFiles || []).length, 0)
|
||||
const ff = results.reduce((s, r) => s + (r.frontendFiles || []).length, 0)
|
||||
log(`W4完成: 补完${closed}缺口 跳过外部${skipped}; 后端文件${bf} 前端页${ff}`)
|
||||
return { built: results.length, total: UNITS.length, closed, skipped, backendFiles: bf, frontendFiles: ff, results }
|
||||
@@ -0,0 +1,105 @@
|
||||
export const meta = {
|
||||
name: 'erp-w5-buildable',
|
||||
description: 'W5:29机构并行把剩余72个可建PARTIAL缺口推向MET(补状态机/聚合/联动/调度/自动取数;跳过需外部系统的23个)',
|
||||
phases: [{ title: '补可建缺口W5' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:web/FinancingController.java、web/DevProjectController.java(状态机+审批自动展开)、聚合 web/FundPoolController.java、调度 @Scheduled、前端 oa/pages/payment/repayment.vue。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double);②日期String+LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400/409中文),状态迁移/级联@Transactional;④仓库extends JpaRepository派生查询;⑤前端真页接真后端(import { http },已解包ApiResp.data,token键oa.token)。
|
||||
|
||||
**⚠️W3量产5大崩溃坑——本轮绝不再犯(逐条自查)**:
|
||||
[后端]①**Map.of()最多10对键值**(20参)——超过就编译失败"找不到合适的方法";多字段Map一律用 new java.util.LinkedHashMap<>() 逐.put()。
|
||||
②**SQLite保留字绝不做列名/字段名**:references/primary/order/group/key/values/index/table/column/check/default/constraint/references/desc/asc等;若业务字段必须叫这名,Java字段可留但**必须**加@Column(name="安全别名")映射物理列(并import jakarta.persistence.Column),否则建表DDL崩"near xxx: syntax error"。
|
||||
③**派生查询禁用ContainingIgnoreCase**(Hibernate6社区SQLite方言upper()类型校验崩,启动即挂)——一律用 Containing(SQLite的LIKE对ASCII本就大小写不敏感,中文无大小写,功能等价)。
|
||||
[前端]④**el-table-column插槽**:写 #default="{ row }" 或 #default="{ row }: { row: any }";**绝不写 typeof X[0] / typeof X.value[0] 注解**(vue-tsc过但vite编译/类型崩),绝不套外层括号。
|
||||
⑤**v-model必须是可写成员表达式**:绝不 v-model="!!expr" 或 v-model="fn()"(vite编译崩"must be a valid JavaScript member expression");需要派生可见性用 :model-value="!!x" @update:model-value="(v:boolean)=>{ if(!v) x=null }"。
|
||||
⑥**图标必须真存在于@element-plus/icons-vue**(MobilePhone不存在→用Iphone;不确定就用 Document/List/Money/DataLine 等常见图标);http删除用 http.del() 不是 http.delete()。
|
||||
⑦**具名插槽「<template #footer>」/「#header」/「#default」必须是组件(el-dialog/el-card/el-table-column)的直接子节点,绝不能嵌在「<div>」等HTML元素里**(否则vite vue编译器崩"Cannot read properties of undefined reading type",整个build失败)——dialog里要按状态切换footer时,footer提到dialog直属用「<template v-if>」切换,别把footer放进「<div v-if>」。
|
||||
⑧**http参数形态**:「http.get<T>(url, query)」第2参直接就是query对象(「Record<string,string|number|boolean|null|undefined>」),**不是**「{ params: {...} }」;「http.post<T>(url, body, opts)」的opts用「query」键不是「params」;声明query变量用「const params: Record<string, any> = {}」(别用unknown)。模板里「Promise」/「window」不在Vue全局白名单,要用就在「<script setup>」定义函数包装再调。
|
||||
⑨无emoji、无渐变(纯色蓝#2f6fed);类名表名加域前缀,grep确认与现有~623控制器/614实体零撞名。**优先新建实体;若必须给既有实体加字段,在summary注明"既有实体X加字段Y"(SQLite ddl-update不可靠加列,集成时统一schema-sync)**。
|
||||
**关键纪律**:①只新建文件或改你机构自己的页;共享文件(AuthInterceptor/oaModules/TriggerRuleEngine/WorkflowService)不自改,放sharedFileSnippets;②不运行gradle/npm;③加法式不破坏现有链;④逐文件自审Java语法(import齐全[@PathVariable/@RequestBody/@Column/domain类]、ApiResp用record访问器.data()非.getData()、括号配平、record字段一致、实体setter存在、Map.of≤10对)与Vue语法(插槽不套外括号无typeof、v-model成员表达式、http.del、图标存在)。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { type: 'string' },
|
||||
backendFiles: { type: 'array', items: { type: 'string' } },
|
||||
frontendFiles: { 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'] } },
|
||||
closedGaps: { type: 'array', items: { type: 'string' } },
|
||||
skippedExternal: { type: 'array', items: { type: 'string' }, description: '本轮判定需外部系统而跳过的缺口' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['unit', 'backendFiles', 'frontendFiles', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'closedGaps', 'skippedExternal', 'summary'],
|
||||
}
|
||||
|
||||
const GAPS = '/Users/qiu/Desktop/ERP/requirements/_xlsx_audit_w4post.json'
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const UNITS = [
|
||||
['创新研发中心','产品开发部','rd','01_创新研发中心__产品开发部'],
|
||||
['创新研发中心','申报服务部','rd','02_创新研发中心__申报服务部'],
|
||||
['创新研发中心','知识产权部','rd','03_创新研发中心__知识产权部'],
|
||||
['创新研发中心','实验室','lab','04_创新研发中心__实验室'],
|
||||
['设计研究中心','咨询可研院','design','05_设计研究中心__咨询可研院'],
|
||||
['设计研究中心','规划设计部','design','06_设计研究中心__规划设计部'],
|
||||
['设计研究中心','工程监理部','supervision','07_设计研究中心__工程监理部'],
|
||||
['制造管理中心','环保设备制造中心','mfg','08_制造管理中心__环保设备制造中心'],
|
||||
['制造管理中心','生物质肥料制造中心','mfg','09_制造管理中心__生物质肥料制造中心'],
|
||||
['工程管理中心','质安部','ehs','10_工程管理中心__质安部'],
|
||||
['工程管理中心','资料室','archive','11_工程管理中心__资料室'],
|
||||
['工程管理中心','专利工法办','rd','12_工程管理中心__专利工法办'],
|
||||
['工程管理中心','成本控制部','budget','13_工程管理中心__成本控制部'],
|
||||
['运营管理中心','城镇污水运营中心','ops','14_运营管理中心__城镇污水运营中心'],
|
||||
['运营管理中心','工业废水运营中心','ops','15_运营管理中心__工业废水运营中心'],
|
||||
['市场部','经营部','crm','16_市场部__经营部'],
|
||||
['市场部','办事处','crm','17_市场部__办事处'],
|
||||
['市场部','分公司','crm','18_市场部__分公司'],
|
||||
['支付中心','结算中心','payment','19_支付中心__结算中心'],
|
||||
['支付中心','财务部','finance','20_支付中心__财务部'],
|
||||
['支付中心','金融办','payment','21_支付中心__金融办'],
|
||||
['内控部','法务风险部','legal','22_内控部__法务风险部'],
|
||||
['内控部','审计监察部','audit','23_内控部__审计监察部'],
|
||||
['品牌推广部','宣传部','culture','24_品牌推广部__宣传部'],
|
||||
['品牌推广部','项目文化','culture','25_品牌推广部__项目文化'],
|
||||
['行政','综合部','hr','26_行政__综合部'],
|
||||
['行政','信息部','itasset','27_行政__信息部'],
|
||||
['行政','办公室','admin','28_行政__办公室'],
|
||||
['行政','后勤','admin','29_行政__后勤'],
|
||||
]
|
||||
|
||||
log(`W4:${UNITS.length} 机构补94个可建PARTIAL缺口`)
|
||||
phase('补可建缺口W5')
|
||||
const results = await parallel(UNITS.map(([dept, sub, mod, fn]) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP【把这个机构剩余的"可建PARTIAL缺口"推向真正MET】:${dept} / ${sub}。
|
||||
第一步 运行 python3 取本机构的剩余可建缺口:python3 -c "import json;d=json.load(open('${GAPS}'));[print('['+g['severity']+']',g['module'],':',g['gap']) for g in d['buildable'] if '${sub}' in g['area']]"
|
||||
若上面输出为空,说明本机构无可建缺口,直接返回空结果(closedGaps=[])。
|
||||
第二步 Read 需求切片 ${SLICE}/${fn}.txt 对照理解。
|
||||
第三步 grep/读码确认现状(本机构已有很多控制器/实体),针对每条可建缺口补完真实现:缺的结构化实体(如测试计划TestPlan)/状态机端点/甘特或日历聚合API/自动计算逻辑(如标准成本从BOM+工艺路线展开)/跨模块联动写入(如发布BOM到生产)/规则引擎自动触发钩子/调度Job(@Scheduled自动下架/生成)/统计分析端点(上市周期/成功率/三维投入)等。新建实体+仓库+控制器(+服务)与真实前端页,把PARTIAL真正补全到可用。
|
||||
**优先 high>med>low**。**凡缺口本质需要外部系统的**(真CA电子签/数字证书/区块链存证、BIM碰撞、CAD/Revit解析、AI语义/知识图谱/向量、JPush/APNs推送网关、语音录入、IoT/SCADA、银企直连/税务直连)——放入skippedExternal数组并简述,本轮不做。
|
||||
前端页挂模块 '${mod}'。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果(closedGaps列出真正补完到MET的缺口模块名;skippedExternal列出跳过的;导航 moduleId='${mod}')。`,
|
||||
{ label: `W5:${sub}`, phase: '补可建缺口W5', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
const closed = results.reduce((s, r) => s + (r.closedGaps || []).length, 0)
|
||||
const skipped = results.reduce((s, r) => s + (r.skippedExternal || []).length, 0)
|
||||
const bf = results.reduce((s, r) => s + (r.backendFiles || []).length, 0)
|
||||
const ff = results.reduce((s, r) => s + (r.frontendFiles || []).length, 0)
|
||||
log(`W5完成: 补完${closed}缺口 跳过外部${skipped}; 后端文件${bf} 前端页${ff}`)
|
||||
return { built: results.length, total: UNITS.length, closed, skipped, backendFiles: bf, frontendFiles: ff, results }
|
||||
@@ -0,0 +1,105 @@
|
||||
export const meta = {
|
||||
name: 'erp-w6-buildable',
|
||||
description: 'W6:29机构并行把剩余45个可建PARTIAL缺口推向MET(补状态机/聚合/联动/调度/自动取数;跳过需外部系统的28个)',
|
||||
phases: [{ title: '补可建缺口W6' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:web/FinancingController.java、web/DevProjectController.java(状态机+审批自动展开)、聚合 web/FundPoolController.java、调度 @Scheduled、前端 oa/pages/payment/repayment.vue。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double);②日期String+LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400/409中文),状态迁移/级联@Transactional;④仓库extends JpaRepository派生查询;⑤前端真页接真后端(import { http },已解包ApiResp.data,token键oa.token)。
|
||||
|
||||
**⚠️W3量产5大崩溃坑——本轮绝不再犯(逐条自查)**:
|
||||
[后端]①**Map.of()最多10对键值**(20参)——超过就编译失败"找不到合适的方法";多字段Map一律用 new java.util.LinkedHashMap<>() 逐.put()。
|
||||
②**SQLite保留字绝不做列名/字段名**:references/primary/order/group/key/values/index/table/column/check/default/constraint/references/desc/asc等;若业务字段必须叫这名,Java字段可留但**必须**加@Column(name="安全别名")映射物理列(并import jakarta.persistence.Column),否则建表DDL崩"near xxx: syntax error"。
|
||||
③**派生查询禁用ContainingIgnoreCase**(Hibernate6社区SQLite方言upper()类型校验崩,启动即挂)——一律用 Containing(SQLite的LIKE对ASCII本就大小写不敏感,中文无大小写,功能等价)。
|
||||
[前端]④**el-table-column插槽**:写 #default="{ row }" 或 #default="{ row }: { row: any }";**绝不写 typeof X[0] / typeof X.value[0] 注解**(vue-tsc过但vite编译/类型崩),绝不套外层括号。
|
||||
⑤**v-model必须是可写成员表达式**:绝不 v-model="!!expr" 或 v-model="fn()"(vite编译崩"must be a valid JavaScript member expression");需要派生可见性用 :model-value="!!x" @update:model-value="(v:boolean)=>{ if(!v) x=null }"。
|
||||
⑥**图标必须真存在于@element-plus/icons-vue**(MobilePhone不存在→用Iphone;不确定就用 Document/List/Money/DataLine 等常见图标);http删除用 http.del() 不是 http.delete()。
|
||||
⑦**具名插槽「<template #footer>」/「#header」/「#default」必须是组件(el-dialog/el-card/el-table-column)的直接子节点,绝不能嵌在「<div>」等HTML元素里**(否则vite vue编译器崩"Cannot read properties of undefined reading type",整个build失败)——dialog里要按状态切换footer时,footer提到dialog直属用「<template v-if>」切换,别把footer放进「<div v-if>」。
|
||||
⑧**http参数形态**:「http.get<T>(url, query)」第2参直接就是query对象(「Record<string,string|number|boolean|null|undefined>」),**不是**「{ params: {...} }」;「http.post<T>(url, body, opts)」的opts用「query」键不是「params」;声明query变量用「const params: Record<string, any> = {}」(别用unknown)。模板里「Promise」/「window」不在Vue全局白名单,要用就在「<script setup>」定义函数包装再调。
|
||||
⑨无emoji、无渐变(纯色蓝#2f6fed);类名表名加域前缀,grep确认与现有~623控制器/614实体零撞名。**优先新建实体;若必须给既有实体加字段,在summary注明"既有实体X加字段Y"(SQLite ddl-update不可靠加列,集成时统一schema-sync)**。
|
||||
**关键纪律**:①只新建文件或改你机构自己的页;共享文件(AuthInterceptor/oaModules/TriggerRuleEngine/WorkflowService)不自改,放sharedFileSnippets;②不运行gradle/npm;③加法式不破坏现有链;④逐文件自审Java语法(import齐全[@PathVariable/@RequestBody/@Column/domain类]、ApiResp用record访问器.data()非.getData()、括号配平、record字段一致、实体setter存在、Map.of≤10对)与Vue语法(插槽不套外括号无typeof、v-model成员表达式、http.del、图标存在)。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { type: 'string' },
|
||||
backendFiles: { type: 'array', items: { type: 'string' } },
|
||||
frontendFiles: { 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'] } },
|
||||
closedGaps: { type: 'array', items: { type: 'string' } },
|
||||
skippedExternal: { type: 'array', items: { type: 'string' }, description: '本轮判定需外部系统而跳过的缺口' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['unit', 'backendFiles', 'frontendFiles', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'closedGaps', 'skippedExternal', 'summary'],
|
||||
}
|
||||
|
||||
const GAPS = '/Users/qiu/Desktop/ERP/requirements/_xlsx_audit_w5post.json'
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const UNITS = [
|
||||
['创新研发中心','产品开发部','rd','01_创新研发中心__产品开发部'],
|
||||
['创新研发中心','申报服务部','rd','02_创新研发中心__申报服务部'],
|
||||
['创新研发中心','知识产权部','rd','03_创新研发中心__知识产权部'],
|
||||
['创新研发中心','实验室','lab','04_创新研发中心__实验室'],
|
||||
['设计研究中心','咨询可研院','design','05_设计研究中心__咨询可研院'],
|
||||
['设计研究中心','规划设计部','design','06_设计研究中心__规划设计部'],
|
||||
['设计研究中心','工程监理部','supervision','07_设计研究中心__工程监理部'],
|
||||
['制造管理中心','环保设备制造中心','mfg','08_制造管理中心__环保设备制造中心'],
|
||||
['制造管理中心','生物质肥料制造中心','mfg','09_制造管理中心__生物质肥料制造中心'],
|
||||
['工程管理中心','质安部','ehs','10_工程管理中心__质安部'],
|
||||
['工程管理中心','资料室','archive','11_工程管理中心__资料室'],
|
||||
['工程管理中心','专利工法办','rd','12_工程管理中心__专利工法办'],
|
||||
['工程管理中心','成本控制部','budget','13_工程管理中心__成本控制部'],
|
||||
['运营管理中心','城镇污水运营中心','ops','14_运营管理中心__城镇污水运营中心'],
|
||||
['运营管理中心','工业废水运营中心','ops','15_运营管理中心__工业废水运营中心'],
|
||||
['市场部','经营部','crm','16_市场部__经营部'],
|
||||
['市场部','办事处','crm','17_市场部__办事处'],
|
||||
['市场部','分公司','crm','18_市场部__分公司'],
|
||||
['支付中心','结算中心','payment','19_支付中心__结算中心'],
|
||||
['支付中心','财务部','finance','20_支付中心__财务部'],
|
||||
['支付中心','金融办','payment','21_支付中心__金融办'],
|
||||
['内控部','法务风险部','legal','22_内控部__法务风险部'],
|
||||
['内控部','审计监察部','audit','23_内控部__审计监察部'],
|
||||
['品牌推广部','宣传部','culture','24_品牌推广部__宣传部'],
|
||||
['品牌推广部','项目文化','culture','25_品牌推广部__项目文化'],
|
||||
['行政','综合部','hr','26_行政__综合部'],
|
||||
['行政','信息部','itasset','27_行政__信息部'],
|
||||
['行政','办公室','admin','28_行政__办公室'],
|
||||
['行政','后勤','admin','29_行政__后勤'],
|
||||
]
|
||||
|
||||
log(`W4:${UNITS.length} 机构补94个可建PARTIAL缺口`)
|
||||
phase('补可建缺口W6')
|
||||
const results = await parallel(UNITS.map(([dept, sub, mod, fn]) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP【把这个机构剩余的"可建PARTIAL缺口"推向真正MET】:${dept} / ${sub}。
|
||||
第一步 运行 python3 取本机构的剩余可建缺口:python3 -c "import json;d=json.load(open('${GAPS}'));[print('['+g['severity']+']',g['module'],':',g['gap']) for g in d['buildable'] if '${sub}' in g['area']]"
|
||||
若上面输出为空,说明本机构无可建缺口,直接返回空结果(closedGaps=[])。
|
||||
第二步 Read 需求切片 ${SLICE}/${fn}.txt 对照理解。
|
||||
第三步 grep/读码确认现状(本机构已有很多控制器/实体),针对每条可建缺口补完真实现:缺的结构化实体(如测试计划TestPlan)/状态机端点/甘特或日历聚合API/自动计算逻辑(如标准成本从BOM+工艺路线展开)/跨模块联动写入(如发布BOM到生产)/规则引擎自动触发钩子/调度Job(@Scheduled自动下架/生成)/统计分析端点(上市周期/成功率/三维投入)等。新建实体+仓库+控制器(+服务)与真实前端页,把PARTIAL真正补全到可用。
|
||||
**优先 high>med>low**。**凡缺口本质需要外部系统的**(真CA电子签/数字证书/区块链存证、BIM碰撞、CAD/Revit解析、AI语义/知识图谱/向量、JPush/APNs推送网关、语音录入、IoT/SCADA、银企直连/税务直连)——放入skippedExternal数组并简述,本轮不做。
|
||||
前端页挂模块 '${mod}'。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果(closedGaps列出真正补完到MET的缺口模块名;skippedExternal列出跳过的;导航 moduleId='${mod}')。`,
|
||||
{ label: `W6:${sub}`, phase: '补可建缺口W6', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
const closed = results.reduce((s, r) => s + (r.closedGaps || []).length, 0)
|
||||
const skipped = results.reduce((s, r) => s + (r.skippedExternal || []).length, 0)
|
||||
const bf = results.reduce((s, r) => s + (r.backendFiles || []).length, 0)
|
||||
const ff = results.reduce((s, r) => s + (r.frontendFiles || []).length, 0)
|
||||
log(`W6完成: 补完${closed}缺口 跳过外部${skipped}; 后端文件${bf} 前端页${ff}`)
|
||||
return { built: results.length, total: UNITS.length, closed, skipped, backendFiles: bf, frontendFiles: ff, results }
|
||||
@@ -0,0 +1,106 @@
|
||||
export const meta = {
|
||||
name: 'erp-w7-buildable',
|
||||
description: 'W7:29机构并行攻剩余45个可建+种子/小bug缺口(补种子数据让空表功能可演示+修小bug+建真缺功能;跳过AI/LLM/外部)',
|
||||
phases: [{ title: '补可建缺口W7' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:web/FinancingController.java、web/DevProjectController.java(状态机+审批自动展开)、聚合 web/FundPoolController.java、调度 @Scheduled、前端 oa/pages/payment/repayment.vue。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double);②日期String+LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400/409中文),状态迁移/级联@Transactional;④仓库extends JpaRepository派生查询;⑤前端真页接真后端(import { http },已解包ApiResp.data,token键oa.token)。
|
||||
|
||||
**⚠️W3量产5大崩溃坑——本轮绝不再犯(逐条自查)**:
|
||||
[后端]①**Map.of()最多10对键值**(20参)——超过就编译失败"找不到合适的方法";多字段Map一律用 new java.util.LinkedHashMap<>() 逐.put()。
|
||||
②**SQLite保留字绝不做列名/字段名**:references/primary/order/group/key/values/index/table/column/check/default/constraint/references/desc/asc等;若业务字段必须叫这名,Java字段可留但**必须**加@Column(name="安全别名")映射物理列(并import jakarta.persistence.Column),否则建表DDL崩"near xxx: syntax error"。
|
||||
③**派生查询禁用ContainingIgnoreCase**(Hibernate6社区SQLite方言upper()类型校验崩,启动即挂)——一律用 Containing(SQLite的LIKE对ASCII本就大小写不敏感,中文无大小写,功能等价)。
|
||||
[前端]④**el-table-column插槽**:写 #default="{ row }" 或 #default="{ row }: { row: any }";**绝不写 typeof X[0] / typeof X.value[0] 注解**(vue-tsc过但vite编译/类型崩),绝不套外层括号。
|
||||
⑤**v-model必须是可写成员表达式**:绝不 v-model="!!expr" 或 v-model="fn()"(vite编译崩"must be a valid JavaScript member expression");需要派生可见性用 :model-value="!!x" @update:model-value="(v:boolean)=>{ if(!v) x=null }"。
|
||||
⑥**图标必须真存在于@element-plus/icons-vue**(MobilePhone不存在→用Iphone;不确定就用 Document/List/Money/DataLine 等常见图标);http删除用 http.del() 不是 http.delete()。
|
||||
⑦**具名插槽「<template #footer>」/「#header」/「#default」必须是组件(el-dialog/el-card/el-table-column)的直接子节点,绝不能嵌在「<div>」等HTML元素里**(否则vite vue编译器崩"Cannot read properties of undefined reading type",整个build失败)——dialog里要按状态切换footer时,footer提到dialog直属用「<template v-if>」切换,别把footer放进「<div v-if>」。
|
||||
⑧**http参数形态**:「http.get<T>(url, query)」第2参直接就是query对象(「Record<string,string|number|boolean|null|undefined>」),**不是**「{ params: {...} }」;「http.post<T>(url, body, opts)」的opts用「query」键不是「params」;声明query变量用「const params: Record<string, any> = {}」(别用unknown)。模板里「Promise」/「window」不在Vue全局白名单,要用就在「<script setup>」定义函数包装再调。
|
||||
⑨无emoji、无渐变(纯色蓝#2f6fed);类名表名加域前缀,grep确认与现有~623控制器/614实体零撞名。**优先新建实体;若必须给既有实体加字段,在summary注明"既有实体X加字段Y"(SQLite ddl-update不可靠加列,集成时统一schema-sync)**。
|
||||
**关键纪律**:①只新建文件或改你机构自己的页;共享文件(AuthInterceptor/oaModules/TriggerRuleEngine/WorkflowService)不自改,放sharedFileSnippets;②不运行gradle/npm;③加法式不破坏现有链;④逐文件自审Java语法(import齐全[@PathVariable/@RequestBody/@Column/domain类]、ApiResp用record访问器.data()非.getData()、括号配平、record字段一致、实体setter存在、Map.of≤10对)与Vue语法(插槽不套外括号无typeof、v-model成员表达式、http.del、图标存在)。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { type: 'string' },
|
||||
backendFiles: { type: 'array', items: { type: 'string' } },
|
||||
frontendFiles: { 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'] } },
|
||||
closedGaps: { type: 'array', items: { type: 'string' } },
|
||||
skippedExternal: { type: 'array', items: { type: 'string' }, description: '本轮判定需外部系统而跳过的缺口' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['unit', 'backendFiles', 'frontendFiles', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'closedGaps', 'skippedExternal', 'summary'],
|
||||
}
|
||||
|
||||
const GAPS = '/Users/qiu/Desktop/ERP/requirements/_xlsx_audit_w6post.json'
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const UNITS = [
|
||||
['创新研发中心','产品开发部','rd','01_创新研发中心__产品开发部'],
|
||||
['创新研发中心','申报服务部','rd','02_创新研发中心__申报服务部'],
|
||||
['创新研发中心','知识产权部','rd','03_创新研发中心__知识产权部'],
|
||||
['创新研发中心','实验室','lab','04_创新研发中心__实验室'],
|
||||
['设计研究中心','咨询可研院','design','05_设计研究中心__咨询可研院'],
|
||||
['设计研究中心','规划设计部','design','06_设计研究中心__规划设计部'],
|
||||
['设计研究中心','工程监理部','supervision','07_设计研究中心__工程监理部'],
|
||||
['制造管理中心','环保设备制造中心','mfg','08_制造管理中心__环保设备制造中心'],
|
||||
['制造管理中心','生物质肥料制造中心','mfg','09_制造管理中心__生物质肥料制造中心'],
|
||||
['工程管理中心','质安部','ehs','10_工程管理中心__质安部'],
|
||||
['工程管理中心','资料室','archive','11_工程管理中心__资料室'],
|
||||
['工程管理中心','专利工法办','rd','12_工程管理中心__专利工法办'],
|
||||
['工程管理中心','成本控制部','budget','13_工程管理中心__成本控制部'],
|
||||
['运营管理中心','城镇污水运营中心','ops','14_运营管理中心__城镇污水运营中心'],
|
||||
['运营管理中心','工业废水运营中心','ops','15_运营管理中心__工业废水运营中心'],
|
||||
['市场部','经营部','crm','16_市场部__经营部'],
|
||||
['市场部','办事处','crm','17_市场部__办事处'],
|
||||
['市场部','分公司','crm','18_市场部__分公司'],
|
||||
['支付中心','结算中心','payment','19_支付中心__结算中心'],
|
||||
['支付中心','财务部','finance','20_支付中心__财务部'],
|
||||
['支付中心','金融办','payment','21_支付中心__金融办'],
|
||||
['内控部','法务风险部','legal','22_内控部__法务风险部'],
|
||||
['内控部','审计监察部','audit','23_内控部__审计监察部'],
|
||||
['品牌推广部','宣传部','culture','24_品牌推广部__宣传部'],
|
||||
['品牌推广部','项目文化','culture','25_品牌推广部__项目文化'],
|
||||
['行政','综合部','hr','26_行政__综合部'],
|
||||
['行政','信息部','itasset','27_行政__信息部'],
|
||||
['行政','办公室','admin','28_行政__办公室'],
|
||||
['行政','后勤','admin','29_行政__后勤'],
|
||||
]
|
||||
|
||||
log(`W4:${UNITS.length} 机构补94个可建PARTIAL缺口`)
|
||||
phase('补可建缺口W7')
|
||||
const results = await parallel(UNITS.map(([dept, sub, mod, fn]) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP【把这个机构剩余的"可建PARTIAL缺口"推向真正MET】:${dept} / ${sub}。
|
||||
第一步 运行 python3 取本机构的剩余可建缺口:python3 -c "import json;d=json.load(open('${GAPS}'));[print('['+g['severity']+']',g['module'],':',g['gap']) for g in d['buildable'] if '${sub}' in g['area']]"
|
||||
若上面输出为空,说明本机构无可建缺口,直接返回空结果(closedGaps=[])。
|
||||
第二步 Read 需求切片 ${SLICE}/${fn}.txt 对照理解。
|
||||
第三步 grep/读码确认现状(本机构已有很多控制器/实体),针对每条可建缺口补完真实现:缺的结构化实体(如测试计划TestPlan)/状态机端点/甘特或日历聚合API/自动计算逻辑(如标准成本从BOM+工艺路线展开)/跨模块联动写入(如发布BOM到生产)/规则引擎自动触发钩子/调度Job(@Scheduled自动下架/生成)/统计分析端点(上市周期/成功率/三维投入)等。新建实体+仓库+控制器(+服务)与真实前端页,把PARTIAL真正补全到可用。
|
||||
**本轮特别注意三类廉价高值修复**:①**缺口提到"表空/0条/无种子数据/活体返回null,功能在但无数据演示"**→在对应的 seed/ 目录 Seeder(@Order)或新建Seeder补**真实演示数据**(金额BigDecimal,日期合理,跨状态多条),让该功能活体可见;②**缺口提到"路径错误/字段需调试/返回400/正确路径为X"等小bug**→直接读码定位并修正(改控制器路径/补@RequestParam/修字段名/补@PathVariable),这类一行修复最划算;③**缺口提到"前端缺可视化页/无看板/无录入入口/页面调错接口"**→新建或修正前端.vue页接对后端真接口。
|
||||
**优先 high>med>low**。**凡缺口本质需要外部系统的**(真CA电子签/数字证书/区块链存证、BIM碰撞、CAD/Revit解析、AI语义/知识图谱/向量、JPush/APNs推送网关、语音录入、IoT/SCADA、银企直连/税务直连)——放入skippedExternal数组并简述,本轮不做。
|
||||
前端页挂模块 '${mod}'。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果(closedGaps列出真正补完到MET的缺口模块名;skippedExternal列出跳过的;导航 moduleId='${mod}')。`,
|
||||
{ label: `W7:${sub}`, phase: '补可建缺口W7', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
const closed = results.reduce((s, r) => s + (r.closedGaps || []).length, 0)
|
||||
const skipped = results.reduce((s, r) => s + (r.skippedExternal || []).length, 0)
|
||||
const bf = results.reduce((s, r) => s + (r.backendFiles || []).length, 0)
|
||||
const ff = results.reduce((s, r) => s + (r.frontendFiles || []).length, 0)
|
||||
log(`W7完成: 补完${closed}缺口 跳过外部${skipped}; 后端文件${bf} 前端页${ff}`)
|
||||
return { built: results.length, total: UNITS.length, closed, skipped, backendFiles: bf, frontendFiles: ff, results }
|
||||
@@ -0,0 +1,106 @@
|
||||
export const meta = {
|
||||
name: 'erp-w8-buildable',
|
||||
description: 'W8:29机构并行攻最后40个可建+种子/bug缺口(末轮内部推进:加字段/接审批流/补种子/建前端页/修小bug;跳过CA/BIM/CAD/AI-LLM/IoT/商用API外部)',
|
||||
phases: [{ title: '补可建缺口W8' }],
|
||||
}
|
||||
|
||||
const COMMON = `黄金模板:web/FinancingController.java、web/DevProjectController.java(状态机+审批自动展开)、聚合 web/FundPoolController.java、调度 @Scheduled、前端 oa/pages/payment/repayment.vue。
|
||||
硬约束:①金额BigDecimal+com.kaidi.oa.common.Money(无裸double);②日期String+LocalDate/ChronoUnit;③控制器@RestController @RequestMapping("/api/oa/<资源>"),ApiResp.ok(),record请求体,NotFoundException/ApiException(400/409中文),状态迁移/级联@Transactional;④仓库extends JpaRepository派生查询;⑤前端真页接真后端(import { http },已解包ApiResp.data,token键oa.token)。
|
||||
|
||||
**⚠️W3量产5大崩溃坑——本轮绝不再犯(逐条自查)**:
|
||||
[后端]①**Map.of()最多10对键值**(20参)——超过就编译失败"找不到合适的方法";多字段Map一律用 new java.util.LinkedHashMap<>() 逐.put()。
|
||||
②**SQLite保留字绝不做列名/字段名**:references/primary/order/group/key/values/index/table/column/check/default/constraint/references/desc/asc等;若业务字段必须叫这名,Java字段可留但**必须**加@Column(name="安全别名")映射物理列(并import jakarta.persistence.Column),否则建表DDL崩"near xxx: syntax error"。
|
||||
③**派生查询禁用ContainingIgnoreCase**(Hibernate6社区SQLite方言upper()类型校验崩,启动即挂)——一律用 Containing(SQLite的LIKE对ASCII本就大小写不敏感,中文无大小写,功能等价)。
|
||||
[前端]④**el-table-column插槽**:写 #default="{ row }" 或 #default="{ row }: { row: any }";**绝不写 typeof X[0] / typeof X.value[0] 注解**(vue-tsc过但vite编译/类型崩),绝不套外层括号。
|
||||
⑤**v-model必须是可写成员表达式**:绝不 v-model="!!expr" 或 v-model="fn()"(vite编译崩"must be a valid JavaScript member expression");需要派生可见性用 :model-value="!!x" @update:model-value="(v:boolean)=>{ if(!v) x=null }"。
|
||||
⑥**图标必须真存在于@element-plus/icons-vue**(MobilePhone不存在→用Iphone;不确定就用 Document/List/Money/DataLine 等常见图标);http删除用 http.del() 不是 http.delete()。
|
||||
⑦**具名插槽「<template #footer>」/「#header」/「#default」必须是组件(el-dialog/el-card/el-table-column)的直接子节点,绝不能嵌在「<div>」等HTML元素里**(否则vite vue编译器崩"Cannot read properties of undefined reading type",整个build失败)——dialog里要按状态切换footer时,footer提到dialog直属用「<template v-if>」切换,别把footer放进「<div v-if>」。
|
||||
⑧**http参数形态**:「http.get<T>(url, query)」第2参直接就是query对象(「Record<string,string|number|boolean|null|undefined>」),**不是**「{ params: {...} }」;「http.post<T>(url, body, opts)」的opts用「query」键不是「params」;声明query变量用「const params: Record<string, any> = {}」(别用unknown)。模板里「Promise」/「window」不在Vue全局白名单,要用就在「<script setup>」定义函数包装再调。
|
||||
⑨无emoji、无渐变(纯色蓝#2f6fed);类名表名加域前缀,grep确认与现有~623控制器/614实体零撞名。**优先新建实体;若必须给既有实体加字段,在summary注明"既有实体X加字段Y"(SQLite ddl-update不可靠加列,集成时统一schema-sync)**。
|
||||
**关键纪律**:①只新建文件或改你机构自己的页;共享文件(AuthInterceptor/oaModules/TriggerRuleEngine/WorkflowService)不自改,放sharedFileSnippets;②不运行gradle/npm;③加法式不破坏现有链;④逐文件自审Java语法(import齐全[@PathVariable/@RequestBody/@Column/domain类]、ApiResp用record访问器.data()非.getData()、括号配平、record字段一致、实体setter存在、Map.of≤10对)与Vue语法(插槽不套外括号无typeof、v-model成员表达式、http.del、图标存在)。`
|
||||
|
||||
const RESULT = {
|
||||
type: 'object', additionalProperties: false,
|
||||
properties: {
|
||||
unit: { type: 'string' },
|
||||
backendFiles: { type: 'array', items: { type: 'string' } },
|
||||
frontendFiles: { 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'] } },
|
||||
closedGaps: { type: 'array', items: { type: 'string' } },
|
||||
skippedExternal: { type: 'array', items: { type: 'string' }, description: '本轮判定需外部系统而跳过的缺口' },
|
||||
summary: { type: 'string' },
|
||||
},
|
||||
required: ['unit', 'backendFiles', 'frontendFiles', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'closedGaps', 'skippedExternal', 'summary'],
|
||||
}
|
||||
|
||||
const GAPS = '/Users/qiu/Desktop/ERP/requirements/_xlsx_audit_w7post.json'
|
||||
const SLICE = '/Users/qiu/Desktop/ERP/requirements/_req_slices'
|
||||
const UNITS = [
|
||||
['创新研发中心','产品开发部','rd','01_创新研发中心__产品开发部'],
|
||||
['创新研发中心','申报服务部','rd','02_创新研发中心__申报服务部'],
|
||||
['创新研发中心','知识产权部','rd','03_创新研发中心__知识产权部'],
|
||||
['创新研发中心','实验室','lab','04_创新研发中心__实验室'],
|
||||
['设计研究中心','咨询可研院','design','05_设计研究中心__咨询可研院'],
|
||||
['设计研究中心','规划设计部','design','06_设计研究中心__规划设计部'],
|
||||
['设计研究中心','工程监理部','supervision','07_设计研究中心__工程监理部'],
|
||||
['制造管理中心','环保设备制造中心','mfg','08_制造管理中心__环保设备制造中心'],
|
||||
['制造管理中心','生物质肥料制造中心','mfg','09_制造管理中心__生物质肥料制造中心'],
|
||||
['工程管理中心','质安部','ehs','10_工程管理中心__质安部'],
|
||||
['工程管理中心','资料室','archive','11_工程管理中心__资料室'],
|
||||
['工程管理中心','专利工法办','rd','12_工程管理中心__专利工法办'],
|
||||
['工程管理中心','成本控制部','budget','13_工程管理中心__成本控制部'],
|
||||
['运营管理中心','城镇污水运营中心','ops','14_运营管理中心__城镇污水运营中心'],
|
||||
['运营管理中心','工业废水运营中心','ops','15_运营管理中心__工业废水运营中心'],
|
||||
['市场部','经营部','crm','16_市场部__经营部'],
|
||||
['市场部','办事处','crm','17_市场部__办事处'],
|
||||
['市场部','分公司','crm','18_市场部__分公司'],
|
||||
['支付中心','结算中心','payment','19_支付中心__结算中心'],
|
||||
['支付中心','财务部','finance','20_支付中心__财务部'],
|
||||
['支付中心','金融办','payment','21_支付中心__金融办'],
|
||||
['内控部','法务风险部','legal','22_内控部__法务风险部'],
|
||||
['内控部','审计监察部','audit','23_内控部__审计监察部'],
|
||||
['品牌推广部','宣传部','culture','24_品牌推广部__宣传部'],
|
||||
['品牌推广部','项目文化','culture','25_品牌推广部__项目文化'],
|
||||
['行政','综合部','hr','26_行政__综合部'],
|
||||
['行政','信息部','itasset','27_行政__信息部'],
|
||||
['行政','办公室','admin','28_行政__办公室'],
|
||||
['行政','后勤','admin','29_行政__后勤'],
|
||||
]
|
||||
|
||||
log(`W4:${UNITS.length} 机构补94个可建PARTIAL缺口`)
|
||||
phase('补可建缺口W8')
|
||||
const results = await parallel(UNITS.map(([dept, sub, mod, fn]) => () =>
|
||||
agent(
|
||||
`你是资深全栈工程师,为凯迪 ERP【把这个机构剩余的"可建PARTIAL缺口"推向真正MET】:${dept} / ${sub}。
|
||||
第一步 运行 python3 取本机构的剩余可建缺口:python3 -c "import json;d=json.load(open('${GAPS}'));[print('['+g['severity']+']',g['module'],':',g['gap']) for g in d['buildable'] if '${sub}' in g['area']]"
|
||||
若上面输出为空,说明本机构无可建缺口,**立即返回空结果(closedGaps=[],backendFiles=[],frontendFiles=[]),绝对不要替其它机构做缺口、不要新建任何文件、不要"顺手"补邻居单元的功能**(上一轮多个agent抢做同一跨单元缺口产生了重复Seeder,本轮严禁)——只做 ${sub} 本机构过滤命中的缺口。
|
||||
第二步 Read 需求切片 ${SLICE}/${fn}.txt 对照理解。
|
||||
第三步 grep/读码确认现状(本机构已有很多控制器/实体),针对每条可建缺口补完真实现:缺的结构化实体(如测试计划TestPlan)/状态机端点/甘特或日历聚合API/自动计算逻辑(如标准成本从BOM+工艺路线展开)/跨模块联动写入(如发布BOM到生产)/规则引擎自动触发钩子/调度Job(@Scheduled自动下架/生成)/统计分析端点(上市周期/成功率/三维投入)等。新建实体+仓库+控制器(+服务)与真实前端页,把PARTIAL真正补全到可用。
|
||||
**本轮特别注意三类廉价高值修复**:①**缺口提到"表空/0条/无种子数据/活体返回null,功能在但无数据演示"**→在对应的 seed/ 目录 Seeder(@Order)或新建Seeder补**真实演示数据**(金额BigDecimal,日期合理,跨状态多条),让该功能活体可见;②**缺口提到"路径错误/字段需调试/返回400/正确路径为X"等小bug**→直接读码定位并修正(改控制器路径/补@RequestParam/修字段名/补@PathVariable),这类一行修复最划算;③**缺口提到"前端缺可视化页/无看板/无录入入口/页面调错接口"**→新建或修正前端.vue页接对后端真接口。
|
||||
**优先 high>med>low**。**凡缺口本质需要外部系统的**(真CA电子签/数字证书/区块链存证、BIM碰撞、CAD/Revit解析、AI语义/知识图谱/向量、JPush/APNs推送网关、语音录入、IoT/SCADA、银企直连/税务直连)——放入skippedExternal数组并简述,本轮不做。
|
||||
前端页挂模块 '${mod}'。
|
||||
|
||||
${COMMON}
|
||||
|
||||
返回结构化结果(closedGaps列出真正补完到MET的缺口模块名;skippedExternal列出跳过的;导航 moduleId='${mod}')。`,
|
||||
{ label: `W8:${sub}`, phase: '补可建缺口W8', schema: RESULT, model: 'sonnet' }
|
||||
)
|
||||
)).then((a) => a.filter(Boolean))
|
||||
|
||||
const closed = results.reduce((s, r) => s + (r.closedGaps || []).length, 0)
|
||||
const skipped = results.reduce((s, r) => s + (r.skippedExternal || []).length, 0)
|
||||
const bf = results.reduce((s, r) => s + (r.backendFiles || []).length, 0)
|
||||
const ff = results.reduce((s, r) => s + (r.frontendFiles || []).length, 0)
|
||||
log(`W8完成: 补完${closed}缺口 跳过外部${skipped}; 后端文件${bf} 前端页${ff}`)
|
||||
return { built: results.length, total: UNITS.length, closed, skipped, backendFiles: bf, frontendFiles: ff, results }
|
||||
Reference in New Issue
Block a user