// 一次性脚本:通过 HTTP API 向运行中的后端批量灌入 3 个评估示例。 const BASE = process.env.API_BASE ?? 'http://localhost:3005'; const SEP = '\u0000'; // indicatorKey 复合键分隔符(NUL) const kd = (rows) => rows.map(([d, i, l]) => [`${d}${SEP}${i}`, l]); const cases = [ { name: '案例1 银行IT运维岗位外包(预期可接受)', body: { projectDescription: '为某大型国有银行提供IT运维岗位外包服务。客户资信优良、注册资本充足、无失信记录;账期30天且历史回款准时;岗位为常规运维支持非高危;SLA交付标准清晰可量化;毛利率充足、人力成本可控。', confirmation: { businessType: '岗位外包', industry: '通用' }, region: 'CN-SH', assessorId: 'sales-001', knownData: kd([ ['dim-customer', 'customer-credit', 1], ['dim-customer', 'payment-ability', 1], ['dim-position', 'position-nature', 2], ['dim-business', 'delivery-standard', 1], ['dim-labor', 'layoff-risk', 2], ['dim-labor', 'injury-risk', 1], ['dim-financial', 'gross-margin', 2], ['dim-legal', 'qualification', 1], ['dim-lifecycle', 'lifecycle-stage', 2], ['dim-macro', 'macro-policy', 2], ]), costInputs: { baselineQuote: 2000000 }, topN: 5, }, }, { name: '案例2 互联网客服BPO(预期有条件接受)', body: { projectDescription: '为某成长期互联网公司提供客服BPO外包。客户为创业公司资信一般、账期90天且偶有逾期;岗位含部分替代性用工;SLA标准较模糊;毛利率偏薄;存在一定裁员与合规风险。', confirmation: { businessType: 'BPO', industry: '通用' }, region: 'CN-GD', assessorId: 'sales-002', knownData: kd([ ['dim-customer', 'customer-credit', 4], ['dim-customer', 'payment-ability', 4], ['dim-position', 'position-nature', 4], ['dim-business', 'delivery-standard', 4], ['dim-labor', 'layoff-risk', 4], ['dim-labor', 'injury-risk', 3], ['dim-financial', 'gross-margin', 4], ['dim-legal', 'qualification', 3], ['dim-lifecycle', 'lifecycle-stage', 3], ['dim-macro', 'macro-policy', 3], ]), costInputs: { baselineQuote: 1200000 }, topN: 5, }, }, { name: '案例3 衰退期制造高危劳务派遣(预期不可接受)', body: { projectDescription: '为某衰退期制造企业提供高危产线劳务派遣。客户资信差、已有涉诉与逾期记录;账期超120天回款困难;岗位为高危作业工伤风险高;测算毛利率为负;资质不全存在假外包真派遣风险。', confirmation: { businessType: '劳务派遣', industry: '通用' }, region: 'CN-HB', assessorId: 'sales-003', knownData: kd([ ['dim-customer', 'customer-credit', 5], ['dim-customer', 'payment-ability', 5], ['dim-position', 'position-nature', 5], ['dim-business', 'delivery-standard', 5], ['dim-labor', 'layoff-risk', 5], ['dim-labor', 'injury-risk', 5], ['dim-financial', 'gross-margin', 5], ['dim-legal', 'qualification', 5], ['dim-lifecycle', 'lifecycle-stage', 5], ['dim-macro', 'macro-policy', 4], ]), costInputs: { baselineQuote: 800000 }, topN: 5, }, }, ]; for (const c of cases) { const res = await fetch(`${BASE}/api/assessments/run`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(c.body), }); const j = await res.json(); if (!res.ok) { console.error(`✗ ${c.name} 失败 [${res.status}]:`, j.error ?? j); continue; } console.log( `✓ ${c.name}\n id=${j.assessmentId} | score=${j.riskScore} grade=${j.riskGrade} | 结论=${j.acceptability} | 报价 ${j.assessment.costEstimate.baselineQuote}->${j.assessment.costEstimate.riskAdjustedQuote}`, ); } // 校验列表接口 const list = await (await fetch(`${BASE}/api/assessments`)).json(); console.log(`\n后端现有评估记录数:${list.length}`); for (const r of list) { console.log(` - ${r.id} | ${r.businessType} | ${r.riskGrade} | ${r.acceptability} | 状态=${r.status}`); }