Archived
W05 在途修订:差异评估结论审核件一个候选一张表 · 关键台账数据看板件(ledger-board)· S1 清单不再把人刚填的参数摆成缺口
活动包 `part-substitution-assessment`(case-model / manifest / report / target-style / badge / ledger-board 与两份包内测试)、 目标件「验收工单-01-差异评估结论审核」、`docs/ss02-act-05` 关键台账数据两份、端到端测试记录、e2e 脚本。 逐条口径见同批 CLAUDE.md 快照。2026-08-27 另一会话做的,一直留在工作树没入库;与同批另两条提交互相依赖。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
This commit is contained in:
@@ -13,8 +13,14 @@ import { manifest, D, RULE_VERSION } from '../src/manifest.ts';
|
||||
import activity from '../src/index.ts';
|
||||
|
||||
const ITEMS = ['S0_bind', 'S0d_p08_master', 'S0d_p10_document', 'S1_input_confirm', 'S2_normalize', 'S3_assess', 'S4_review', 'S5_prepare_landing', 'T_release'];
|
||||
const NO_DONE_WHEN = new Set(['S0d_p08_master', 'S0d_p10_document', 'S1_input_confirm', 'S4_review', 'T_release']);
|
||||
/*
|
||||
* 2026-08-27 晚:两张数据工单改成**给 doneWhen**(只读入库事实)—— 引擎只在人答过卡之后求它,
|
||||
* 不再靠模型记得 finish。仍不给的三处:输入确认(交人补缺口)/ 审核循环 / 放行。
|
||||
*/
|
||||
const NO_DONE_WHEN = new Set(['S1_input_confirm', 'S4_review', 'T_release']);
|
||||
const VIEWS = ['p08-master-create', 'p10-document-create', 'eval-input-list', 'difference-review', 'landing-confirm'];
|
||||
/** 运营中心 L2 沙箱里那张关键台账数据看板 —— 不是工单件,只在「都声明了」这一条里出现;自己那组断言在文件尾 */
|
||||
const BOARD_VIEW = 'activity-ledger';
|
||||
const byAddress = (domain: string, object: string) => manifest.declarations.ledger.find((l) => l.domain === domain && l.object === object);
|
||||
const viewHtml = (name: string) => manifest.assets.viewTemplates.find((t) => t.name === name)?.html ?? '';
|
||||
|
||||
@@ -67,8 +73,8 @@ describe('清单本身合规', () => {
|
||||
expect(newCustomer).toBeDefined();
|
||||
});
|
||||
|
||||
it('五张视图模版都声明了,剧本每一步引用的 view 都在其中', () => {
|
||||
expect(new Set(manifest.assets.viewTemplates.map((v) => v.name))).toEqual(new Set(VIEWS));
|
||||
it('五张工单视图 + 一张运营侧看板都声明了,剧本每一步引用的 view 都在其中', () => {
|
||||
expect(new Set(manifest.assets.viewTemplates.map((v) => v.name))).toEqual(new Set([...VIEWS, BOARD_VIEW]));
|
||||
for (const step of manifest.assets.businessModel.steps as ReadonlyArray<{ view?: string }>) {
|
||||
if (step.view !== undefined) expect(VIEWS, step.view).toContain(step.view);
|
||||
}
|
||||
@@ -158,7 +164,7 @@ describe('案例模型与清单的对齐', () => {
|
||||
expect((manifest.assets.businessModel.steps as ReadonlyArray<{ item: string }>).map((s) => s.item)).toEqual(ITEMS);
|
||||
});
|
||||
|
||||
it('五处不给 doneWhen(两张数据工单 / 输入确认 / 审核 / 放行),其余四处都给', () => {
|
||||
it('三处不给 doneWhen(输入确认 / 审核 / 放行),其余六处都给 —— 两张数据工单的只读入库事实', () => {
|
||||
for (const s of manifest.assets.businessModel.steps as ReadonlyArray<{ item: string; doneWhen?: string }>) {
|
||||
if (NO_DONE_WHEN.has(s.item)) expect(s.doneWhen, s.item).toBeUndefined();
|
||||
else expect(s.doneWhen, s.item).toBeDefined();
|
||||
@@ -313,6 +319,23 @@ describe('徽标别名与值域相关的坑(2026-08-27 实测账,回归网)', ()
|
||||
{ view: 'landing-confirm', domain: 'substitution', object: 'relation', column: 'analysis_status' },
|
||||
{ view: 'landing-confirm', domain: 'substitution', object: 'relation', column: 'risk_level' },
|
||||
{ view: 'landing-confirm', domain: 'demand', object: 'request', column: 'request_status' },
|
||||
/* 运营侧看板把六张表的枚举列全摆成徽标 —— 每一列的每个值都得有文案,漏一个就是一枚「—」 */
|
||||
{ view: BOARD_VIEW, domain: 'parts', object: 'profile', column: 'lifecycle_status' },
|
||||
{ view: BOARD_VIEW, domain: 'parts', object: 'document', column: 'document_type' },
|
||||
{ view: BOARD_VIEW, domain: 'parts', object: 'document', column: 'document_status' },
|
||||
{ view: BOARD_VIEW, domain: 'demand', object: 'request', column: 'request_status' },
|
||||
{ view: BOARD_VIEW, domain: 'demand', object: 'request', column: 'risk_level' },
|
||||
{ view: BOARD_VIEW, domain: 'substitution', object: 'relation', column: 'substitution_type' },
|
||||
{ view: BOARD_VIEW, domain: 'substitution', object: 'relation', column: 'recommendation_level' },
|
||||
{ view: BOARD_VIEW, domain: 'substitution', object: 'relation', column: 'analysis_status' },
|
||||
{ view: BOARD_VIEW, domain: 'substitution', object: 'relation', column: 'risk_level' },
|
||||
{ view: BOARD_VIEW, domain: 'substitution', object: 'difference_item', column: 'constraint_type' },
|
||||
{ view: BOARD_VIEW, domain: 'substitution', object: 'difference_item', column: 'difference_status' },
|
||||
{ view: BOARD_VIEW, domain: 'substitution', object: 'difference_item', column: 'risk_level' },
|
||||
{ view: BOARD_VIEW, domain: 'validation', object: 'record', column: 'validation_type' },
|
||||
{ view: BOARD_VIEW, domain: 'validation', object: 'record', column: 'validation_status' },
|
||||
{ view: BOARD_VIEW, domain: D, object: 'pn_check', column: 'role' },
|
||||
{ view: BOARD_VIEW, domain: D, object: 'pn_check', column: 'exists_status' },
|
||||
];
|
||||
|
||||
it('每张模版摆了徽标的每个 tally 列,声明里的每个值都有对应的 v-<token> 规则(选择器是从值算出来的,不是手写的)', () => {
|
||||
@@ -400,3 +423,134 @@ const CONTRACT = {
|
||||
prohibitions: [],
|
||||
discretion: [],
|
||||
} as const;
|
||||
|
||||
/* 验收件题头是验收绿(2026-08-27 用户定:与对话区验收卡同色,不再是目标件的红) */
|
||||
describe('两张验收件的主题色', () => {
|
||||
it('ACC1 / ACC2 的 --ledger 是验收绿 #0aa294,题头渐变不再带红;CONDITIONAL 徽标保留语义红', async () => {
|
||||
const { ACC1_CSS, ACC2_CSS } = await import('../src/views/target-style.ts');
|
||||
for (const css of [ACC1_CSS, ACC2_CSS]) {
|
||||
expect(css).toContain('--ledger:#0aa294');
|
||||
expect(css).not.toContain('--ledger:#b23a2e');
|
||||
expect(css).not.toContain('#fdf3f1');
|
||||
expect(css).toContain('rgba(10,162,148,.25)');
|
||||
}
|
||||
// ACC2 的 CONDITIONAL 徽标保留目标件的语义红;ACC1 目标件 2026-08-27 改版把它改成了品牌蓝,照抄
|
||||
expect(ACC2_CSS).toContain('.st.cond{color:#b23a2e');
|
||||
expect(ACC1_CSS).toContain('.st.cond{color:var(--brand-deep)');
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* 差异评估结论审核 · 目标件 2026-08-27 改版:「一个候选一张表」(用户:存在多个替代 PN 要对比差异时看不清楚)。
|
||||
* 外层按 relation 逐个复制 <section class="cand">,里层明细只列该候选名下的行(data-by 父键过滤);
|
||||
* 汇总表一个候选一条;品牌从 parts.profile 整表按料号挑(取值,不是算)。
|
||||
*/
|
||||
describe('difference-review:一个候选一张表', () => {
|
||||
const html = viewHtml('difference-review');
|
||||
it('候选块是嵌套行模版:外层 relation、里层明细按 substitution_relation_id 过滤;容器标签不在行模版里再出现', () => {
|
||||
expect(html).toContain('<article class="cands" data-rows="mine:substitution.relation"><section class="cand">');
|
||||
expect(html).toContain('data-rows="mine:substitution.difference_item" data-by="substitution_relation_id"');
|
||||
const inner = html.slice(html.indexOf('<section class="cand">'), html.indexOf('</section></article>'));
|
||||
expect(inner).not.toContain('<article');
|
||||
expect(inner).toContain('class="cand-idx"');
|
||||
expect(inner).toContain('data-slot="original_internal_pn"');
|
||||
});
|
||||
it('汇总表一个候选一条:推荐程度 / 风险级别按值上色,差异统计绑 difference_summary,品牌按料号从 parts.profile 挑', () => {
|
||||
expect(html).toContain('<tbody data-rows="mine:substitution.relation"><tr>');
|
||||
expect(html).toContain('<span class="rec" data-class-of="recommendation_level"></span>');
|
||||
expect(html).toContain('class="stat" data-slot="difference_summary"');
|
||||
expect(html).toContain('data-rows="parts.profile" data-by="internal_pn=candidate_internal_pn"');
|
||||
expect(html).toContain('data-slot="substitution_relation_rows"');
|
||||
expect(html).not.toContain('【AI 产出的差异明细】');
|
||||
});
|
||||
});
|
||||
|
||||
/* 评估输入清单的件上摆「候选参数现值」:一颗料一张、里层按料号过滤、只读(没有 data-edit) */
|
||||
describe('eval-input-list:候选参数现值只读参考', () => {
|
||||
it('外层按核对表逐颗复制,里层 parts.parameter 按 internal_pn 过滤,不是可编辑表', () => {
|
||||
const html = viewHtml('eval-input-list');
|
||||
expect(html).toContain(`<article class="prefs" data-rows="mine:${D}.pn_check"><section class="pref">`);
|
||||
expect(html).toContain('<tbody data-rows="parts.parameter" data-by="internal_pn"><tr>');
|
||||
const block = html.slice(html.indexOf('<article class="prefs"'), html.indexOf('</section></article>'));
|
||||
expect(block).not.toContain('data-edit=');
|
||||
expect(block).toContain('data-slot="param_value"');
|
||||
expect(html).toContain('【候选参数现值】');
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* 运营中心沙箱看板(2026-08-27 用户定:替换全流程分支图,只摆最近一次已放行实例的关键台账落账快照)。
|
||||
* 模版归活动,「哪几行是这一单的」也归活动 —— `data` 声明:案号怎么铸、哪张表按哪一列圈;基座只照它查正式表。
|
||||
*/
|
||||
describe('activity-ledger:关键台账数据看板', () => {
|
||||
const board = manifest.assets.viewTemplates.find((v) => v.name === BOARD_VIEW);
|
||||
const html = board?.html ?? '';
|
||||
const data = board?.data;
|
||||
const declaredAddresses = new Set(manifest.declarations.ledger.map((l) => `${l.domain}.${l.object}`));
|
||||
|
||||
it('取数声明:案号台账是 record 且 key 是它的 caseKey、前缀 W05-;每条 rows 的表都已声明;from 只指 case 或前面的 as.列', () => {
|
||||
expect(data).toBeDefined();
|
||||
if (data === undefined) return;
|
||||
const caseLedger = manifest.declarations.ledger.find((l) => `${l.domain}.${l.object}` === data.case.ledger);
|
||||
expect(caseLedger?.kind).toBe('record');
|
||||
expect(caseLedger?.caseKey).toBe(data.case.key);
|
||||
expect(data.case.prefix).toBe('W05-');
|
||||
const seen = new Set<string>();
|
||||
for (const entry of data.rows) {
|
||||
expect(declaredAddresses.has(entry.ledger), entry.ledger).toBe(true);
|
||||
const columns = new Set(manifest.declarations.ledger.find((l) => `${l.domain}.${l.object}` === entry.ledger)?.fields.map((f) => f.name));
|
||||
expect(columns.has(entry.by.column), `${entry.as} by ${entry.by.column}`).toBe(true);
|
||||
for (const ref of [entry.by.from, entry.not?.from]) {
|
||||
if (ref === undefined || ref === 'case') continue;
|
||||
const at = ref.lastIndexOf('.');
|
||||
const as = ref.slice(0, at);
|
||||
const column = ref.slice(at + 1);
|
||||
expect(seen.has(as), `${entry.as} 引用了后面 / 不存在的集合 ${as}`).toBe(true);
|
||||
const source = data.rows.find((r) => r.as === as);
|
||||
const sourceColumns = new Set(manifest.declarations.ledger.find((l) => `${l.domain}.${l.object}` === source?.ledger)?.fields.map((f) => f.name));
|
||||
expect(sourceColumns.has(column), `${ref} 不是 ${source?.ledger} 的列`).toBe(true);
|
||||
}
|
||||
seen.add(entry.as);
|
||||
}
|
||||
// 六张主表 + 案号两张 + 同料号历史都圈了
|
||||
expect([...seen]).toEqual(
|
||||
expect.arrayContaining([`${D}.verdict`, `${D}.pn_check`, 'demand.request', 'customer.profile', 'parts.profile', 'parts.parameter', 'parts.document', 'substitution.relation', 'substitution.difference_item', 'validation.record', 'validation.history']),
|
||||
);
|
||||
});
|
||||
|
||||
it('html 里每个 data-rows 键都是声明里的一个 as(行由基座圈过,不是整表);嵌套只用 data-by 父键过滤', () => {
|
||||
const as = new Set(data?.rows.map((r) => r.as) ?? []);
|
||||
const keys = [...html.matchAll(/data-rows="([^"]+)"/g)].map((m) => m[1] ?? '');
|
||||
expect(keys.length).toBeGreaterThan(8);
|
||||
for (const key of keys) expect(as.has(key), key).toBe(true);
|
||||
expect(html).toContain('<span class="pnrow" data-rows="sub_eval.pn_check" data-by="internal_pn">');
|
||||
expect(html).toContain('<div class="pchips" data-rows="parts.parameter" data-by="internal_pn">');
|
||||
expect(html).toContain('<tbody class="hist" data-rows="validation.history">');
|
||||
expect(html).not.toContain('mine:');
|
||||
});
|
||||
|
||||
it('无脚本、无 on*、无外链(过安装静态审);有 </body> 给出口注入报高脚本;三态由 board:state 投影;只读', () => {
|
||||
expect(html.length).toBeGreaterThan(5000);
|
||||
expect(html).not.toMatch(/<\s*script\b/i);
|
||||
expect(html).not.toMatch(/\son[a-z]+\s*=/i);
|
||||
expect(html).not.toMatch(/(src|href)\s*=\s*["']?\s*(https?:)?\/\//i);
|
||||
expect(html.toLowerCase()).toContain('</body>');
|
||||
expect(html).toContain('<div class="page" data-class-of="board:state">');
|
||||
expect(html).toContain('.page.v-none .notice.none{display:flex}');
|
||||
expect(html).toContain('.page.v-missing .notice.missing{display:flex}');
|
||||
expect(html).not.toContain('data-edit=');
|
||||
expect(html).not.toContain('data-col=');
|
||||
});
|
||||
|
||||
it('目标件六张表的表头与页头要素都在;MATCH 行淡显、放弃的候选只在有 abandoned 时露面 —— 都是 class 交样式表,模版不判', () => {
|
||||
for (const header of ['<th>内部料号</th>', '<th>替代关系 ID</th>', '<th>参数项</th>', '<th>关联料号</th>', '<th>验证 ID</th>', '<th>标准化参数集</th>']) expect(html).toContain(header);
|
||||
expect(html).toContain('data-slot="case:instanceNo"');
|
||||
expect(html).toContain('data-slot="case:ref"');
|
||||
expect(html).toContain(`data-slot="${D}.verdict.original_internal_pn"`);
|
||||
expect(html).toContain('data-slot="demand.request.request_id"');
|
||||
expect(html).toContain('<tr data-class-of="difference_status">');
|
||||
expect(html).toContain('tr.v-match td{opacity:.55}');
|
||||
expect(html).toContain('.aband:has(i.v-abandoned){display:block}');
|
||||
expect(html).toContain('data-slot="substitution_difference_item_difference_status_unknown"');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -174,6 +174,45 @@ describe('说明书与剧本的骨架', () => {
|
||||
expect(secondPass).toMatch(/收不了步|收不掉/);
|
||||
});
|
||||
|
||||
/*
|
||||
* 数据工单确认即入库(2026-08-27 用户定:「数据工单里填的数据,确认后就应该入库」)。
|
||||
* 基座在确认那一刻把卡上 gateLedgers 那几张表并进正式表;剧本这一头不能再教模型「已经落草稿层」——
|
||||
* 那句话会让它以为放行前还能改、还能 drop,而在库的键写下来会被当场拒。
|
||||
*/
|
||||
it('两张数据工单的剧本都写明:确认后已入正式表,别再写、别 drop 那几行;P-10 的卡骨架也说「确认后即入库」', () => {
|
||||
for (const item of ['S0d_p08_master', 'S0d_p10_document']) {
|
||||
const guide = ASSESSMENT_STEPS.find((s) => s.item === item)?.guide ?? '';
|
||||
expect(guide, item).toContain('入了正式表');
|
||||
expect(guide, item).not.toContain('已经落草稿层');
|
||||
expect(guide, item).toContain('别去 drop');
|
||||
}
|
||||
expect(NARRATIVE).toContain('确认后这批主数据即入库');
|
||||
expect(NARRATIVE).toContain('确认后这批资料记录即入库');
|
||||
});
|
||||
|
||||
/*
|
||||
* S1 的「待确认」行只许来自真写着「未披露」的参数(2026-08-27 用户:「我在第一步已经补充了
|
||||
* XL2596S-5.0 使能阈值,当前这一步还要填写一次?」)—— 剧本从前给了一句原话示例
|
||||
* 「input_item 如『XL2596S-5.0 使能阈值』」,模型照抄示例、不读现值,把人刚填的 2.5 摆成缺口。
|
||||
* 提示词里唯一该出现的原话,是你想听到的那句;示例行一律不引具体料号 + 参数名。
|
||||
*/
|
||||
/*
|
||||
* 第三次同一病(2026-08-27):措辞改了两遍照样复现 —— 台账里每个参数都有值,模型还是写了一行
|
||||
* 「使能阈值 · 原厂未披露」。参数值有没有是台账里的事实,不该由模型在清单里宣布:
|
||||
* S1 从此**一行参数都不写**,件上摆一张基座现读的「候选参数现值」表;说明书全文不再出现「使能阈值」。
|
||||
*/
|
||||
it('S1 不写参数行(item_key 不许以 unknown_ 开头);说明书全文没有「使能阈值」这个可照抄的名字', () => {
|
||||
const s1 = ASSESSMENT_STEPS.find((s) => s.item === 'S1_input_confirm')?.guide ?? '';
|
||||
expect(s1).toContain('候选参数一行都不写');
|
||||
expect(s1).toContain('不许以 unknown_ 开头');
|
||||
expect(s1).not.toContain('待确认');
|
||||
expect(NARRATIVE).not.toContain('使能阈值');
|
||||
for (const step of ASSESSMENT_STEPS) expect(step.guide, step.item).not.toContain('使能阈值');
|
||||
const skeleton = NARRATIVE.slice(NARRATIVE.indexOf('⑤ 执行工单 01'), NARRATIVE.indexOf('"standard":"每一条「待补」行'));
|
||||
expect(skeleton).toContain('候选参数现值');
|
||||
expect(skeleton).not.toContain('待确认');
|
||||
});
|
||||
|
||||
it('S0 剧本写明都在库时数据工单两项本就不会进「当下可为」;S0d_p08_master 剧本写明 found 的一颗都不建', () => {
|
||||
const s0 = ASSESSMENT_STEPS.find((s) => s.item === 'S0_bind')?.guide ?? '';
|
||||
expect(s0).toContain('当下可为');
|
||||
@@ -206,23 +245,47 @@ describe('说明书与剧本的骨架', () => {
|
||||
for (const step of ASSESSMENT_STEPS) expect(step.guide, step.item).not.toMatch(disableCallPattern);
|
||||
});
|
||||
|
||||
it('S0d 拆成两项各自绑自己的 view(P-10 那份件不会永远推不出来),两项都没有 doneWhen', () => {
|
||||
it('S0d 拆成两项各自绑自己的 view(P-10 那份件不会永远推不出来)', () => {
|
||||
const p08 = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p08_master');
|
||||
const p10 = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p10_document');
|
||||
expect(p08?.view).toBe('p08-master-create');
|
||||
expect(p10?.view).toBe('p10-document-create');
|
||||
expect(p08?.doneWhen).toBeUndefined();
|
||||
expect(p10?.doneWhen).toBeUndefined();
|
||||
});
|
||||
|
||||
it('P-08 交回之后先 finish 再发 P-10 卡,顺序写死进两段 guide(2026-08-27 实测:漏收步会让工作区画面停在 P-08 那两张表,P-10 卡发出后人却看不见资料表、提交闸拦死)', () => {
|
||||
/*
|
||||
* **两张数据工单的 doneWhen 只读入库事实**(2026-08-27 晚):引擎只在人答过卡之后求它 —— 值是人在件上填的、
|
||||
* 引擎数得出来,不再靠模型记得 finish(剧本写了两处它照样忘,件停在 P-08)。
|
||||
*/
|
||||
it('P-08:要建的每颗料主数据与参数都落了、必填不缺 → 收得掉;少建一颗 / 还缺必填 / 参数行对不上账 → 收不掉', () => {
|
||||
const ok = { parts_profile_rows: 2, [`${D}_pn_check_exists_status_absent`]: 2, [`${D}_pn_check_exists_status_created`]: 0, parts_profile_missing: 0, parts_parameter_missing: 0, parts_parameter_rows: 14, parts_parameter_distinct_param_name: 7 };
|
||||
expect(safeEval(doneOf('S0d_p08_master'), ok)).toBe(true);
|
||||
// 模型把其中一颗改成 created 也一样算(absent + created 才是要建的料数)
|
||||
expect(safeEval(doneOf('S0d_p08_master'), { ...ok, [`${D}_pn_check_exists_status_absent`]: 1, [`${D}_pn_check_exists_status_created`]: 1 })).toBe(true);
|
||||
expect(safeEval(doneOf('S0d_p08_master'), { ...ok, parts_profile_rows: 1, parts_parameter_rows: 7 })).toBe(false);
|
||||
expect(safeEval(doneOf('S0d_p08_master'), { ...ok, parts_profile_missing: 1 })).toBe(false);
|
||||
expect(safeEval(doneOf('S0d_p08_master'), { ...ok, parts_parameter_rows: 13 })).toBe(false);
|
||||
});
|
||||
|
||||
it('P-10:建过的每颗料都有一行资料记录且必填不缺 → 收得掉;资料少一行 / 骨架还空着 → 收不掉', () => {
|
||||
const ok = { parts_document_rows: 2, parts_profile_rows: 2, parts_document_missing: 0 };
|
||||
expect(safeEval(doneOf('S0d_p10_document'), ok)).toBe(true);
|
||||
expect(safeEval(doneOf('S0d_p10_document'), { ...ok, parts_document_rows: 1 })).toBe(false);
|
||||
expect(safeEval(doneOf('S0d_p10_document'), { ...ok, parts_document_missing: 3 })).toBe(false);
|
||||
});
|
||||
|
||||
it('S1 的入场哨兵不再等模型写 created 旗:入库事实齐了门就开', () => {
|
||||
const cond = /<sentry id="s_pns_resolved">[\s\S]*?<condition>([\s\S]*?)<\/condition>/.exec(CMMN_XML)?.[1] ?? '';
|
||||
expect(cond).not.toContain('sub_eval_pn_check_exists_status_absent = 0');
|
||||
expect(cond).toContain('sub_eval_pn_check_exists_status_absent + sub_eval_pn_check_exists_status_created');
|
||||
});
|
||||
|
||||
it('P-08 交回之后的收步不再靠模型记得 finish:剧本写明引擎按入库事实自己收,finish 只是省一拍(2026-08-27 晚:「顺序写死」两处模型照样忘)', () => {
|
||||
const s0d = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p08_master')?.guide ?? '';
|
||||
expect(s0d).toContain('finish S0d_p08_master');
|
||||
expect(s0d).toMatch(/顺序不能反/);
|
||||
expect(s0d).toContain('p08-master-create');
|
||||
expect(s0d).toMatch(/引擎也会自己收/);
|
||||
expect(s0d).not.toMatch(/顺序不能反/);
|
||||
const s0d10 = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p10_document')?.guide ?? '';
|
||||
expect(s0d10).toContain('finish S0d_p08_master');
|
||||
expect(s0d10).toMatch(/若它还开着|先.*finish/);
|
||||
expect(s0d10).toMatch(/引擎按入库事实自己收/);
|
||||
});
|
||||
|
||||
it('「发卡前清单必须先有行」写在说明书里,不只在剧本里(2026-08-27 实测:模型把 P-10 收步与 S1 发卡压成一拍,那一拍 S1 剧本没摊开,卡发出去时 input_gap 一行都没有,人对着空表无从下手)', () => {
|
||||
@@ -270,7 +333,7 @@ describe('说明书与剧本的骨架', () => {
|
||||
expect(NARRATIVE).toContain('parts.document` 必须先有骨架行');
|
||||
expect(NARRATIVE).toMatch(/压拍/);
|
||||
// 标了几颗建好,主数据就得有几行 —— 逐颗对账(第一刀写成「≥1 行就算数」太松,三候选那单从缝里过去了)
|
||||
expect(CMMN_XML).toContain('parts_profile_rows >= sub_eval_pn_check_exists_status_created');
|
||||
expect(CMMN_XML).toContain('parts_profile_rows >= sub_eval_pn_check_exists_status_absent + sub_eval_pn_check_exists_status_created');
|
||||
});
|
||||
|
||||
it('评估输入那张卡的**前提**写在说明书的卡骨架上(2026-08-27 e2e:两颗缺库,模型只问只建了第一颗,CN 还 absent 就把 S1 的卡发了出去 —— 发卡的授权面是调人预算,绕得过哨兵)', () => {
|
||||
@@ -295,7 +358,7 @@ describe('说明书与剧本的骨架', () => {
|
||||
const g = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p08_master')?.guide ?? '';
|
||||
expect(g).toMatch(/参数名一律用中文/);
|
||||
// 措辞写过两遍都没拦住 → 上结构:把「同一套名字」变成基座算得出的数
|
||||
expect(CMMN_XML).toContain('parts_parameter_rows = parts_parameter_distinct_param_name * sub_eval_pn_check_exists_status_created');
|
||||
expect(CMMN_XML).toContain('parts_parameter_rows = parts_parameter_distinct_param_name * (sub_eval_pn_check_exists_status_absent + sub_eval_pn_check_exists_status_created)');
|
||||
expect(g).toContain('input_voltage_range');
|
||||
expect(g).toMatch(/不是同一行/);
|
||||
});
|
||||
@@ -316,6 +379,7 @@ describe('说明书与剧本的骨架', () => {
|
||||
it('件上三处样式毛病钉死(2026-08-27 用户:表显示不全不能右滑 / 编辑态内部料号只读字与输入框并排 / input 与 select 没对齐)', () => {
|
||||
const html = manifest.assets.viewTemplates.find((v) => v.name === 'p08-master-create')?.html ?? '';
|
||||
// 两种包装都要能横滑:验收件用目标件的 .tbl-wrap(它的验收版写着 overflow:hidden),2026-08-27 用户在结论审核页撞上
|
||||
// 运营侧的看板也在这条纪律里(它六张表都宽)
|
||||
for (const v of manifest.assets.viewTemplates) expect(v.html, v.name).toContain('.jc-tbl-wrap, .tbl-wrap { overflow-x: auto;');
|
||||
expect(html).toContain('#tbl1.on td > .jc-vcell:not(.ro) { display: none; }');
|
||||
expect(html).toContain('input.jc-cell, select.jc-cell { height: 32px;');
|
||||
@@ -347,3 +411,47 @@ describe('说明书与剧本的骨架', () => {
|
||||
expect([...all].sort()).toEqual([...ITEM_IDS.filter((i) => i !== 'T_release')].sort());
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* 人工验收清单(2026-08-27 用户定):验收卡上的条目是人核这份工单要走的步骤,不是系统判的判据;
|
||||
* 每份验收工单固定 —— 差异评估结论审核(S4_review 审核卡)与评审放行与落账确认(T_release 终局验收卡)各一份。
|
||||
*/
|
||||
describe('两张验收工单的人工验收清单', () => {
|
||||
it('S4_review 与 T_release 各声明一份固定清单:至少 4 条,每条是一句可核对的动作,互不重复', () => {
|
||||
for (const item of ['S4_review', 'T_release']) {
|
||||
const list = ASSESSMENT_STEPS.find((s) => s.item === item)?.acceptanceChecklist ?? [];
|
||||
expect(list.length, item).toBeGreaterThanOrEqual(4);
|
||||
expect(new Set(list).size, item).toBe(list.length);
|
||||
for (const line of list) expect(line.length, `${item}: ${line}`).toBeGreaterThan(12);
|
||||
}
|
||||
// 别的步骤不发验收卡,不该有清单
|
||||
for (const step of ASSESSMENT_STEPS) {
|
||||
if (step.item === 'S4_review' || step.item === 'T_release') continue;
|
||||
expect(step.acceptanceChecklist, step.item).toBeUndefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* 评估输入清单每行六列都要写(2026-08-27 实测:模型 11 行全漏了必填列 input_item,件上红带点名「缺输入项」,
|
||||
* 人把别的格填满也过不了闸;而剧本从前只在括号里提过一次 input_item,逐行的做法里没再说)。
|
||||
*/
|
||||
describe('S1 清单:每行六列都要写', () => {
|
||||
it('剧本逐行写明 input_item 的人读名与 source_ledger,并让模型发卡前核 _missing = 0', () => {
|
||||
const s1 = ASSESSMENT_STEPS.find((s) => s.item === 'S1_input_confirm')?.guide ?? '';
|
||||
expect(s1).toContain('每一行六列都要写');
|
||||
for (const name of ['customer「客户」', 'request「客户需求」', 'original_pn「原 PN」', 'application_scenario「应用场景」', 'bom_position「BOM 位」', 'original_doc_version「原 PN 资料版本」']) {
|
||||
expect(s1, name).toContain(name);
|
||||
}
|
||||
expect(s1).toContain(`${D}_input_gap_missing`);
|
||||
});
|
||||
});
|
||||
|
||||
/* 放行那一步只 submit,不发工单(2026-08-27 实测:先一张执行单「评审放行与落账确认」,人答完才 submit 又一张验收单) */
|
||||
describe('T_release 只 submit', () => {
|
||||
it('剧本写明不发执行工单 / 决策卡', () => {
|
||||
const t = ASSESSMENT_STEPS.find((s) => s.item === 'T_release')?.guide ?? '';
|
||||
expect(t).toContain('不发执行工单');
|
||||
expect(t).toContain('submit');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -94,7 +94,12 @@ export const CMMN_XML = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
却只建了第一颗,一行足以让门开着,直到 S2 写关系时才被引用检查拦下。
|
||||
改成**逐颗对账**:\`parts_profile_rows >= created\` —— 标了几颗建好,就得有几行。
|
||||
-->
|
||||
<ifPart id="if_pr"><condition>sub_eval_pn_check_rows = count(candidateInternalPns) + 1 and sub_eval_pn_check_missing = 0 and sub_eval_pn_check_exists_status_absent = 0 and sub_eval_pn_check_exists_status_abandoned < count(candidateInternalPns) and parts_profile_missing = 0 and parts_parameter_missing = 0 and parts_document_missing = 0 and parts_profile_rows >= sub_eval_pn_check_exists_status_created and parts_document_rows >= sub_eval_pn_check_exists_status_created and parts_parameter_rows = parts_parameter_distinct_param_name * sub_eval_pn_check_exists_status_created</condition></ifPart>
|
||||
<!--
|
||||
**不再等模型把 absent 改成 created**(2026-08-27 晚):那面旗是模型记的账,忘了记就永远开不了门
|
||||
(「机检只读基座数」的哨兵形)。「一颗 absent 都不剩」的基座事实 = 要建的每一颗(absent + created)
|
||||
主数据、参数、资料都落了且必填不缺;created 仍可写(说明书照旧让它记),但门不靠它。
|
||||
-->
|
||||
<ifPart id="if_pr"><condition>sub_eval_pn_check_rows = count(candidateInternalPns) + 1 and sub_eval_pn_check_missing = 0 and sub_eval_pn_check_exists_status_abandoned < count(candidateInternalPns) and parts_profile_missing = 0 and parts_parameter_missing = 0 and parts_document_missing = 0 and parts_profile_rows >= sub_eval_pn_check_exists_status_absent + sub_eval_pn_check_exists_status_created and parts_document_rows >= sub_eval_pn_check_exists_status_absent + sub_eval_pn_check_exists_status_created and parts_parameter_rows = parts_parameter_distinct_param_name * (sub_eval_pn_check_exists_status_absent + sub_eval_pn_check_exists_status_created)</condition></ifPart>
|
||||
</sentry>
|
||||
<!-- ③ 评估输入已确认(旗 + 清单有行且必填齐)—— 标准化那一步的入场前提 -->
|
||||
<sentry id="s_input_confirmed">
|
||||
@@ -130,13 +135,13 @@ export const CMMN_XML = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 启动期:铸案号、建需求 V1、锁规则版本、逐个料号查库(能算的不问人) -->
|
||||
<humanTask id="S0_bind" name="建立评估上下文:绑定四项、新建需求、存在性核对"/>
|
||||
|
||||
<!-- 0.5a 等待数据(建主数据):P-08 数据工单;触达人,不给 doneWhen;都在库时 s_bound 不开,不进「当下可为」 -->
|
||||
<!-- 0.5a 等待数据(建主数据):P-08 数据工单;人工激活,doneWhen 只在人答过卡之后求(入库事实);都在库时 s_bound 不开,不进「当下可为」 -->
|
||||
<humanTask id="S0d_p08_master" name="数据工单:补建芯片主数据(P-08)">
|
||||
<entryCriterion id="ec_s0d8" sentryRef="s_bound"/>
|
||||
<itemControl><manualActivationRule id="m_s0d8"/></itemControl>
|
||||
</humanTask>
|
||||
|
||||
<!-- 0.5b 等待数据(建资料):P-10 数据工单;触达人,不给 doneWhen;都在库时 s_p08_created 不开,不进「当下可为」 -->
|
||||
<!-- 0.5b 等待数据(建资料):P-10 数据工单;人工激活,doneWhen 只在人答过卡之后求(入库事实);都在库时 s_p08_created 不开,不进「当下可为」 -->
|
||||
<humanTask id="S0d_p10_document" name="数据工单:补建原厂技术资料(P-10)">
|
||||
<entryCriterion id="ec_s0d10" sentryRef="s_p08_created"/>
|
||||
<itemControl><manualActivationRule id="m_s0d10"/></itemControl>
|
||||
@@ -256,7 +261,7 @@ key 是 {internal_pn, doc_seq:"01"});一行都没有的话人打开是空表、
|
||||
"ask":"请把这些料号的 datasheet / 承诺函等资料记录补进原厂技术资料库(一份资料一行,可加行)。",
|
||||
"steps":["资料类型、标题、版本、文件链接、资料状态为必填;证据定位写页码或章节,差异评估的证据引用会指向它",
|
||||
"同一料号多份资料就多加几行,序号 01/02… 自己续",
|
||||
"改完保存,回这张卡确认"],
|
||||
"改完保存,回这张卡确认 —— 确认后这批资料记录即入库,活动接着往下办"],
|
||||
"standard":"每颗料号至少一行 datasheet 记录,必填列全齐。",
|
||||
"gateLedgers":["parts.document"],
|
||||
"basis":[{"k":"触发原因","v":"按 internal_pn 查 P-10 查无记录"}]}}
|
||||
@@ -275,15 +280,15 @@ key 是 {internal_pn, doc_seq:"01"});一行都没有的话人打开是空表、
|
||||
{"kind":"human","itemId":"S1_input_confirm","workOrder":"execution","card":{
|
||||
"gateLedgers":["${D}.input_gap"],
|
||||
"title":"评估输入与资料补齐确认:<原 PN> → <N> 个候选",
|
||||
"ask":"启动绑定的四项已锁定。请在工作区的件上补齐「待补 / 待确认」行的补充内容,默认值可改可确认。",
|
||||
"ask":"启动绑定的四项已锁定。请在工作区的件上补齐「待补」行的补充内容,默认值可改可确认。",
|
||||
"steps":["应用场景、BOM 位是启动时未收的:必须补(写在「补充内容」列)",
|
||||
"原厂未披露的参数(如使能阈值)补不到就写「挂验证任务」或「留 UNKNOWN」—— 补不了也是合法答案,不拦流程",
|
||||
"每颗料每个参数此刻的值摆在件上的「候选参数现值」表里(只读参考);原厂未披露的参数这里不用补 —— 差异评估会把它判成 UNKNOWN 并挂验证任务",
|
||||
"替代类型 / 规则版本 / 负责人期限三行是系统默认,可改可不改",
|
||||
"加一行 = 补充 AI 没列出的资料项;删一行 = 该项不适用;已绑定的四项不可改",
|
||||
"改完保存,回这张卡提交"],
|
||||
"standard":"每一条「待补」行的补充内容都有;补不了的写明理由。",
|
||||
"basis":[{"k":"已绑定","v":"客户 <customerCode> · 需求 <request_id> V1 · 原 PN <原 PN> · 候选 <N> 颗"},
|
||||
{"k":"缺口","v":"<N> 项待补 / 待确认"}]}}
|
||||
{"k":"缺口","v":"<N> 项待补"}]}}
|
||||
|
||||
⑥ 验收工单 01 · 差异评估结论审核(S4_review;决策卡循环,不是终局验收)—— 发之前先在轨迹里找有没有已答过、还没处理的 \`[card-reply]\`:
|
||||
· \`value\` 是 \`"approve"\` → 写 \`${D}.verdict.review_approved_total = 1\`,finish 这一项,别再发卡;
|
||||
@@ -364,7 +369,13 @@ current_stage = "assessing"。application_scenario / bom_position **这一步不
|
||||
reads: [`${D}.pn_check`, 'candidateInternalPns', 'originalInternalPn', 'datasheets', 'parts.profile', 'parts.parameter', 'parts.document'],
|
||||
view: 'p08-master-create',
|
||||
tools: [],
|
||||
/* 触达人,不给 doneWhen;人工激活:发卡就算启动 */
|
||||
/*
|
||||
* 人工激活:发卡就算启动。doneWhen 只在**人答过卡之后**才由引擎求(2026-08-27 晚,harness 立此规矩):
|
||||
* 要建的每一颗(absent + created)主数据与参数都落了、必填不缺 —— 值是人在件上填的,引擎数得出来,
|
||||
* 不再靠模型记得 finish(剧本写了两处它照样忘,两步同时 Active、件停在 P-08)。名单里还有没建的料时它为假,
|
||||
* 「再发一张 P-08」那条路照旧走得通。
|
||||
*/
|
||||
doneWhen: `parts_profile_rows > 0 and parts_profile_rows >= ${D}_pn_check_exists_status_absent + ${D}_pn_check_exists_status_created and parts_profile_missing = 0 and parts_parameter_missing = 0 and parts_parameter_rows = parts_parameter_distinct_param_name * parts_profile_rows`,
|
||||
guide: `这一项只在 \`${D}.pn_check\` 里有 absent 行时走 —— 都在库时入场前提本就不成立,这一项与下一项 S0d_p10_document 都不会进你的「当下可为」。**先分岔,再动作**:
|
||||
|
||||
【名单】= \`${D}.pn_check\` 里 **exists_status = "absent" 的每一行**,不管它是原 PN 还是候选 —— **一律建,不问人**
|
||||
@@ -381,13 +392,13 @@ current_stage = "assessing"。application_scenario / bom_position **这一步不
|
||||
没有 datasheet 就只写 internal_pn 这一列(其余留给人填,**别编**)。
|
||||
2. 同一拍给每颗料写标准化参数集骨架(表 2,\`parts.parameter\`,一行一参数):
|
||||
**参数名一律用中文,与库里既有料号的那几行同名**(输入电压范围 / 输出电压 / 输出电流 / 开关频率 /
|
||||
静态电流 / 工作温度 / 使能阈值…)—— \`param_name\` 是主键的一半,写成 \`input_voltage_range\`
|
||||
静态电流 / 工作温度…)—— \`param_name\` 是主键的一半,写成 \`input_voltage_range\`
|
||||
与写成「输入电压范围」**不是同一行**:原 PN 那边是中文、候选这边是英文,比对时两套名字对不上,
|
||||
逐条判成 UNKNOWN,结论就废了(2026-08-27 实测:27 条里 14 条 UNKNOWN)。
|
||||
封装、工艺、生命周期这些**不是参数**,它们在表 1,别往表 2 里塞。
|
||||
**建几颗料就用同一套名字**:门上有一条对账 —— 参数行数 = 不同参数名数 × 建过的料数,
|
||||
只有每颗料的名字集合一模一样时才成立;混着写(这颗中文那颗英文、或同一颗写两套)这一步就过不去。有 \`datasheets[].text\` 就从里面读出典型参数
|
||||
(如输入电压范围 / 输出电压 / 输出电流 / 开关频率 / 静态电流 / 工作温度 / 使能阈值等,按品类而定)各写一行,
|
||||
(如输入电压范围 / 输出电压 / 输出电流 / 开关频率 / 静态电流 / 工作温度等,按品类而定)各写一行,
|
||||
key {internal_pn, param_name},patch 带 param_value / param_unit / constraint_type(hard/soft)/ param_note(一句话说清这项为什么要卡,
|
||||
如「须覆盖客户输入上限」);原厂没写的值写「未披露」(它会进入 UNKNOWN 并挂验证任务)。没有 datasheet 就只写
|
||||
internal_pn + param_name 骨架(把你判断这颗料该评估的参数名列出来,**param_value 留空给人填,别编**)。
|
||||
@@ -410,14 +421,13 @@ current_stage = "assessing"。application_scenario / bom_position **这一步不
|
||||
而那颗料从此没人建,后面写替代关系时被引用检查逐颗拦下(2026-08-27 实测,一单连拒四次)。
|
||||
· **一颗都不剩了** → 才走下面这两步。
|
||||
|
||||
这一拍的动作串**恰好两个,顺序不能反**:
|
||||
① 先 \`finish S0d_p08_master\` —— **必须先把这一项收掉**。不收掉,引擎挑工作区画面时按
|
||||
「当下还没干完的第一步」取 view,S0d_p08_master 只要还 Active,画面就一直停在
|
||||
\`p08-master-create\`(P-08 那两张表);下一拍就算发出了 P-10 的卡,人的工作区也看不见
|
||||
P-10 的资料表,一格都填不了,提交闸必然拦死。
|
||||
② 再照说明书④发 P-10 数据工单 —— 下一项是 S0d_p10_document,同一批料号接着补资料记录。
|
||||
这一拍的动作串:① \`finish S0d_p08_master\`(建好的料主数据与参数都已入库、必填不缺时引擎也会自己收这一项 ——
|
||||
你 finish 一下更省一拍,忘了也不会卡住);② 照说明书④发 P-10 数据工单 —— 下一项是 S0d_p10_document,同一批料号接着补资料记录。
|
||||
|
||||
【这张卡一单只发一次】人交回来之后不许再发;答复里没有值(空 values)也算答过 —— 人在件上填的东西已经落草稿层。`,
|
||||
【这张卡一单只发一次】人交回来之后不许再发;答复里没有值(空 values)也算答过 —— 人在件上填的东西已随确认**入了正式表**
|
||||
(轨迹里有一条「数据工单确认入库」的痕点名哪几张表各几行;试跑单不落主数据时那条痕会如实写「只留在活动缓存」)。
|
||||
这几颗料从此在库:**别再往 \`parts.profile\` / \`parts.parameter\` 写它们的键**(在库的键会被当场拒),也别去 drop 它们
|
||||
(那是本单自己建好的行,撤不掉);值要改由人在件上改。`,
|
||||
},
|
||||
{
|
||||
item: 'S0d_p10_document',
|
||||
@@ -428,19 +438,21 @@ P-10 的资料表,一格都填不了,提交闸必然拦死。
|
||||
reads: [`${D}.pn_check`, 'parts.profile', 'parts.document'],
|
||||
view: 'p10-document-create',
|
||||
tools: [],
|
||||
/* 触达人,不给 doneWhen;人工激活:发卡就算启动 */
|
||||
guide: `这一项只在 \`${D}.pn_check\` 里有 absent 行时走(要走到这一步,S0d_p08_master 必然已经收完);都在库时入场前提本就不成立,
|
||||
这一项与 S0d_p08_master 都不会进你的「当下可为」。**进到这一项时,S0d_p08_master 应当已经收掉了;若它还开着(Active),
|
||||
先 \`finish S0d_p08_master\` 再发这张卡** —— 它没收掉,画面会一直停在 P-08 那两张表,人拿到 P-10 的卡也看不见资料表。
|
||||
/* 人工激活:发卡就算启动。doneWhen 同 P-08 的道理:人答过卡之后,建过的每颗料都有一行资料记录且必填不缺 → 引擎自己收 */
|
||||
doneWhen: `parts_document_rows > 0 and parts_document_rows >= parts_profile_rows and parts_document_missing = 0`,
|
||||
guide: `这一项只在 \`${D}.pn_check\` 里有 absent 行时走(要走到这一步,S0d_p08_master 已经收完 —— 引擎按入库事实自己收);都在库时入场前提本就不成立,
|
||||
这一项与 S0d_p08_master 都不会进你的「当下可为」。
|
||||
|
||||
【发 P-10 数据工单】「建」的名单就是 \`${D}.pn_check\` 里仍是 exists_status = "absent" 的那几行(候选总数 ≥2 时被放弃的那些,
|
||||
S0d_p08_master 那一步已经把它们改成 "abandoned",不在这份名单里)。同一拍照说明书④发那张 P-10 数据工单(title 里列全料号,只发一次),
|
||||
发完这一拍结束(挂起)。
|
||||
|
||||
【P-10 那张确认回来了】把名单里每颗料的 \`${D}.pn_check\` 改成 exists_status = "created"(同 PK 覆盖写),然后 finish 这一项。
|
||||
这时 S1_input_confirm 的入场前提(全部料号落定、本单建的主数据不缺必填)自己就成立了 —— 缺必填由提交闸兜着,卡回来时一定是齐的。
|
||||
【P-10 那张确认回来了】把名单里每颗料的 \`${D}.pn_check\` 改成 exists_status = "created"(同 PK 覆盖写,记账用),然后 finish 这一项
|
||||
(资料记录都入库、必填不缺时引擎也会自己收)。S1_input_confirm 的入场前提认的是**入库事实**(要建的每颗料主数据 / 参数 / 资料都落了且不缺必填),
|
||||
不等这面旗 —— 缺必填由提交闸兜着,卡回来时一定是齐的。
|
||||
|
||||
【这张卡一单只发一次】人交回来之后不许再发;答复里没有值(空 values)也算答过 —— 人在件上填的东西已经落草稿层。`,
|
||||
【这张卡一单只发一次】人交回来之后不许再发;答复里没有值(空 values)也算答过 —— 人在件上填的东西已随确认**入了正式表**
|
||||
(轨迹里有一条「数据工单确认入库」的痕)。这几份资料记录从此在库:**别再往 \`parts.document\` 写它们的键**(会被当场拒),也别去 drop 它们。`,
|
||||
},
|
||||
{
|
||||
item: 'S1_input_confirm',
|
||||
@@ -453,14 +465,20 @@ S0d_p08_master 那一步已经把它们改成 "abandoned",不在这份名单里)
|
||||
guide: `料号全部落定了,**该 PW 补评估输入了** —— 这是本活动唯一的执行工单,零输入。**先分岔**:【当前这一步】那行引擎事实说
|
||||
「从没给它发过卡」→ 走【发卡】;说「人已经被问过了」→ 走【收口】。
|
||||
|
||||
【发卡】先把评估输入清单写下来(\`${D}.input_gap\`,一行一项,item_key 用英文短键,input_item 用人读名),一拍连做:
|
||||
· 已绑定四项(status = "ok",detail 写绑定值,origin = "ai"):item_key = customer / request / original_pn / candidates
|
||||
(候选多颗就 candidate_1、candidate_2… 一颗一行,detail 写料号与在库状态);
|
||||
【发卡】先把评估输入清单写下来(\`${D}.input_gap\`,一行一项),一拍连做。
|
||||
**每一行六列都要写,一列都不能少**:item_key(英文短键)/ input_item(人读名,就是下面每行「」里那几个字)/ source_ledger(来源台账)/
|
||||
status / detail / origin = "ai"。input_item 是必填列 —— 漏了它,件上红带会点名「缺输入项」,人对着一张没有名字的清单什么也补不了,
|
||||
卡就此交不回来(2026-08-27 实测:11 行全漏了 input_item,人把别的格填满也过不了闸)。
|
||||
· 已绑定四项(status = "ok",detail 写绑定值):item_key = customer「客户」(source_ledger = "L-02")/ request「客户需求」(source_ledger = "P-01")/
|
||||
original_pn「原 PN」(source_ledger = "P-08")/ 候选多颗就 candidate_1「候选 1」、candidate_2「候选 2」… 一颗一行(source_ledger = "P-08",detail 写料号与在库状态);
|
||||
· 待补两项(status = "gap",detail 写「启动时未收」):application_scenario「应用场景」(source_ledger = "P-01")、bom_position「BOM 位」(source_ledger = "P-09");
|
||||
· 默认可改三项(status = "default",detail 写默认值):substitution_type「替代类型」= "Pin-to-Pin"、rule_version「规则版本」= "${RULE_VERSION}"、owner「负责人 / 期限」= "按客户线默认 · 1 个工作日";
|
||||
· 待确认(status = "gap"):逐颗候选看它名下 \`parts.parameter\` 的那几行,param_value 是「未披露」的各一行(item_key = unknown_<料号>_<序号>,
|
||||
input_item 如「XL2596S-5.0 使能阈值」,source_ledger = "P-08",detail 写「原厂未披露(有而不全)」);
|
||||
· 齐备项(status = "ok"):原 PN 资料版本(source_ledger = "P-10",detail 写 datasheet 版本)。
|
||||
· 默认可改三项(status = "default",detail 写默认值,source_ledger = "GOV"):substitution_type「替代类型」= "Pin-to-Pin"、rule_version「规则版本」= "${RULE_VERSION}"、owner「负责人 / 期限」= "按客户线默认 · 1 个工作日";
|
||||
· **候选参数一行都不写**:原厂未披露的参数不是这份清单的事 —— 差异评估那一步(S3)会把它判成 UNKNOWN 并挂验证任务;
|
||||
件上另有一张只读的「候选参数现值」表(P-08 标准化参数集,一颗料一张,基座从台账现读),人看得见每颗料每个参数此刻的值。
|
||||
这份清单里**不许出现任何参数行**(item_key 不许以 unknown_ 开头)—— 参数值有没有,是台账里的事实,不由你在这里替它宣布
|
||||
(2026-08-27 实测三次:人在 P-08 填好的参数被这份清单当成缺口再问一遍);
|
||||
· 齐备项(status = "ok"):original_doc_version「原 PN 资料版本」(source_ledger = "P-10",detail 写 datasheet 版本)。
|
||||
发卡前自己核一遍:\`${D}_input_gap_missing\` 这个读数必须是 0(它只该等 supplement 那一列由人来填;不是 0 就是你漏写了必填列,回去补写再发)。
|
||||
写完同一拍照说明书⑤发执行工单,发完这一拍结束(挂起)。
|
||||
|
||||
【收口】人交回之后只做三件事,然后 finish:
|
||||
@@ -533,7 +551,7 @@ difference_status / compare_result / risk_level / impact_statement / unknown_dis
|
||||
这一步的收步判据里就有这两个数,**不调够,写多少行都收不了步**。
|
||||
① 逐条 \`substitution.difference_item\` 同 PK 覆盖写:difference_status / compare_result / risk_level 照第一拍出参**一字不改**;
|
||||
impact_statement(MATCH 写「无」;其余说清对应用 / 验证 / 报价的影响,如「输入上限 32V < 客户 40V,不能上板」);
|
||||
difference_status = unknown 的行**必须**写 unknown_disposition(「挂验证任务 VAL-<案号数字串>-01:实测使能阈值」或「向原厂补来源」);confidence(0~1)。
|
||||
difference_status = unknown 的行**必须**写 unknown_disposition(「挂验证任务 VAL-<案号数字串>-01:实测<参数名>」或「向原厂补来源」);confidence(0~1)。
|
||||
② 每个 UNKNOWN 写一行 \`validation.record\`:validation_id = "VAL-<案号数字串>-01/02…"、request_id、validation_internal_pn(候选)、
|
||||
validation_type = "pin_to_pin"、validation_status = "not_started"、next_validation_action(要测什么、什么条件)、test_condition。
|
||||
③ 逐条 \`substitution.relation\` 同 PK 覆盖写:recommendation_level / risk_level 照第二拍出参、recommendation_reason(工具 reason 扩写成人话,
|
||||
@@ -548,6 +566,13 @@ difference_status / compare_result / risk_level / impact_statement / unknown_dis
|
||||
item: 'S4_review',
|
||||
/* 中间审核摆成验收工单的样子(机制是可循环的决策卡);由剧本声明,模型抄不抄都一样 */
|
||||
cardVariant: 'review' as const,
|
||||
/* 人工验收清单(2026-08-27 用户定):FAE/RI 拿着「差异评估结论审核」这份件要亲自核的步骤,固定 */
|
||||
acceptanceChecklist: [
|
||||
'逐个候选核对结论汇总:推荐程度、风险级别与它下方明细表的四态分布吻合(有硬约束 MISMATCH 或悬空 UNKNOWN 的候选没有给「推荐」)',
|
||||
'逐条核对差异明细:每个候选的每个参数都有 MATCH / MISMATCH / UNKNOWN / CONDITIONAL 之一,没有漏项',
|
||||
'核对 UNKNOWN 项的去向:每个 UNKNOWN 都挂了验证任务或写明补来源动作,没有悬空',
|
||||
'核对证据引用:每项结论能追溯到 P-08 / P-10 / P-06 的记录或本单数据工单的创建记录;硬约束的 MATCH 都有证据支持',
|
||||
],
|
||||
intent: '差异评估结论审核:决策卡循环,通过或驳回 + AI 按意见改台账重发',
|
||||
writes: ['substitution.relation', 'substitution.difference_item', 'validation.record', `${D}.verdict`],
|
||||
reads: ['substitution.relation', 'substitution.difference_item', 'validation.record', `${D}.verdict`],
|
||||
@@ -588,13 +613,23 @@ difference_status / compare_result / risk_level / impact_statement / unknown_dis
|
||||
{
|
||||
item: 'T_release',
|
||||
intent: '拟落账内容已备好,提交 ACT-GATE-03 交 FAE/RI 放行;被打回就改台账再交',
|
||||
/* 人工验收清单(2026-08-27 用户定):FAE/RI 拿着「评审放行与落账确认」这份件要亲自核的步骤,固定 */
|
||||
acceptanceChecklist: [
|
||||
'核对拟写 P-11 的每条替代关系:推荐等级与差异明细一致(有 UNKNOWN / CONDITIONAL 的候选没有给「推荐」),推荐理由与差异摘要说得通',
|
||||
'核对分析状态:每条只写分析层(分析状态 = FAE 确认),客户批准状态保持「未提交」,不由本单产生',
|
||||
'核对规则版本:每条结论都带本次锁定的 GOV 差异规则版本(R-2026.07)',
|
||||
'核对拟回写 P-01 的五项:风险等级、验证要求、输出链接、下一步动作、当前阶段都填了,且与结论一致',
|
||||
'核对验证任务:每个 UNKNOWN 对应的验证记录都在,要测什么、什么条件写清楚了',
|
||||
],
|
||||
/* 被打回重做时要改的就是这几张 —— 不声明就写不进去 */
|
||||
writes: ['substitution.relation', 'substitution.difference_item', 'validation.record', 'demand.request', `${D}.verdict`],
|
||||
reads: ['substitution.relation', 'substitution.difference_item', 'validation.record', 'demand.request', `${D}.verdict`],
|
||||
view: 'landing-confirm',
|
||||
tools: [],
|
||||
/* 放行触达世界,必须人按一下 —— 引擎不自动收它 */
|
||||
guide: `落账确认那一屏摆着拟写 P-11 主记录与拟回写 P-01。**先看轨迹里有没有「验收被打回重做」**:
|
||||
guide: `落账确认那一屏摆着拟写 P-11 主记录与拟回写 P-01。**这一步不发执行工单、不发决策卡**:放行卡由 submit 发
|
||||
(基座预检后自己发验收卡),发执行工单等于把同一件事问人两遍(2026-08-27 实测:先一张执行单、人答完才 submit 又一张验收单)。
|
||||
**先看轨迹里有没有「验收被打回重做」**:
|
||||
有 → 这一拍不是再提交一遍。照意见改**台账本身**(同 PK 覆盖写,不开新行):
|
||||
· 他说推荐等级与明细不符 → 核对 \`substitution.relation.recommendation_level\` 与该关系明细的四态计数,不符的把 recommendation_reason 改实、把漏挂的验证要求补上;
|
||||
· 他说 P-01 回写不全 → 补 \`demand.request\` 那五项;
|
||||
|
||||
@@ -24,6 +24,7 @@ import { activityIdSchema } from '@contracts';
|
||||
import { ASSESSMENT_SKILLS } from './skills.ts';
|
||||
import { CMMN_XML, NARRATIVE, ASSESSMENT_PHASES, ASSESSMENT_STEPS } from './case-model.ts';
|
||||
import { P08_MASTER_CREATE, P10_DOCUMENT_CREATE, EVAL_INPUT_LIST, DIFFERENCE_REVIEW, LANDING_CONFIRM } from './views/report.ts';
|
||||
import { LEDGER_BOARD, LEDGER_BOARD_DATA } from './views/ledger-board.ts';
|
||||
import { ACTIVITY_ID_TEXT, D, TOOL_COMPARE, TOOL_RECOMMEND } from './constants.ts';
|
||||
|
||||
export { D, RULE_VERSION, TOOL_COMPARE, TOOL_RECOMMEND } from './constants.ts';
|
||||
@@ -89,7 +90,7 @@ export const manifest: ActivityManifest = {
|
||||
identity: {
|
||||
activityId: ACTIVITY_ID,
|
||||
name: 'ACT-WORK-05 · 差异评估',
|
||||
packageVersion: '1.4.7',
|
||||
packageVersion: '1.6.2',
|
||||
category: '需求分析与方案匹配',
|
||||
sdkVersion: '0.1.0-m5',
|
||||
checksum: 'dev-checksum-part-substitution-assessment',
|
||||
@@ -109,20 +110,57 @@ export const manifest: ActivityManifest = {
|
||||
data: {
|
||||
type: 'object',
|
||||
required: ['customerCode', 'requestDescription', 'originalInternalPn', 'candidateInternalPns'],
|
||||
/*
|
||||
* 运营端「启动活动」表单照这几个字段渲染(2026-08-27,`docs/API文档-活动模块.md` §4):
|
||||
* `x-control` 定控件(combo = 选择 + 新增,textarea = 多行),`x-options` 指候选从哪张正式台账现读,`x-order` 定表单次序
|
||||
* (清单存在 jsonb 里,书写顺序到不了运营端 —— PG 会按键长重排),
|
||||
* `description` 是控件下那句辅助说明。台账里没有的值**照样启动**,启动后由 S0 的存在性核对派数据工单。
|
||||
* datasheets 是文件,本期不上启动表单(在数据工单里传)。
|
||||
*/
|
||||
properties: {
|
||||
customerCode: { type: 'string', title: '客户编码(L-02 客户主台账)', examples: ['CU-0142'] },
|
||||
customerName: { type: 'string', title: '客户名称(仅客户不在库时填,启动后先建档)', examples: ['深圳恒星电源有限公司'] },
|
||||
customerCode: {
|
||||
type: 'string',
|
||||
title: '客户',
|
||||
description: '台账里有就直接选;是新客户就自己填客户编码,启动后派数据录入卡建档。',
|
||||
examples: ['CU-0142'],
|
||||
'x-control': 'combo',
|
||||
'x-options': { ledger: 'customer.profile', value: 'customer_code', label: 'name' },
|
||||
'x-order': 1,
|
||||
},
|
||||
customerName: {
|
||||
type: 'string',
|
||||
title: '客户名称(仅客户不在库时填)',
|
||||
description: '新客户先把名字摆上,启动后建档时让人核。',
|
||||
examples: ['深圳恒星电源有限公司'],
|
||||
'x-order': 2,
|
||||
},
|
||||
requestDescription: {
|
||||
type: 'string',
|
||||
title: '客户需求(原始描述 —— 据此新建 P-01 需求主记录 · 版本 V1)',
|
||||
title: '客户需求',
|
||||
description: '保留原始需求语义,据此新建 P-01 需求主记录(版本 V1)。',
|
||||
examples: ['工业电源项目在用 LM2596S-5.0(TI,12V→5V),原厂 PCN 转 NRND,客户要求验证替代料'],
|
||||
'x-control': 'textarea',
|
||||
'x-order': 3,
|
||||
},
|
||||
originalInternalPn: {
|
||||
type: 'string',
|
||||
title: '原内部料号',
|
||||
description: '差异评估基准;库里没有该 PN 也可启动,启动后派数据工单补参数。',
|
||||
examples: ['LM2596S-5.0'],
|
||||
'x-control': 'combo',
|
||||
'x-options': { ledger: 'parts.profile', value: 'internal_pn', label: 'internal_pn' },
|
||||
'x-order': 4,
|
||||
},
|
||||
originalInternalPn: { type: 'string', title: '原内部料号(P-08)', examples: ['LM2596S-5.0'] },
|
||||
candidateInternalPns: {
|
||||
type: 'array',
|
||||
title: '候选内部料号(数组,≥1;不在库的启动后经数据工单创建)',
|
||||
title: '候选内部料号',
|
||||
description: '被评估物料;库里有就直接选,没有就自己填料号,启动后经数据工单创建。',
|
||||
items: { type: 'string' },
|
||||
examples: [['XL2596S-5.0', 'LM2596S-ADJ']],
|
||||
/* 运营端启动表单只选一颗(2026-08-27 用户定):摆成与原料号同款的下拉;提交的单个料号由后端包成一元数组,活动契约不变 */
|
||||
'x-control': 'combo',
|
||||
'x-options': { ledger: 'parts.profile', value: 'internal_pn', label: 'internal_pn' },
|
||||
'x-order': 5,
|
||||
},
|
||||
datasheets: {
|
||||
type: 'array',
|
||||
@@ -257,7 +295,7 @@ export const manifest: ActivityManifest = {
|
||||
skills: ASSESSMENT_SKILLS.map((s) => s.id),
|
||||
models: ['deepseek-v4-flash'],
|
||||
roles: ['FAE/RI'],
|
||||
budget: { steps: 90, tokens: 600_000, activeMinutes: 120, humanCalls: 16 },
|
||||
budget: { steps: 90, tokens: 2_000_000, activeMinutes: 120, humanCalls: 16 },
|
||||
},
|
||||
},
|
||||
|
||||
@@ -561,6 +599,9 @@ col({ name: 'internal_pn', type: 'text', label: '内部料号', primaryKey: true
|
||||
{ name: 'eval-input-list', html: EVAL_INPUT_LIST },
|
||||
{ name: 'difference-review', html: DIFFERENCE_REVIEW },
|
||||
{ name: 'landing-confirm', html: LANDING_CONFIRM },
|
||||
/* 运营中心 L2 的沙箱视图(2026-08-27,用户定替换掉全流程分支图):关键台账数据看板 —— 最近一次已放行
|
||||
实例的落账快照,行由基座按 `data` 声明从正式表圈;无脚本,报高脚本由服务端出口注入 */
|
||||
{ name: 'activity-ledger', html: LEDGER_BOARD, data: LEDGER_BOARD_DATA },
|
||||
],
|
||||
cardSchemas: {},
|
||||
distillHooks: [{ on: 'terminal', prompt: '归纳本次差异评估:哪些候选、各自推荐等级与关键依据、UNKNOWN 挂了什么验证任务、审核是否被驳回过(为什么)、数据工单建了哪些主数据。' }],
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 徽标别名的生成器(与 `report.ts` 里那一段同一套逻辑;report.ts 另有一份 —— 并成一处记在 debt)。
|
||||
*
|
||||
* **2026-08-27 实测事故**:手写的 `.jc-tag.v-pin_to_pin::after{…}` 永远匹配不上,件上显示「待定」,
|
||||
* 而台账里 `substitution_type` 明明是 `pin_to_pin`。`data-class-of` 投影出的 class 走 `view-render.ts` 的
|
||||
* `classToken`(只留 `[a-z0-9-]`,**吃掉下划线**,封顶 24 字),所以选择器一律从 tally 值**算**出来。
|
||||
*/
|
||||
/** 必须与 `classToken` 一字不差:小写、只留 `[a-z0-9-]`、封顶 24 字。 */
|
||||
export const vtok = (v: string): string => v.toLowerCase().replace(/[^a-z0-9-]/g, '').slice(0, 24);
|
||||
/** `[值, 人读名, 可选颜色声明]`:值与文案成对写在一处 */
|
||||
export type BadgeSpec = readonly [value: string, label: string, color?: string];
|
||||
export const badgeCss = (selector: string, specs: readonly BadgeSpec[]): string =>
|
||||
specs
|
||||
.map(([v, label, color]) => {
|
||||
const cls = `${selector}.v-${vtok(v)}`;
|
||||
return color === undefined ? `${cls}::after { content: "${label}"; }` : `${cls}::after { content: "${label}"; }\n${cls} { ${color} }`;
|
||||
})
|
||||
.join('\n');
|
||||
@@ -0,0 +1,517 @@
|
||||
/**
|
||||
* 运营中心 L2 沙箱视图 —— ACT-WORK-05「关键台账数据」看板(2026-08-27)。
|
||||
*
|
||||
* 版式与样式逐字节搬自 `docs/ss02-act-05/ACT-WORK-05-关键台账数据.html`(只改两处:`.tbl-wrap` 放开横滑;
|
||||
* 徽标文案由 `data-class-of` 投影 + 生成式 `::after` 出,不再写死)。溯源口径照 `…-数据溯源.md`:
|
||||
* 页头 / P-01 一条 / P-08 逐颗 + 参数瓷贴(一格一列,不叠灰字次列 —— 2026-08-27 用户定)/ P-11 主记录 + 差异明细 / P-10(同样一格一列)/ P-06(本单 + 同料号历史)。
|
||||
*
|
||||
* **它摆的是最近一次已放行实例的落账快照**(用户定):行由基座按 `LEDGER_BOARD_DATA` 的声明从**正式表**圈出 ——
|
||||
* 每个 `data-rows` 键都是声明里的一个 `as`,不是整表;`<as>.<列>` 是那一集合首行的标量,`<as 去符号>_rows` /
|
||||
* `_<列>_<值>` 是基座数出来的读数(`apps/api/src/app/activity-ops/view-scope.ts`)。模版仍**不算不判**:
|
||||
* MATCH 行淡显、放弃的候选、三态横幅,全是 `data-class-of` 投出的 class 交样式表。
|
||||
* 无脚本、无外链(过安装静态审);报高脚本由服务端出口注入。
|
||||
*/
|
||||
import type { ViewData } from '@contracts';
|
||||
import { badgeCss } from './badge.ts';
|
||||
import { D } from '../constants.ts';
|
||||
|
||||
/** 案号 `W05-<开案时刻 14 位>`(与说明书让模型铸 `eval_ref` 的写法同源);行集按案号 → 核对表 → 料号 / 需求逐表圈 */
|
||||
export const LEDGER_BOARD_DATA: ViewData = {
|
||||
case: { ledger: `${D}.verdict`, key: 'eval_ref', prefix: 'W05-' },
|
||||
rows: [
|
||||
{ as: `${D}.verdict`, ledger: `${D}.verdict`, by: { column: 'eval_ref', from: 'case' } },
|
||||
/* 原 PN 排第一(original > candidate),下游按料号圈的表都随这个顺序 */
|
||||
{ as: `${D}.pn_check`, ledger: `${D}.pn_check`, by: { column: 'eval_ref', from: 'case' }, orderBy: [{ field: 'role', dir: 'desc' }, { field: 'internal_pn', dir: 'asc' }] },
|
||||
{ as: 'demand.request', ledger: 'demand.request', by: { column: 'request_id', from: `${D}.verdict.request_id` } },
|
||||
{ as: 'customer.profile', ledger: 'customer.profile', by: { column: 'customer_code', from: 'demand.request.customer_code' } },
|
||||
{ as: 'parts.profile', ledger: 'parts.profile', by: { column: 'internal_pn', from: `${D}.pn_check.internal_pn` } },
|
||||
{ as: 'parts.parameter', ledger: 'parts.parameter', by: { column: 'internal_pn', from: `${D}.pn_check.internal_pn` }, orderBy: [{ field: 'param_name', dir: 'asc' }] },
|
||||
{ as: 'parts.document', ledger: 'parts.document', by: { column: 'internal_pn', from: `${D}.pn_check.internal_pn` }, orderBy: [{ field: 'doc_seq', dir: 'asc' }] },
|
||||
{ as: 'substitution.relation', ledger: 'substitution.relation', by: { column: 'eval_ref', from: 'case' }, orderBy: [{ field: 'substitution_relation_id', dir: 'asc' }] },
|
||||
{
|
||||
as: 'substitution.difference_item',
|
||||
ledger: 'substitution.difference_item',
|
||||
by: { column: 'substitution_relation_id', from: 'substitution.relation.substitution_relation_id' },
|
||||
orderBy: [{ field: 'difference_item_id', dir: 'asc' }],
|
||||
},
|
||||
{ as: 'validation.record', ledger: 'validation.record', by: { column: 'request_id', from: `${D}.verdict.request_id` }, orderBy: [{ field: 'validation_id', dir: 'asc' }] },
|
||||
/* 同料号在别单 / 别处留下的验证记录:本次评估的历史证据引用(目标件 P-06 里 VAL-2026-0040 / 0032 那两行的位置) */
|
||||
{
|
||||
as: 'validation.history',
|
||||
ledger: 'validation.record',
|
||||
by: { column: 'validation_internal_pn', from: `${D}.pn_check.internal_pn` },
|
||||
not: { column: 'request_id', from: `${D}.verdict.request_id` },
|
||||
orderBy: [{ field: 'validation_id', dir: 'desc' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/* ==================== 目标件样式(逐字节搬;两处改动标了 [改]) ==================== */
|
||||
const TARGET_CSS = `
|
||||
:root{
|
||||
--ink:#1f2329; --ink-2:#41464e; --ink-3:#646a73; --ink-4:#8f959e;
|
||||
--line:#dee0e3; --line-soft:#e8eaed; --soft:#f8f9fb;
|
||||
--brand:#3370ff; --brand-deep:#245bdb; --brand-soft:#e1eaff; --brand-wash:#f0f4ff;
|
||||
--data:#3370ff; --data-soft:#e1eaff; --data-line:#c3d6ff;
|
||||
--human:#d97706; --human-soft:#fdf1dc; --human-line:#f0d8a8;
|
||||
--ledger:#16a34a; --ledger-soft:#e6f6ec; --ledger-line:#b7e5c6;
|
||||
--ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9;
|
||||
--amber:#8f6a12; --amber-soft:#fdf3d7; --amber-line:#ecd9a0;
|
||||
--mono:"SF Mono",Menlo,Consolas,monospace;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
html,body{margin:0;padding:0}
|
||||
body{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:#fff;color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
|
||||
.page{max-width:none;margin:0;padding:0}
|
||||
|
||||
/* 头部 */
|
||||
.mast{background:#fff;border:1px solid var(--line-soft);border-radius:14px;padding:22px 26px;position:relative;overflow:hidden}
|
||||
.mast::before{content:"";position:absolute;inset:0 0 auto 0;height:4px;background:linear-gradient(90deg,var(--brand) 0%,var(--brand-deep) 100%)}
|
||||
.mast .kick{font-size:11px;letter-spacing:.12em;color:var(--ink-4);font-weight:800}
|
||||
.mast h1{margin:4px 0 6px;font-size:23px;font-weight:800;line-height:1.3}
|
||||
.mast h1 .code{font-family:var(--mono);font-size:14px;font-weight:700;color:var(--brand-deep);background:var(--brand-wash);border:1px solid var(--brand-soft);border-radius:8px;padding:3px 10px;margin-right:10px;vertical-align:3px}
|
||||
.mast .sub{font-size:13px;color:var(--ink-3)}
|
||||
.mast .sub b{color:var(--ink-2)}
|
||||
|
||||
/* 数据来源图例 */
|
||||
.legend{display:flex;gap:10px;flex-wrap:wrap;margin:12px 0 0;font-size:12px;color:var(--ink-3)}
|
||||
.legend .li{display:inline-flex;align-items:center;gap:6px;background:#fff;border:1px solid var(--line-soft);border-radius:999px;padding:3px 12px}
|
||||
.dot{width:8px;height:8px;border-radius:50%;flex:none}
|
||||
.dot.full{background:var(--brand)}
|
||||
.dot.half{background:var(--amber)}
|
||||
|
||||
/* 分层图例 */
|
||||
.layers{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin:14px 0 18px}
|
||||
.layer{background:#fff;border:1px solid var(--line-soft);border-radius:11px;padding:11px 14px;font-size:12px;color:var(--ink-2);border-top:3px solid var(--brand)}
|
||||
.layer b{display:block;font-size:12.5px;color:var(--ink);margin-bottom:2px}
|
||||
.layer .lg{font-family:var(--mono);font-weight:800;color:var(--brand-deep)}
|
||||
.layer.core-out{border-top-color:var(--ledger)} .layer.core-out .lg{color:var(--ledger)}
|
||||
.layer.evid{border-top-color:var(--human)} .layer.evid .lg{color:var(--human)}
|
||||
.layer.loop{border-top-color:var(--amber)} .layer.loop .lg{color:var(--amber)}
|
||||
.layer.ctx{border-top-color:var(--ink-4)} .layer.ctx .lg{color:var(--ink-3)}
|
||||
|
||||
/* 区块 */
|
||||
section{background:#fff;border:1px solid var(--line-soft);border-radius:14px;padding:18px 22px;margin-bottom:16px}
|
||||
.sec-head{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap}
|
||||
.sec-head h2{margin:0;font-size:15.5px;font-weight:800}
|
||||
.sec-head h2 .lid{font-family:var(--mono);font-size:12px;color:var(--brand-deep);background:var(--brand-wash);border:1px solid var(--brand-soft);border-radius:6px;padding:1px 8px;margin-right:8px}
|
||||
.ltag{font-size:10.5px;font-weight:800;padding:2px 9px;border-radius:999px;border:1px solid transparent;white-space:nowrap}
|
||||
.ltag.in{color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft)}
|
||||
.ltag.out{color:var(--ledger);background:var(--ledger-soft);border-color:var(--ledger-line)}
|
||||
.ltag.evid{color:var(--human);background:var(--human-soft);border-color:var(--human-line)}
|
||||
.ltag.loop{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.ltag.ctx{color:var(--ink-3);background:var(--soft);border-color:var(--line)}
|
||||
.sec-head .why{font-size:12px;color:var(--ink-4)}
|
||||
.sec-head .cnt{margin-left:auto;font-size:11.5px;color:var(--ink-4);font-family:var(--mono)}
|
||||
|
||||
/* 表格 —— [改] 目标件写 overflow:hidden,列一多右边被裁且滑不动;本仓 2026-08-23 定:表宽超出就得能横滑 */
|
||||
.tbl-wrap{border:1px solid var(--line-soft);border-radius:10px;overflow-x:auto;overflow-y:hidden}
|
||||
.jc-tbl-wrap, .tbl-wrap { overflow-x: auto; overflow-y: hidden; }
|
||||
table{width:100%;border-collapse:collapse;font-size:12.5px}
|
||||
th{text-align:left;background:var(--soft);font-size:11px;letter-spacing:.05em;font-weight:800;color:var(--ink-3);padding:9px 12px;border-bottom:1px solid var(--line);white-space:nowrap}
|
||||
td{padding:9px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top}
|
||||
tr:last-child td{border-bottom:0}
|
||||
tbody tr{transition:background .15s}
|
||||
tbody tr:hover{background:var(--brand-wash)}
|
||||
.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
|
||||
.pn{font-weight:700}
|
||||
|
||||
/* 状态 pill */
|
||||
.st{display:inline-block;padding:1px 9px;border-radius:999px;font-size:11px;font-weight:800;white-space:nowrap;border:1px solid transparent}
|
||||
.st.ok{color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4}
|
||||
.st.miss{color:var(--danger);background:var(--danger-soft);border-color:#f3b9b5}
|
||||
.st.unknown{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.st.cond{color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft)}
|
||||
.st.gray{color:var(--ink-3);background:var(--soft);border-color:var(--line)}
|
||||
.st.warn{color:var(--human);background:var(--human-soft);border-color:var(--human-line)}
|
||||
|
||||
/* P-01 单记录 KV 卡 */
|
||||
.kv{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line-soft);border:1px solid var(--line-soft);border-radius:10px;overflow:hidden}
|
||||
.kv .cell{background:#fff;padding:10px 14px}
|
||||
.kv .k{font-size:11px;font-weight:800;color:var(--ink-4);margin-bottom:2px}
|
||||
.kv .v{font-size:12.5px;color:var(--ink);line-height:1.5}
|
||||
.kv .span2{grid-column:span 2}
|
||||
|
||||
/* 参数集摘要 chips */
|
||||
.pchips{display:flex;flex-wrap:wrap;gap:4px}
|
||||
.pchips span{font-size:11px;font-family:var(--mono);background:var(--soft);border:1px solid var(--line-soft);border-radius:6px;padding:1px 7px;color:var(--ink-2);white-space:nowrap}
|
||||
|
||||
/* 次要台账条 */
|
||||
.minor{display:flex;gap:10px;flex-wrap:wrap}
|
||||
.minor .m{flex:1;min-width:220px;border:1px solid var(--line-soft);border-radius:10px;padding:11px 14px;font-size:12px;color:var(--ink-2)}
|
||||
.minor .m b{display:block;font-size:12.5px;color:var(--ink);margin-bottom:3px}
|
||||
.minor .m .lid{font-family:var(--mono);color:var(--ink-4);font-weight:700;margin-right:6px}
|
||||
|
||||
footer{margin-top:18px;font-size:11.5px;color:var(--ink-4);display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px}
|
||||
@media(max-width:900px){.layers{grid-template-columns:repeat(2,1fr)}.kv{grid-template-columns:1fr 1fr}.kv .span2{grid-column:span 2}}
|
||||
`;
|
||||
|
||||
/* ==================== 绑定层:徽标别名 / 三态横幅 / 淡显 —— 只取值,不算不判 ==================== */
|
||||
const OK = 'color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4;';
|
||||
const MISS = 'color:var(--danger);background:var(--danger-soft);border-color:#f3b9b5;';
|
||||
const UNKNOWN = 'color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line);';
|
||||
const COND = 'color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft);';
|
||||
const GRAY = 'color:var(--ink-3);background:var(--soft);border-color:var(--line);';
|
||||
const WARN = 'color:var(--human);background:var(--human-soft);border-color:var(--human-line);';
|
||||
|
||||
const BIND_CSS = `
|
||||
/* 徽标:值域各归各族(同一个词在不同列意思不同,如 pending 在资料状态是待生效、在需求状态是待处理),
|
||||
文案与颜色由 data-class-of 投出的 v-<token> 决定;没投出 class 的格子摆「—」,客户批准那格摆「未提交」 */
|
||||
.st::after{content:"—"}
|
||||
.st.ap::after{content:"未提交"}
|
||||
${badgeCss('.st.lc', [
|
||||
['active', 'Active', OK],
|
||||
['nrnd', 'NRND', MISS],
|
||||
['eol', 'EOL', MISS],
|
||||
['discontinued', '停产', MISS],
|
||||
['risk', '风险', WARN],
|
||||
])}
|
||||
${badgeCss('.st.rec', [
|
||||
['recommended', '推荐', OK],
|
||||
['conditional', '条件推荐', WARN],
|
||||
['alternate', '备选', COND],
|
||||
['not_recommended', '不推荐', MISS],
|
||||
])}
|
||||
${badgeCss('.st.an', [
|
||||
['ai_draft', 'AI 草稿', GRAY],
|
||||
['fae_confirmed', 'FAE确认', COND],
|
||||
['pending_customer', '待客户验证', WARN],
|
||||
['customer_approved', '客户已批准', OK],
|
||||
['rejected', '不批准', MISS],
|
||||
['void', '作废', GRAY],
|
||||
])}
|
||||
${badgeCss('.st.rk', [
|
||||
['low', '低', OK],
|
||||
['medium', '中', WARN],
|
||||
['high', '高', MISS],
|
||||
['critical', '危急', MISS],
|
||||
])}
|
||||
${badgeCss('.st.dst', [
|
||||
['match', 'MATCH', OK],
|
||||
['mismatch', 'MISMATCH', MISS],
|
||||
['unknown', 'UNKNOWN', UNKNOWN],
|
||||
['conditional', 'CONDITIONAL', COND],
|
||||
])}
|
||||
${badgeCss('.st.vs', [
|
||||
['not_started', '未开始', GRAY],
|
||||
['in_progress', '进行中', COND],
|
||||
['passed', '通过', OK],
|
||||
['failed', '未通过', MISS],
|
||||
['conditional', '条件通过', WARN],
|
||||
['pending_evidence', '待证据', UNKNOWN],
|
||||
])}
|
||||
${badgeCss('.st.ds', [
|
||||
['valid', '有效', OK],
|
||||
['expired', '过期', MISS],
|
||||
['pending', '待生效', WARN],
|
||||
['void', '作废', GRAY],
|
||||
])}
|
||||
${badgeCss('.st.rq', [
|
||||
['pending', '待处理', GRAY],
|
||||
['responded', '已响应', COND],
|
||||
['won', '已成交', OK],
|
||||
['abandoned', '已放弃', MISS],
|
||||
['closed', '已关闭', GRAY],
|
||||
])}
|
||||
${badgeCss('.st.stg', [
|
||||
['assessing', '评估中', GRAY],
|
||||
['gate03', '提交 ACT-GATE-03', OK],
|
||||
])}
|
||||
${badgeCss('.st.ex', [
|
||||
['found', '在库直读', COND],
|
||||
['created', '本单建档', OK],
|
||||
['absent', '缺库', MISS],
|
||||
['abandoned', '已放弃', GRAY],
|
||||
])}
|
||||
${badgeCss('.st.rl', [
|
||||
['original', '原 PN', COND],
|
||||
['candidate', '候选', GRAY],
|
||||
])}
|
||||
/* 纯文字的枚举列:只补文案 */
|
||||
.enumtxt::after{content:"—"}
|
||||
${badgeCss('.enumtxt.ty', [
|
||||
['pin_to_pin', 'Pin-to-Pin'],
|
||||
['functional', '功能替代'],
|
||||
['parametric', '参数替代'],
|
||||
['other', '其他'],
|
||||
])}
|
||||
${badgeCss('.enumtxt.con', [
|
||||
['hard', '硬约束'],
|
||||
['soft', '软约束'],
|
||||
])}
|
||||
${badgeCss('.enumtxt.vt', [
|
||||
['pin_to_pin', 'Pin-to-Pin'],
|
||||
['functional', '功能'],
|
||||
['reliability', '可靠性'],
|
||||
['certification', '认证'],
|
||||
['retest', '复测'],
|
||||
])}
|
||||
${badgeCss('.enumtxt.dt', [
|
||||
['datasheet', 'Datasheet'],
|
||||
['app_note', '应用笔记'],
|
||||
['reference_design', '参考设计'],
|
||||
['white_paper', '白皮书'],
|
||||
['sample_doc', '样品资料'],
|
||||
['commitment_letter', '承诺函'],
|
||||
['other', '其他'],
|
||||
])}
|
||||
|
||||
/* 页头候选料号:一行内逐个摆,用顿号连;一个都没有就摆「—」 */
|
||||
.cands b+b::before{content:"、";font-weight:400;color:var(--ink-3)}
|
||||
.cands:empty::after{content:"—"}
|
||||
/* 参数瓷贴:参数名淡、值粗、单位紧跟 */
|
||||
.pchips i{font-style:normal;color:var(--ink-4);margin-right:3px}
|
||||
.pchips b{font-weight:700}
|
||||
.pchips em{font-style:normal;margin-left:1px}
|
||||
.pchips:empty::after{content:"参数集未登记";font-size:11px;color:var(--ink-4)}
|
||||
/* 料号格里的两枚小徽(角色 / 在库状态) */
|
||||
.pnrow{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}
|
||||
.pnrow .st{font-size:10px;padding:0 7px}
|
||||
/* 差异明细:MATCH 行淡显(不藏:那也是比对过的事实),非 MATCH 才是要看的 */
|
||||
tr.v-match td{opacity:.55}
|
||||
/* 已放弃的候选:只在有 abandoned 行时露面,别的核对行不显 */
|
||||
.aband{display:none;font-size:12px;color:var(--ink-3);margin:8px 0 0}
|
||||
.aband i{font-style:normal;font-family:var(--mono);color:var(--ink-2)}
|
||||
.aband i:not(.v-abandoned){display:none}
|
||||
.aband i+i.v-abandoned::before{content:"、"}
|
||||
.aband:has(i.v-abandoned){display:block}
|
||||
/* P-06 历史行:首格挂一枚「历史」灰签 */
|
||||
tbody.hist td:first-child::after{content:"历史";display:inline-block;margin-left:6px;font-size:10px;font-weight:800;padding:0 6px;border-radius:999px;color:var(--ink-3);background:var(--soft);border:1px solid var(--line);font-family:Inter,ui-sans-serif,system-ui,sans-serif}
|
||||
td .sub{display:block;font-size:11px;color:var(--ink-3);font-weight:400}
|
||||
td .sub:empty{display:none}
|
||||
/* 三态横幅:none = 本活动还没有已放行实例;missing = 有实例但案号在正式表里查无 */
|
||||
.notice{display:none;align-items:flex-start;gap:8px;margin:0 0 16px;padding:12px 16px;border-radius:12px;font-size:13px;line-height:1.6}
|
||||
.notice.none{background:var(--soft);border:1px solid var(--line);color:var(--ink-2)}
|
||||
.notice.missing{background:var(--amber-soft);border:1px solid var(--amber-line);color:var(--amber)}
|
||||
.page.v-none .notice.none{display:flex}
|
||||
.page.v-missing .notice.missing{display:flex}
|
||||
.page.v-none .layers,.page.v-none section,.page.v-none .mast .sub.case,.page.v-none .mast .sub.verdict{display:none}
|
||||
.page.v-missing section,.page.v-missing .mast .sub.verdict{display:none}
|
||||
`;
|
||||
|
||||
const th = (...cols: string[]): string => `<thead><tr>${cols.map((c) => `<th>${c}</th>`).join('')}</tr></thead>`;
|
||||
|
||||
export const LEDGER_BOARD = `<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>ACT-WORK-05 差异评估 · 关键台账数据 · SS02 需求分析与方案匹配</title>
|
||||
<style>${TARGET_CSS}${BIND_CSS}</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page" data-class-of="board:state">
|
||||
|
||||
<header class="mast">
|
||||
<div class="kick">SS02 需求分析与方案匹配 · 活动台账视图</div>
|
||||
<h1><span class="code">ACT-WORK-05</span>关键台账数据</h1>
|
||||
<p class="sub case">视角:本活动最近一次已放行实例 <b data-slot="case:instanceNo"></b>(<b data-slot="case:openedAt"></b> 开案 · <b data-slot="case:releasedAt"></b> 放行 · 负责人 <b data-slot="case:owner" data-blank></b>)的落账快照 · 案号 <b class="mono" data-slot="case:ref"></b> · 关联需求 <b data-slot="demand.request.request_id"></b>(客户 <b data-slot="demand.request.customer_code"></b> <span data-slot="customer.profile.name" data-blank></span>)· 评估基准 <b data-slot="${D}.verdict.original_internal_pn"></b>(<span data-slot="parts.profile.brand_name" data-blank></span>)→ 候选 <span class="cands" data-rows="substitution.relation"><b data-slot="candidate_internal_pn"></b></span> · 规则版本 <b data-slot="${D}.verdict.rule_version"></b></p>
|
||||
<p class="sub verdict">评估结论:<span data-slot="${D}.verdict.summary" data-blank></span></p>
|
||||
<div class="legend">
|
||||
<span class="li"><span class="dot full"></span>正式台账直读 —— 放行落地后的事实,按案号圈出这一单的行</span>
|
||||
<span class="li"><span class="dot half"></span>同料号的历史验证记录(别单 / 线下留下的,作本次评估的证据引用)</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="notice none">本活动还没有已放行的实例 —— 有一单放行后,这里摆它的关键台账落账快照。</div>
|
||||
<div class="notice missing">实例 <b data-slot="case:instanceNo"></b> 已放行,但案号 <b class="mono" data-slot="case:ref"></b> 在正式表里查无 —— 多半是起单时关了「落真库」(主数据只留在活动缓存),这一单没有可摆的落账数据。</div>
|
||||
|
||||
<!-- 重要性分层 -->
|
||||
<div class="layers">
|
||||
<div class="layer"><b><span class="lg">P-08</span> 芯片主数据</b>核心输入 · 评估原材料,查无即硬阻塞</div>
|
||||
<div class="layer core-out"><b><span class="lg">P-11</span> 替代批准关系库</b>核心产出 · 结论与明细的落账地</div>
|
||||
<div class="layer evid"><b><span class="lg">P-10</span> 原厂技术资料库</b>证据链 · 每项结论的版本化出处</div>
|
||||
<div class="layer loop"><b><span class="lg">P-06</span> 样品验证记录</b>闭环去向 · UNKNOWN 的实测收口</div>
|
||||
<div class="layer ctx"><b><span class="lg">P-01</span> 客户需求主台账</b>上下文 · 需求源头与回写对象</div>
|
||||
</div>
|
||||
|
||||
<!-- P-01 -->
|
||||
<section id="p01">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-01</span>客户需求主台账</h2>
|
||||
<span class="ltag ctx">上下文 · R+W</span>
|
||||
<span class="why">启动时新建需求;结束时回写风险 / 验证要求 / 输出链接 / 下一步 / 当前阶段</span>
|
||||
<span class="cnt">正式表 · <i data-slot="demand_request_rows"></i> 条</span>
|
||||
</div>
|
||||
<div class="kv">
|
||||
<div class="cell"><div class="k">需求编号</div><div class="v mono" data-slot="demand.request.request_id"></div></div>
|
||||
<div class="cell"><div class="k">客户</div><div class="v mono"><span data-slot="demand.request.customer_code"></span> <span class="sub" data-slot="customer.profile.name" data-blank></span></div></div>
|
||||
<div class="cell"><div class="k">需求版本</div><div class="v mono" data-slot="demand.request.requirement_version"></div></div>
|
||||
<div class="cell"><div class="k">需求状态</div><div class="v"><span class="st rq" data-class-of="demand.request.request_status"></span></div></div>
|
||||
<div class="cell span2"><div class="k">需求描述</div><div class="v" data-slot="demand.request.request_description"></div></div>
|
||||
<div class="cell"><div class="k">应用场景</div><div class="v" data-slot="demand.request.application_scenario" data-blank></div></div>
|
||||
<div class="cell"><div class="k">BOM 位</div><div class="v mono" data-slot="demand.request.bom_position" data-blank></div></div>
|
||||
<div class="cell"><div class="k">原内部料号</div><div class="v mono" data-slot="demand.request.original_internal_pn"></div></div>
|
||||
<div class="cell"><div class="k">候选内部料号</div><div class="v mono cands" data-rows="substitution.relation"><b data-slot="candidate_internal_pn"></b></div></div>
|
||||
<div class="cell"><div class="k">风险等级(回写)</div><div class="v"><span class="st rk" data-class-of="demand.request.risk_level"></span></div></div>
|
||||
<div class="cell"><div class="k">验证要求(回写)</div><div class="v mono" data-slot="demand.request.verification_requirement" data-blank></div></div>
|
||||
<div class="cell"><div class="k">当前阶段</div><div class="v"><span class="st stg" data-class-of="demand.request.current_stage"></span></div></div>
|
||||
<div class="cell"><div class="k">标准输出链接</div><div class="v mono" data-slot="demand.request.output_ref" data-blank></div></div>
|
||||
<div class="cell span2"><div class="k">下一步动作</div><div class="v" data-slot="demand.request.next_action" data-blank></div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- P-08 -->
|
||||
<section id="p08">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-08</span>芯片主数据台账</h2>
|
||||
<span class="ltag in">核心输入 · R(查无 → 数据工单创建)</span>
|
||||
<span class="why">原 PN 与候选 PN 的物料基准 + 标准化参数集(子表 P-08 参数),逐项比对的原材料</span>
|
||||
<span class="cnt">正式表 · <i data-slot="parts_profile_rows"></i> 条(本活动相关)</span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
${th('内部料号', '品牌', '规格描述', '封装', '生命周期', 'Datasheet 版本', '标准化参数集', '适配场景')}
|
||||
<tbody data-rows="parts.profile">
|
||||
<tr>
|
||||
<td class="pn mono"><span data-slot="internal_pn"></span><span class="pnrow" data-rows="${D}.pn_check" data-by="internal_pn"><i class="st rl" data-class-of="role"></i><i class="st ex" data-class-of="exists_status"></i></span></td>
|
||||
<td data-slot="brand_name" data-blank></td>
|
||||
<td data-slot="specification_description" data-blank></td>
|
||||
<td class="mono" data-slot="package" data-blank></td>
|
||||
<td><span class="st lc" data-class-of="lifecycle_status"></span></td>
|
||||
<td class="mono" data-slot="datasheet_version" data-blank></td>
|
||||
<td><div class="pchips" data-rows="parts.parameter" data-by="internal_pn"><span><i data-slot="param_name"></i><b data-slot="param_value" data-blank></b><em data-slot="param_unit" data-blank></em></span></div></td>
|
||||
<td data-slot="application_scenarios" data-blank></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="aband">本轮放弃的候选(未建档、未评估):<span data-rows="${D}.pn_check"><i data-class-of="exists_status" data-slot="internal_pn"></i></span></p>
|
||||
</section>
|
||||
|
||||
<!-- P-11 -->
|
||||
<section id="p11">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-11</span>替代选型与批准关系库 · 替代关系主记录</h2>
|
||||
<span class="ltag out">核心产出 · R+W</span>
|
||||
<span class="why">每个候选一条关系记录;客户批准状态为只读边界,本活动不写</span>
|
||||
<span class="cnt">正式表 · <i data-slot="substitution_relation_rows"></i> 条</span>
|
||||
</div>
|
||||
<div class="tbl-wrap" style="margin-bottom:14px">
|
||||
<table>
|
||||
${th('替代关系 ID', '原 → 候选', '替代类型', '推荐等级', '分析状态', '风险', '差异摘要', '验证要求 / 回链', '规则版本', '客户批准(只读)')}
|
||||
<tbody data-rows="substitution.relation">
|
||||
<tr>
|
||||
<td class="mono" data-slot="substitution_relation_id"></td>
|
||||
<td class="mono"><span data-slot="original_internal_pn"></span> → <b data-slot="candidate_internal_pn"></b></td>
|
||||
<td><span class="enumtxt ty" data-class-of="substitution_type"></span></td>
|
||||
<td><span class="st rec" data-class-of="recommendation_level"></span></td>
|
||||
<td><span class="st an" data-class-of="analysis_status"></span></td>
|
||||
<td><span class="st rk" data-class-of="risk_level"></span></td>
|
||||
<td><span data-slot="difference_summary" data-blank></span><span class="sub" data-slot="recommendation_reason" data-blank></span></td>
|
||||
<td class="mono"><span data-slot="validation_id" data-blank></span><span class="sub" data-slot="verification_requirement" data-blank></span></td>
|
||||
<td class="mono" data-slot="rule_version" data-blank></td>
|
||||
<td><span class="st ap" data-class-of="customer_approval_status"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="sec-head" style="margin-bottom:10px">
|
||||
<h2 style="font-size:13.5px"><span class="lid">P-11</span>差异明细子表(由双方 P-08 标准化参数集逐项比对得出;MATCH 项淡显)</h2>
|
||||
<span class="cnt"><i data-slot="substitution_difference_item_rows"></i> 条 · MATCH <i data-slot="substitution_difference_item_difference_status_match"></i> · MISMATCH <i data-slot="substitution_difference_item_difference_status_mismatch"></i> · UNKNOWN <i data-slot="substitution_difference_item_difference_status_unknown"></i> · CONDITIONAL <i data-slot="substitution_difference_item_difference_status_conditional"></i></span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
${th('所属关系', '参数项', '原值 → 候选值', '约束', '结论', '风险', '证据引用', '影响说明')}
|
||||
<tbody data-rows="substitution.difference_item">
|
||||
<tr data-class-of="difference_status">
|
||||
<td class="mono" data-slot="substitution_relation_id"></td>
|
||||
<td data-slot="parameter_name"></td>
|
||||
<td class="mono"><span data-slot="original_value" data-blank></span> → <span data-slot="candidate_value" data-blank></span> <span data-slot="parameter_unit" data-blank></span></td>
|
||||
<td><span class="enumtxt con" data-class-of="constraint_type"></span></td>
|
||||
<td><span class="st dst" data-class-of="difference_status"></span></td>
|
||||
<td><span class="st rk" data-class-of="risk_level"></span></td>
|
||||
<td class="mono" data-slot="evidence_ref" data-blank></td>
|
||||
<td><span data-slot="impact_statement" data-blank></span><span class="sub" data-slot="unknown_disposition" data-blank></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- P-10 -->
|
||||
<section id="p10">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-10</span>原厂技术资料库</h2>
|
||||
<span class="ltag evid">证据链 · R(查无 → 数据工单创建)</span>
|
||||
<span class="why">每项结论的 datasheet 出处,版本回链</span>
|
||||
<span class="cnt">正式表 · <i data-slot="parts_document_rows"></i> 条(本活动相关料号)</span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
${th('关联料号', '品牌', '资料类型', '资料文件', '版本', '状态')}
|
||||
<tbody data-rows="parts.document">
|
||||
<tr>
|
||||
<td class="mono"><span data-slot="internal_pn"></span> · <span data-slot="doc_seq" data-blank></span></td>
|
||||
<td data-slot="brand_name" data-blank></td>
|
||||
<td><span class="enumtxt dt" data-class-of="document_type"></span></td>
|
||||
<td class="mono" data-slot="document_ref" data-blank></td>
|
||||
<td class="mono" data-slot="document_version" data-blank></td>
|
||||
<td><span class="st ds" data-class-of="document_status"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- P-06 -->
|
||||
<section id="p06">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-06</span>样品交付与芯片验证记录台账</h2>
|
||||
<span class="ltag loop">闭环去向 · R + 条件写(不可创建,只能实测产生)</span>
|
||||
<span class="why">UNKNOWN / CONDITIONAL 的收口处;验证完成后回链 P-11</span>
|
||||
<span class="cnt">本单挂的 · <i data-slot="validation_record_rows"></i> 条 · 同料号历史 · <i data-slot="validation_history_rows"></i> 条</span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
${th('验证 ID', '关联需求', '验证料号', '验证类型', '测试条件', '结果 / 状态', '问题与风险', '后续动作')}
|
||||
<tbody data-rows="validation.record">
|
||||
<tr>
|
||||
<td class="mono" data-slot="validation_id"></td>
|
||||
<td class="mono" data-slot="request_id" data-blank></td>
|
||||
<td class="mono" data-slot="validation_internal_pn"></td>
|
||||
<td><span class="enumtxt vt" data-class-of="validation_type"></span></td>
|
||||
<td data-slot="test_condition" data-blank></td>
|
||||
<td><span class="st vs" data-class-of="validation_status"></span><span class="sub" data-slot="test_result" data-blank></span><span class="sub mono" data-slot="evidence_ref" data-blank></span></td>
|
||||
<td data-slot="issue_risk" data-blank></td>
|
||||
<td data-slot="next_validation_action" data-blank></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody class="hist" data-rows="validation.history">
|
||||
<tr>
|
||||
<td class="mono" data-slot="validation_id"></td>
|
||||
<td class="mono" data-slot="request_id" data-blank></td>
|
||||
<td class="mono" data-slot="validation_internal_pn"></td>
|
||||
<td><span class="enumtxt vt" data-class-of="validation_type"></span></td>
|
||||
<td data-slot="test_condition" data-blank></td>
|
||||
<td><span class="st vs" data-class-of="validation_status"></span><span class="sub" data-slot="test_result" data-blank></span><span class="sub mono" data-slot="evidence_ref" data-blank></span></td>
|
||||
<td data-slot="issue_risk" data-blank></td>
|
||||
<td data-slot="next_validation_action" data-blank></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 次要台账 -->
|
||||
<section id="minor">
|
||||
<div class="sec-head">
|
||||
<h2>次要台账(只读引用,不进主看板)</h2>
|
||||
</div>
|
||||
<div class="minor">
|
||||
<div class="m"><b><span class="lid">P-09</span>客户技术与机会档案</b>提供 BOM 位与客户技术栈背景;缺口由执行工单补齐。</div>
|
||||
<div class="m"><b><span class="lid">EXT-02</span>外部来源清单</b>登记本次评估用到的可信外部来源(原厂官网 datasheet 等)。</div>
|
||||
<div class="m"><b><span class="lid">GOV</span>评估规则库</b>四态判定口径;本次锁定版本 <span class="mono" data-slot="${D}.verdict.rule_version"></span>,随结论一并落账。</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<span>SS02 · ACT-WORK-05 差异评估 · 关键台账数据视图</span>
|
||||
<span style="font-family:var(--mono)">数据来源:正式台账(parts / demand / substitution / validation / sub_eval)· 实例 <span data-slot="case:instanceNo"></span> · 案号 <span data-slot="case:ref"></span></span>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
@@ -140,6 +140,14 @@ ${badgeCss('.ct', [
|
||||
|
||||
/* ==================== 执行工单(评估输入清单):徽标别名 ==================== */
|
||||
const BIND_EXEC = `
|
||||
/* 候选参数现值(只读参考块):一颗料一张,复用 .jc-tbl-wrap;块头摆料号 / 角色 / 在库状态 */
|
||||
.prefs { display: block; }
|
||||
.pref { border: 1px solid var(--line-soft); border-radius: 10px; overflow: hidden; margin-bottom: 12px; }
|
||||
.pref:last-of-type { margin-bottom: 0; }
|
||||
.pref-head { display: flex; align-items: center; gap: 10px; padding: 9px 14px; background: var(--soft); border-bottom: 1px solid var(--line); }
|
||||
.pref-head b { font-size: 13.5px; }
|
||||
.pref .jc-tbl-wrap { border: 0; border-radius: 0; }
|
||||
|
||||
/* 存在性核对的两列(角色 / 在库状态)与评估输入清单的状态列共用目标件自己的 .st 徽标基座 ——
|
||||
取值域互不重叠(found/absent/created/abandoned 与 gap/default/ok 没有一个词撞车)。
|
||||
四档配色**原样照抄目标件自己的 .st.bound / .st.ok / .st.miss / .st.def 那四条声明**,只换成 v- 版。 */
|
||||
@@ -181,14 +189,21 @@ ${badgeCss('.st.dst', [
|
||||
['match', 'MATCH', OK],
|
||||
['mismatch', 'MISMATCH', DANGER],
|
||||
['unknown', 'UNKNOWN', AMBER],
|
||||
['conditional', 'CONDITIONAL', 'color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line);'],
|
||||
// 目标件 2026-08-27 改版:CONDITIONAL 从题头红改成品牌蓝(.st.cond),原样照抄
|
||||
['conditional', 'CONDITIONAL', 'color: var(--brand-deep); background: var(--brand-wash); border-color: var(--brand-soft);'],
|
||||
])}
|
||||
${badgeCss('.st.rec', [
|
||||
/* 推荐程度 pill —— 目标件 .rec.yes / .rec.cond / .rec.no 三条声明原样照抄;台账是四档(备选借条件推荐那档琥珀) */
|
||||
${badgeCss('.rec', [
|
||||
['recommended', '推荐', OK],
|
||||
['conditional', '条件推荐', 'color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line);'],
|
||||
['alternate', '备选', AMBER],
|
||||
['conditional', '有条件推荐', 'color: var(--amber); background: var(--amber-soft); border-color: var(--amber-line);'],
|
||||
['alternate', '备选', 'color: var(--amber); background: var(--amber-soft); border-color: var(--amber-line);'],
|
||||
['not_recommended', '不推荐', DANGER],
|
||||
])}
|
||||
/* 候选块序号(目标件 .cand-idx 写死 1/2)—— 交给 CSS 计数器;块头的风险级别前缀「风险 」也在目标件里 */
|
||||
.card-bd { counter-reset: cand; }
|
||||
.cand { counter-increment: cand; }
|
||||
.cand-idx::before { content: counter(cand); }
|
||||
.cand-con .risk::before { content: "风险 "; }
|
||||
/*
|
||||
* 风险等级(原样照抄目标件 .risk.low/.mid/.hi 三条声明)——加 critical 一档:这一屏「各候选
|
||||
* 推荐等级」摘要读的是 substitution.relation.risk_level(声明了 low/medium/high/critical
|
||||
@@ -196,7 +211,7 @@ ${badgeCss('.st.rec', [
|
||||
*/
|
||||
${badgeCss('.risk', [
|
||||
['low', '低', 'color: var(--ok);'],
|
||||
['medium', '中', 'color: #8f6a12;'],
|
||||
['medium', '中', 'color: var(--amber, #8f6a12);'],
|
||||
['high', '高', 'color: var(--danger);'],
|
||||
['critical', '危急', 'color: var(--danger); font-weight: 900;'],
|
||||
])}
|
||||
@@ -246,7 +261,7 @@ ${badgeCss('.st', [
|
||||
/* 风险等级比验收 01 多一档 critical(P-11 主记录的 risk_level 声明了它,差异明细没有) */
|
||||
${badgeCss('.risk', [
|
||||
['low', '低', 'color: var(--ok);'],
|
||||
['medium', '中', 'color: #8f6a12;'],
|
||||
['medium', '中', 'color: var(--amber, #8f6a12);'],
|
||||
['high', '高', 'color: var(--danger);'],
|
||||
['critical', '危急', 'color: var(--danger); font-weight: 900;'],
|
||||
])}
|
||||
@@ -496,6 +511,25 @@ const PN_CHECK_TABLE = `<div class="jc-tbl-wrap"><table>
|
||||
</tr></tbody>
|
||||
</table></div>`;
|
||||
|
||||
/** 候选参数现值 —— **只读参考,基座从台账现读**(2026-08-27,用户三次指出「库里明明有值,清单还要填一遍」):
|
||||
* 从前「待确认」行由模型判「哪个参数原厂未披露」再写进清单 —— 参数值有没有是台账里的事实,不该由模型宣布;
|
||||
* 现在每颗料一张小表(外层按核对表逐颗复制,里层 `data-by="internal_pn"` 只列它名下的参数行),
|
||||
* 人看得见现值;未披露的由差异评估判成 UNKNOWN 并挂验证任务。 */
|
||||
const PARAM_REF = `<article class="prefs" data-rows="mine:${D}.pn_check"><section class="pref">
|
||||
<div class="pref-head"><b class="mono" data-slot="internal_pn" data-blank></b><span class="rl" data-class-of="role"></span>${badge('st', 'exists_status')}</div>
|
||||
<div class="jc-tbl-wrap"><table>
|
||||
<thead><tr><th style="width:38px">#</th><th data-h="参数名">参数名</th><th data-h="值">值</th><th data-h="单位">单位</th><th data-h="约束类型">约束类型</th><th data-h="说明">说明</th></tr></thead>
|
||||
<tbody data-rows="parts.parameter" data-by="internal_pn"><tr>
|
||||
<td class="rn"><span class="jc-rn-num"></span></td>
|
||||
<td>${ro('param_name')}</td>
|
||||
<td>${ro('param_value', 'mono')}</td>
|
||||
<td>${ro('param_unit')}</td>
|
||||
<td><span class="jc-vcell ro"><span class="ct" data-class-of="constraint_type"></span></span></td>
|
||||
<td>${ro('param_note')}</td>
|
||||
</tr></tbody>
|
||||
</table></div>
|
||||
</section></article>`;
|
||||
|
||||
const GAP_TABLE = `<div class="jc-tbl-wrap"><table id="tbl">
|
||||
<thead><tr>
|
||||
<th style="width:38px">#</th>
|
||||
@@ -530,13 +564,16 @@ export const EVAL_INPUT_LIST = doc({
|
||||
zone('做什么', '启动 4 项已绑定,其余信息在工单里补齐') +
|
||||
note([
|
||||
'<span class="done">AI 已完成</span>:系统已按启动传入的 <b>4 项</b>完成绑定——客户、客户需求(新建 P-01 · 版本 V1)、原 PN、候选 PN(数组,逐个评估)——并生成输入快照。',
|
||||
'<span class="need">需要你补齐</span>:启动时未收的信息(应用场景、BOM 位)<b>直接在下表补</b>;默认值(替代类型 / 规则版本 / 负责人期限)可确认可改。本单缺口只覆盖「<b>有而不全</b>」;「完全没有」(料号不在库)已由数据工单创建。未补齐的缺口项将按 <b>UNKNOWN</b> 进入差异评估。',
|
||||
'<span class="need">需要你补齐</span>:启动时未收的信息(应用场景、BOM 位)<b>直接在下表补</b>;默认值(替代类型 / 规则版本 / 负责人期限)可确认可改。「完全没有」(料号不在库)已由数据工单创建;每颗料的参数现值摆在「候选参数现值」里,写着「未披露」的参数将按 <b>UNKNOWN</b> 进入差异评估并挂验证任务,不用在这里补。',
|
||||
]) +
|
||||
zone('料号存在性核对', '只读参考 · 与下表「补充内容」互不冲突') +
|
||||
PN_CHECK_TABLE +
|
||||
zone('候选参数现值', '只读参考 · P-08 标准化参数集,一颗料一张,基座从台账现读;写着「未披露」的由差异评估判成 UNKNOWN 并挂验证任务') +
|
||||
PARAM_REF +
|
||||
zone('交回什么', '评估输入清单(已绑定项照实核对,缺口项补齐,*为必填)') +
|
||||
gapbar(`${D}_input_gap`, '补充内容') +
|
||||
editGate(`${D}.input_gap`, `<b>还有 <span data-slot="${D}_input_gap_missing"></span> 项待补 / 待确认</b>,点「编辑」在「补充内容」列填入 —— 已绑定那几行的「输入项/来源/绑定值」抄的是启动入参,发现记录本身有误请退回触发方重新启动,不要在这里改`) +
|
||||
// 红带说「必填格」不说「补充内容」:缺的可能是 AI 该写的输入项(2026-08-27 实测),写死列名会把人指向错的格子
|
||||
gapbar(`${D}_input_gap`, '必填格') +
|
||||
editGate(`${D}.input_gap`, `<b>还有 <span data-slot="${D}_input_gap_missing"></span> 项待补</b>,点「编辑」在「补充内容」列填入 —— 已绑定那几行的「输入项/来源/绑定值」抄的是启动入参,发现记录本身有误请退回触发方重新启动,不要在这里改`) +
|
||||
GAP_TABLE +
|
||||
addrow(`${D}.input_gap`, '+ 加一行(补充资料项)', '新行的「键」必须写(它是这一行的钥匙,写一个英文短名,如 thermal_note);「输入项」与「补充内容」也是必填;删一行 = 该输入项不适用;补不了的写「留 UNKNOWN」或「挂验证任务」') +
|
||||
flow(
|
||||
@@ -546,42 +583,59 @@ export const EVAL_INPUT_LIST = doc({
|
||||
|
||||
/* ==================== 局面 2 · 差异评估结论审核(搬自「验收工单-01」)==================== */
|
||||
|
||||
const RELATION_SUMMARY_TABLE = `<div class="tbl-wrap"><table>
|
||||
/** 候选 PN 结论汇总 —— 目标件 2026-08-27 改版:一个候选一条结论(P-11 主表草稿)。
|
||||
* 品牌不在 relation 上:用嵌套行模版 `data-by` 从 `parts.profile` 整表里挑这一颗料那一行(取值,不是算)。
|
||||
* 「差异统计(四态)」绑 difference_summary —— S3 剧本让模型按「7 项比对:4 MATCH / 1 MISMATCH / …」的形写它,
|
||||
* 模版不数四态(数出来的画面一律不做假)。 */
|
||||
const RELATION_SUMMARY_TABLE = `<div class="tbl-wrap" style="margin-bottom:20px"><table>
|
||||
<thead><tr>
|
||||
<th style="width:40px">#</th>
|
||||
<th data-h="候选料号">候选料号</th>
|
||||
<th data-h="替代类型">替代类型</th>
|
||||
<th data-h="推荐等级">推荐等级</th>
|
||||
<th data-h="风险等级">风险等级</th>
|
||||
<th data-h="推荐理由">推荐理由</th>
|
||||
<th data-h="差异摘要">差异摘要</th>
|
||||
<th data-h="候选PN">候选 PN</th>
|
||||
<th data-h="品牌">品牌</th>
|
||||
<th data-h="推荐程度">推荐程度</th>
|
||||
<th data-h="风险级别">风险级别</th>
|
||||
<th data-h="差异统计">差异统计(四态)</th>
|
||||
<th data-h="结论摘要">结论摘要</th>
|
||||
</tr></thead>
|
||||
<tbody data-rows="mine:substitution.relation"><tr>
|
||||
<td class="num"></td>
|
||||
<td class="mono" data-slot="candidate_internal_pn" data-blank></td>
|
||||
<td><span class="enumtxt" data-class-of="substitution_type"></span></td>
|
||||
<td>${badge('st rec', 'recommendation_level')}</td>
|
||||
<td class="cust mono" data-slot="candidate_internal_pn" data-blank></td>
|
||||
<td><span data-rows="parts.profile" data-by="internal_pn=candidate_internal_pn"><i data-slot="brand_name" data-blank></i></span></td>
|
||||
<td>${badge('rec', 'recommendation_level')}</td>
|
||||
<td>${badge('risk', 'risk_level')}</td>
|
||||
<td class="stat" data-slot="difference_summary" data-blank></td>
|
||||
<td class="reason" data-slot="recommendation_reason" data-blank></td>
|
||||
<td class="reason" data-slot="difference_summary" data-blank></td>
|
||||
</tr></tbody>
|
||||
</table></div>`;
|
||||
|
||||
const DIFFERENCE_ITEM_TABLE = `<div class="tbl-wrap"><table>
|
||||
<thead><tr><th style="width:40px">#</th><th data-h="参数项">参数项</th><th data-h="原PN值">原 PN 值</th><th data-h="候选PN值">候选 PN 值</th><th data-h="单位">单位</th><th data-h="约束类型">约束类型</th><th data-h="结论">结论</th><th data-h="风险等级">风险等级</th><th data-h="证据引用">证据引用</th><th data-h="AI置信度">AI 置信度</th></tr></thead>
|
||||
<tbody data-rows="mine:substitution.difference_item"><tr>
|
||||
<td class="num"></td>
|
||||
<td class="cust" data-slot="parameter_name" data-blank></td>
|
||||
<td class="mono" data-slot="original_value" data-blank></td>
|
||||
<td class="mono" data-slot="candidate_value" data-blank></td>
|
||||
<td data-slot="parameter_unit" data-blank></td>
|
||||
<td><span class="con" data-class-of="constraint_type"></span></td>
|
||||
<td>${badge('st dst', 'difference_status')}</td>
|
||||
<td>${badge('risk', 'risk_level')}</td>
|
||||
<td class="mono" data-slot="evidence_ref" data-blank></td>
|
||||
<td class="mono" data-slot="confidence" data-blank></td>
|
||||
</tr></tbody>
|
||||
</table></div>`;
|
||||
/** 差异明细 · 按候选 PN 分组 —— 目标件 2026-08-27 改版:**一个候选一张表**(用户:「存在多个替代 PN 要对比差异时看不清楚」)。
|
||||
* 外层容器 <article> 按 relation 逐个复制行模版 <section class="cand">,里层 <tbody data-by="substitution_relation_id">
|
||||
* 只列该候选名下的明细(渲染器 2026-08-27 补的嵌套 + 父键过滤)。容器标签名不得在行模版内部再出现:
|
||||
* <article> 里是 section / div / table,不撞。 */
|
||||
const CANDIDATE_SECTIONS = `<article class="cands" data-rows="mine:substitution.relation"><section class="cand">
|
||||
<div class="cand-head">
|
||||
<span class="cand-idx"></span>
|
||||
<span class="cand-name mono" data-slot="candidate_internal_pn" data-blank></span>
|
||||
<span class="cand-brand" data-rows="parts.profile" data-by="internal_pn=candidate_internal_pn"><i data-slot="brand_name" data-blank></i></span>
|
||||
<span class="cand-vs">vs 原 PN · <i data-slot="original_internal_pn" data-blank></i></span>
|
||||
<span class="cand-con">${badge('rec', 'recommendation_level')}${badge('risk', 'risk_level')}</span>
|
||||
</div>
|
||||
<div class="tbl-wrap"><table>
|
||||
<thead><tr><th style="width:40px">#</th><th data-h="参数项">参数项</th><th data-h="原PN值">原 PN 值</th><th data-h="候选PN值">候选 PN 值</th><th data-h="单位">单位</th><th data-h="约束类型">约束类型</th><th data-h="结论">结论</th><th data-h="风险等级">风险等级</th><th data-h="证据引用">证据引用</th><th data-h="AI置信度">AI 置信度</th></tr></thead>
|
||||
<tbody data-rows="mine:substitution.difference_item" data-by="substitution_relation_id"><tr>
|
||||
<td class="num"></td>
|
||||
<td class="cust" data-slot="parameter_name" data-blank></td>
|
||||
<td class="mono" data-slot="original_value" data-blank></td>
|
||||
<td class="mono" data-slot="candidate_value" data-blank></td>
|
||||
<td data-slot="parameter_unit" data-blank></td>
|
||||
<td><span class="con" data-class-of="constraint_type"></span></td>
|
||||
<td>${badge('st dst', 'difference_status')}</td>
|
||||
<td>${badge('risk', 'risk_level')}</td>
|
||||
<td class="mono" data-slot="evidence_ref" data-blank></td>
|
||||
<td class="mono" data-slot="confidence" data-blank></td>
|
||||
</tr></tbody>
|
||||
</table></div>
|
||||
</section></article>`;
|
||||
|
||||
export const DIFFERENCE_REVIEW = doc({
|
||||
css: ACC1_CSS,
|
||||
@@ -595,18 +649,18 @@ export const DIFFERENCE_REVIEW = doc({
|
||||
body:
|
||||
zone('AI 结论说明', '结论是怎么算出来的') +
|
||||
note([
|
||||
'<b>AI 已完成的计算</b>:按 GOV 评估规则(锁定版本 <b class="mono" data-slot="rule_version" data-blank></b>),对原 PN <b class="mono" data-slot="original_internal_pn" data-blank></b> 与每个候选逐项比对,产出四态结论——<b>MATCH / MISMATCH / UNKNOWN / CONDITIONAL</b>,并给出风险等级、证据引用与置信度。差异明细 = <b>P-11 差异明细子表</b>(一条参数差异一条记录);当前为 AI 草稿,<b>FAE 审核通过前不落账</b>。评估参数可能含本次数据工单创建的主数据(确认人背书;未附 datasheet 的参数项会显式标注「人工录入」)。',
|
||||
'<b>AI 已完成的计算</b>:按 GOV 评估规则(锁定版本 <b class="mono" data-slot="rule_version" data-blank></b>),以原 PN <b class="mono" data-slot="original_internal_pn" data-blank></b> 为基准,对 <b data-slot="substitution_relation_rows"></b> 个候选 PN 分别逐项比对,每项产出四态结论——<b>MATCH / MISMATCH / UNKNOWN / CONDITIONAL</b>,并给出风险等级、证据引用与置信度;再按候选汇总出下方的【候选 PN 结论汇总】(一个候选一条结论)。差异明细 = <b>P-11 差异明细子表</b>(一条参数差异一条记录,按候选分组);结论汇总 = <b>P-11 主表草稿</b>。当前均为 AI 草稿,<b>FAE 审核通过前不落账</b>。评估参数可能含本次数据工单创建的主数据(确认人背书;未附 datasheet 的参数项会显式标注「人工录入」)。',
|
||||
]) +
|
||||
criteria('判断这份差异评估结论是否可信,请逐项核对', [
|
||||
'<b>关键参数差异均有明确状态</b>:逐项结论无漏项,每个参数都有四态之一的判定;',
|
||||
'<b>汇总结论与明细一致</b>:结论表中每个候选的推荐程度 / 风险级别,与其下方差异明细表的四态分布吻合(存在 MISMATCH 硬约束或悬空 UNKNOWN 的候选不得给「推荐」);',
|
||||
'<b>关键参数差异均有明确状态</b>:每个候选的逐项结论无漏项,每个参数都有四态之一的判定;',
|
||||
'<b>UNKNOWN 项均有去向</b>:每个 UNKNOWN 都挂了验证任务或补来源动作,不允许悬空;',
|
||||
'<b>证据链完整</b>:每项结论可追溯至 P-08 / P-10 / P-06 的具体记录,或本单数据工单的创建记录(标注:人工录入);',
|
||||
'<b>硬约束项未被自动判 MATCH</b>:封装 / 工艺等硬约束未经证据支持不得判 MATCH。',
|
||||
'<b>证据链完整</b>:每项结论可追溯至 P-08 / P-10 / P-06 的具体记录,或本单数据工单的创建记录(标注:人工录入);硬约束项未经证据支持不得判 MATCH。',
|
||||
]) +
|
||||
zone('各候选推荐等级', '只读展示(P-11 主记录草稿,一个候选一条)') +
|
||||
zone('候选 PN 结论汇总', '每个候选一条结论,内容 = 对应下方明细表的汇总判定(P-11 主表草稿)') +
|
||||
RELATION_SUMMARY_TABLE +
|
||||
zone('AI 产出的差异明细', '只读展示(P-11 差异明细子表草稿 · 一条参数一条记录 difference_item_id)') +
|
||||
DIFFERENCE_ITEM_TABLE +
|
||||
zone('差异明细 · 按候选 PN 分组', '每个候选一张表,与原 PN 逐项对比(P-11 差异明细子表草稿 · 一条参数一条记录 difference_item_id)') +
|
||||
CANDIDATE_SECTIONS +
|
||||
flow(
|
||||
'<b>审批:</b>本工单只承载内容;「通过 / 驳回」请在对话区的【验收卡】中进行。审核意见与补充条件写入 P-06(验证要求 verification_requirement);<b>通过后去向:</b>进入步骤 5 · 评审放行与落账确认。',
|
||||
),
|
||||
|
||||
@@ -208,13 +208,22 @@ tr.ro td{background:var(--soft)}
|
||||
table.on td>.jc-vcell.ro{display:block}
|
||||
`;
|
||||
|
||||
/*
|
||||
* 两张验收件(ACC1 差异评估结论审核 / ACC2 评审放行与落账确认)的主题色**不再逐字节等于目标件**:
|
||||
* 目标件的题头用 #b23a2e 红(--ledger),2026-08-27 用户定「中央 HTML 模版区域如果是验收工单,
|
||||
* 标题部分的红色改为和验收卡一样的绿色」—— 与对话区验收卡同一枚 #0aa294(app.css --st-collab)。
|
||||
* 只换主题变量与题头渐变 / 徽章投影;ACC2 的 CONDITIONAL 状态徽标是语义色,保留原红。
|
||||
* ACC1 于 2026-08-27 下午随目标件改版整段重搬(「一个候选一张表」:.cand* / .rec* / .stat*,CONDITIONAL 改蓝),
|
||||
* 主题色仍取卡的那一枚绿。
|
||||
*/
|
||||
export const ACC1_CSS = `
|
||||
:root{
|
||||
--ink:#1f2329; --ink-2:#41464e; --ink-3:#646a73; --ink-4:#8f959e;
|
||||
--line:#dee0e3; --line-soft:#e8eaed; --soft:#f8f9fb;
|
||||
--brand:#3370ff; --brand-deep:#245bdb; --brand-soft:#e1eaff; --brand-wash:#f0f4ff;
|
||||
--ledger:#b23a2e; --ledger-soft:#f7e4e0; --ledger-line:#ecc5bd;
|
||||
--ledger:#0aa294; --ledger-soft:#e4f8f5; --ledger-line:#b5e6df; /* 验收绿(2026-08-27 用户定:与对话区验收卡同色;目标件 2026-08-27 改版写的是 #16a34a,这里取卡的那一枚) */
|
||||
--ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9;
|
||||
--amber:#8f6a12; --amber-soft:#fdf3d7; --amber-line:#ecd9a0;
|
||||
--mono:"SF Mono",Menlo,Consolas,monospace;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
@@ -222,8 +231,8 @@ html,body{margin:0;padding:0}
|
||||
body{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:#eef1f6;color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
|
||||
.page{margin:0;padding:0}
|
||||
.card{background:#fff;overflow:hidden;border:0;border-radius:0;box-shadow:none}
|
||||
.card-head{display:flex;align-items:center;gap:14px;padding:18px 22px;border-bottom:2px solid var(--ink);background:linear-gradient(120deg,#fdf3f1 0%,#fff 55%,#fbf2f0 100%)}
|
||||
.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--ledger);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(178,58,46,.25)}
|
||||
.card-head{display:flex;align-items:center;gap:14px;padding:18px 22px;border-bottom:2px solid var(--ink);background:linear-gradient(120deg,#eefaf8 0%,#fff 55%,#ecf8f5 100%)}
|
||||
.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--ledger);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(10,162,148,.25)}
|
||||
.tit{flex:1;min-width:0}
|
||||
.tit .kick{font-size:11px;letter-spacing:.08em;color:var(--ink-4);font-weight:700}
|
||||
.tit h1{margin:2px 0 0;font-size:19px;font-weight:800;line-height:1.3}
|
||||
@@ -249,27 +258,43 @@ table{width:100%;border-collapse:collapse;font-size:13px}
|
||||
th{text-align:left;background:var(--soft);font-size:11px;letter-spacing:.05em;font-weight:800;color:var(--ink-3);padding:9px 12px;border-bottom:1px solid var(--line)}
|
||||
td{padding:11px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top}
|
||||
tr:last-child td{border-bottom:0}
|
||||
.cand .tbl-wrap{border:0;border-radius:0}
|
||||
.num{font-family:var(--mono);color:var(--ink-4);white-space:nowrap}
|
||||
.cust{font-weight:700}
|
||||
.prio{font-family:var(--mono);font-weight:800}
|
||||
.prio.hi{color:var(--danger)}
|
||||
.prio.mid{color:var(--ink-2)}
|
||||
.reason{font-size:12.5px;color:var(--ink-2)}
|
||||
.flow{margin-top:16px;padding:9px 12px;border-radius:8px;background:var(--soft);border:1px dashed var(--line);font-size:12px;color:var(--ink-3)}
|
||||
.flow b{color:var(--ink)}
|
||||
.card-foot{padding:13px 22px;border-top:1px solid var(--line-soft);font-size:11.5px;color:var(--ink-4);display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px}
|
||||
@media(max-width:600px){.card-head{flex-wrap:wrap}.side{align-items:flex-start}}
|
||||
/* 补充:四态结论 pill 与风险等级(仅追加,不改动基件样式) */
|
||||
/* 四态结论 pill 与风险等级 */
|
||||
.st{display:inline-block;padding:1px 9px;border-radius:999px;font-size:11px;font-weight:800;letter-spacing:.04em;font-family:var(--mono);white-space:nowrap;border:1px solid transparent}
|
||||
.st.ok{color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4}
|
||||
.st.miss{color:var(--danger);background:var(--danger-soft);border-color:#f3b9b5}
|
||||
.st.unknown{color:#8f6a12;background:#fdf3d7;border-color:#ecd9a0}
|
||||
.st.cond{color:var(--ledger);background:var(--ledger-soft);border-color:var(--ledger-line)}
|
||||
.st.miss{color:var(--danger);background:#feeae9;border-color:#f3b9b5}
|
||||
.st.unknown{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.st.cond{color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft)}
|
||||
.risk{font-weight:800;font-size:12.5px}
|
||||
.risk.low{color:var(--ok)}
|
||||
.risk.mid{color:#8f6a12}
|
||||
.risk.mid{color:var(--amber)}
|
||||
.risk.hi{color:var(--danger)}
|
||||
.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
|
||||
/* 推荐程度 pill */
|
||||
.rec{display:inline-block;padding:2px 11px;border-radius:999px;font-size:11.5px;font-weight:800;white-space:nowrap;border:1px solid transparent}
|
||||
.rec.yes{color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4}
|
||||
.rec.cond{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.rec.no{color:var(--danger);background:#feeae9;border-color:#f3b9b5}
|
||||
/* 差异统计(结论表内) */
|
||||
.stat{font-family:var(--mono);font-size:11.5px;color:var(--ink-3);white-space:nowrap}
|
||||
.stat b{font-weight:800}
|
||||
.stat .m{color:var(--ok)} .stat .x{color:var(--danger)} .stat .u{color:var(--amber)} .stat .c{color:var(--brand-deep)}
|
||||
/* 候选 PN 明细块:一个候选一张表 */
|
||||
.cand{border:1px solid var(--line-soft);border-radius:10px;overflow:hidden;margin-bottom:16px}
|
||||
.cand:last-of-type{margin-bottom:0}
|
||||
.cand-head{display:flex;align-items:center;gap:10px;padding:11px 14px;background:linear-gradient(120deg,#f6f8fc 0%,#fff 70%);border-bottom:1px solid var(--line);flex-wrap:wrap}
|
||||
.cand-idx{flex:none;width:22px;height:22px;border-radius:6px;display:grid;place-items:center;background:var(--ink);color:#fff;font-size:11px;font-weight:800;font-family:var(--mono)}
|
||||
.cand-name{font-weight:800;font-size:14px}
|
||||
.cand-brand{color:var(--ink-3);font-size:12px}
|
||||
.cand-vs{font-family:var(--mono);font-size:11.5px;color:var(--ink-4)}
|
||||
.cand-con{margin-left:auto;display:flex;align-items:center;gap:8px}
|
||||
`;
|
||||
|
||||
export const ACC2_CSS = `
|
||||
@@ -277,7 +302,7 @@ export const ACC2_CSS = `
|
||||
--ink:#1f2329; --ink-2:#41464e; --ink-3:#646a73; --ink-4:#8f959e;
|
||||
--line:#dee0e3; --line-soft:#e8eaed; --soft:#f8f9fb;
|
||||
--brand:#3370ff; --brand-deep:#245bdb; --brand-soft:#e1eaff; --brand-wash:#f0f4ff;
|
||||
--ledger:#b23a2e; --ledger-soft:#f7e4e0; --ledger-line:#ecc5bd;
|
||||
--ledger:#0aa294; --ledger-soft:#e4f8f5; --ledger-line:#b5e6df; /* 验收绿(2026-08-27 用户定:与对话区验收卡同色,原目标件是 #b23a2e 红) */
|
||||
--ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9;
|
||||
--mono:"SF Mono",Menlo,Consolas,monospace;
|
||||
}
|
||||
@@ -286,8 +311,8 @@ html,body{margin:0;padding:0}
|
||||
body{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:#eef1f6;color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
|
||||
.page{margin:0;padding:0}
|
||||
.card{background:#fff;overflow:hidden;border:0;border-radius:0;box-shadow:none}
|
||||
.card-head{display:flex;align-items:center;gap:14px;padding:18px 22px;border-bottom:2px solid var(--ink);background:linear-gradient(120deg,#fdf3f1 0%,#fff 55%,#fbf2f0 100%)}
|
||||
.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--ledger);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(178,58,46,.25)}
|
||||
.card-head{display:flex;align-items:center;gap:14px;padding:18px 22px;border-bottom:2px solid var(--ink);background:linear-gradient(120deg,#eefaf8 0%,#fff 55%,#ecf8f5 100%)}
|
||||
.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--ledger);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(10,162,148,.25)}
|
||||
.tit{flex:1;min-width:0}
|
||||
.tit .kick{font-size:11px;letter-spacing:.08em;color:var(--ink-4);font-weight:700}
|
||||
.tit h1{margin:2px 0 0;font-size:19px;font-weight:800;line-height:1.3}
|
||||
@@ -328,7 +353,7 @@ tr:last-child td{border-bottom:0}
|
||||
.st.ok{color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4}
|
||||
.st.miss{color:var(--danger);background:var(--danger-soft);border-color:#f3b9b5}
|
||||
.st.unknown{color:#8f6a12;background:#fdf3d7;border-color:#ecd9a0}
|
||||
.st.cond{color:var(--ledger);background:var(--ledger-soft);border-color:var(--ledger-line)}
|
||||
.st.cond{color:#b23a2e;background:#f7e4e0;border-color:#ecc5bd}
|
||||
.risk{font-weight:800;font-size:12.5px}
|
||||
.risk.mid{color:#8f6a12}
|
||||
.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
|
||||
|
||||
@@ -235,6 +235,8 @@ P-11 一条(`LM2596S-3.3 → LM2596S-ADJ | alternate | fae_confirmed`);P-01 回
|
||||
| X | 两颗缺库只问了一次;`expectDecision` 只看张数,审核卡就把它喂饱 | 剧本「还有 absent → 写骨架再发卡」把「先问」压掉;断言太宽 | 剧本补「第二颗也要先问」;脚本新增 `expectAsks`(按问法数) | 活动 + 脚本 |
|
||||
| Y | 模型漏铺骨架 → 闸如实拦「一行都没有」→ 脚本只会填已有行,连吃 400 抛出 | 脚本没有「加一行」这条路,而人在浏览器里正是这么做的 | 主键齐了就加一行(与件上「加一行」同一条路) | 脚本 |
|
||||
| Z | 铺完骨架就标 `created`、直接 finish,撞「从没给它发过卡」连拒五拍 | 我 1.3.1 的措辞「表里真有一行才标 created」—— 而骨架是模型自己铺的 | 「created 认的是卡交回来了」;顺序写死:骨架 → 发卡 → 拍结束 → 人交回 → 才标 | 活动 |
|
||||
| AB | **库里有值的参数被 S1 清单当成缺口再问一遍**(三次复现):人在 P-08 填了使能阈值 2.5,清单上仍有「使能阈值 · 原厂未披露」;第三次连数据工单都没派(料号已在库、21 个参数全有值)照样出现 | S1 的「待确认」行是模型对参数表的断言,基座无读数核它;说明书里「使能阈值」与「未披露」同句三处(含 1.4.10 我写的反例原话);S-FEEL 无列表过滤写不出判据 | S1 一行参数都不写;件上加「候选参数现值」只读块(嵌套 `data-by` 现读台账);未披露归 S3 判 UNKNOWN;说明书全文去掉「使能阈值」 | 活动(结构)+ 平台(渲染器嵌套行) |
|
||||
| AA | **数据工单确认了,数据没入库**:卡上写着「确认后这批主数据即入库」,人建好的 P-08/P-10 记录要等整条评估放行才进正式表;试跑单(不落主数据)永远不进(2026-08-27 用户指出) | 草稿层通往正式表只有整单放行一道口子(`releaseWrite(taskId)`),回传路由只记办结 + 抛人事件;而引擎的 `mine:` / `_rows` / 哨兵全靠草稿层认「本单写下的行」,清掉就断 | `releaseWrite(taskId, {only, cause})` 范围放行:只并这张卡 `gateLedgers` 那几张表,并过的行**留在草稿层打 `landed` 记号**(读面不变,整单放行不再写);回传路由在保存与回传落定后调它,痕点名几张表各几行;`createOnly` / `drop` 对已落地行改口(别 drop,撤了读面少一行);活动 1.4.8 剧本改口「已入正式表」 | **平台**(结构)+ 活动 |
|
||||
|
||||
**可推广的三条**(已记 `docs/debt.md`):
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
--ink:#1f2329; --ink-2:#41464e; --ink-3:#646a73; --ink-4:#8f959e;
|
||||
--line:#dee0e3; --line-soft:#e8eaed; --soft:#f8f9fb;
|
||||
--brand:#3370ff; --brand-deep:#245bdb; --brand-soft:#e1eaff; --brand-wash:#f0f4ff;
|
||||
--ledger:#b23a2e; --ledger-soft:#f7e4e0; --ledger-line:#ecc5bd;
|
||||
--ledger:#16a34a; --ledger-soft:#e6f6ec; --ledger-line:#b7e5c6;
|
||||
--ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9;
|
||||
--amber:#8f6a12; --amber-soft:#fdf3d7; --amber-line:#ecd9a0;
|
||||
--mono:"SF Mono",Menlo,Consolas,monospace;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
@@ -18,8 +19,8 @@ html,body{margin:0;padding:0}
|
||||
body{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:#eef1f6;color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
|
||||
.page{margin:0;padding:0}
|
||||
.card{background:#fff;overflow:hidden;border:0;border-radius:0;box-shadow:none}
|
||||
.card-head{display:flex;align-items:center;gap:14px;padding:18px 22px;border-bottom:2px solid var(--ink);background:linear-gradient(120deg,#fdf3f1 0%,#fff 55%,#fbf2f0 100%)}
|
||||
.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--ledger);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(178,58,46,.25)}
|
||||
.card-head{display:flex;align-items:center;gap:14px;padding:18px 22px;border-bottom:2px solid var(--ink);background:linear-gradient(120deg,#f0faf3 0%,#fff 55%,#ecf7f0 100%)}
|
||||
.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--ledger);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(22,163,74,.28)}
|
||||
.tit{flex:1;min-width:0}
|
||||
.tit .kick{font-size:11px;letter-spacing:.08em;color:var(--ink-4);font-weight:700}
|
||||
.tit h1{margin:2px 0 0;font-size:19px;font-weight:800;line-height:1.3}
|
||||
@@ -45,27 +46,43 @@ table{width:100%;border-collapse:collapse;font-size:13px}
|
||||
th{text-align:left;background:var(--soft);font-size:11px;letter-spacing:.05em;font-weight:800;color:var(--ink-3);padding:9px 12px;border-bottom:1px solid var(--line)}
|
||||
td{padding:11px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top}
|
||||
tr:last-child td{border-bottom:0}
|
||||
.cand .tbl-wrap{border:0;border-radius:0}
|
||||
.num{font-family:var(--mono);color:var(--ink-4);white-space:nowrap}
|
||||
.cust{font-weight:700}
|
||||
.prio{font-family:var(--mono);font-weight:800}
|
||||
.prio.hi{color:var(--danger)}
|
||||
.prio.mid{color:var(--ink-2)}
|
||||
.reason{font-size:12.5px;color:var(--ink-2)}
|
||||
.flow{margin-top:16px;padding:9px 12px;border-radius:8px;background:var(--soft);border:1px dashed var(--line);font-size:12px;color:var(--ink-3)}
|
||||
.flow b{color:var(--ink)}
|
||||
.card-foot{padding:13px 22px;border-top:1px solid var(--line-soft);font-size:11.5px;color:var(--ink-4);display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px}
|
||||
@media(max-width:600px){.card-head{flex-wrap:wrap}.side{align-items:flex-start}}
|
||||
/* 补充:四态结论 pill 与风险等级(仅追加,不改动基件样式) */
|
||||
/* 四态结论 pill 与风险等级 */
|
||||
.st{display:inline-block;padding:1px 9px;border-radius:999px;font-size:11px;font-weight:800;letter-spacing:.04em;font-family:var(--mono);white-space:nowrap;border:1px solid transparent}
|
||||
.st.ok{color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4}
|
||||
.st.miss{color:var(--danger);background:var(--danger-soft);border-color:#f3b9b5}
|
||||
.st.unknown{color:#8f6a12;background:#fdf3d7;border-color:#ecd9a0}
|
||||
.st.cond{color:var(--ledger);background:var(--ledger-soft);border-color:var(--ledger-line)}
|
||||
.st.miss{color:var(--danger);background:#feeae9;border-color:#f3b9b5}
|
||||
.st.unknown{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.st.cond{color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft)}
|
||||
.risk{font-weight:800;font-size:12.5px}
|
||||
.risk.low{color:var(--ok)}
|
||||
.risk.mid{color:#8f6a12}
|
||||
.risk.mid{color:var(--amber)}
|
||||
.risk.hi{color:var(--danger)}
|
||||
.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
|
||||
/* 推荐程度 pill */
|
||||
.rec{display:inline-block;padding:2px 11px;border-radius:999px;font-size:11.5px;font-weight:800;white-space:nowrap;border:1px solid transparent}
|
||||
.rec.yes{color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4}
|
||||
.rec.cond{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.rec.no{color:var(--danger);background:#feeae9;border-color:#f3b9b5}
|
||||
/* 差异统计(结论表内) */
|
||||
.stat{font-family:var(--mono);font-size:11.5px;color:var(--ink-3);white-space:nowrap}
|
||||
.stat b{font-weight:800}
|
||||
.stat .m{color:var(--ok)} .stat .x{color:var(--danger)} .stat .u{color:var(--amber)} .stat .c{color:var(--brand-deep)}
|
||||
/* 候选 PN 明细块:一个候选一张表 */
|
||||
.cand{border:1px solid var(--line-soft);border-radius:10px;overflow:hidden;margin-bottom:16px}
|
||||
.cand:last-of-type{margin-bottom:0}
|
||||
.cand-head{display:flex;align-items:center;gap:10px;padding:11px 14px;background:linear-gradient(120deg,#f6f8fc 0%,#fff 70%);border-bottom:1px solid var(--line);flex-wrap:wrap}
|
||||
.cand-idx{flex:none;width:22px;height:22px;border-radius:6px;display:grid;place-items:center;background:var(--ink);color:#fff;font-size:11px;font-weight:800;font-family:var(--mono)}
|
||||
.cand-name{font-weight:800;font-size:14px}
|
||||
.cand-brand{color:var(--ink-3);font-size:12px}
|
||||
.cand-vs{font-family:var(--mono);font-size:11.5px;color:var(--ink-4)}
|
||||
.cand-con{margin-left:auto;display:flex;align-items:center;gap:8px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -90,113 +107,275 @@ tr:last-child td{border-bottom:0}
|
||||
|
||||
<p class="zone"><b>【AI 结论说明】</b>—— 结论是怎么算出来的</p>
|
||||
<div class="note">
|
||||
<p><b>AI 已完成的计算</b>:按 GOV 评估规则(锁定版本 <b>R-2026.07</b>,rule_version),对 Original=<b>LM2596S-5.0(TI)</b> / Candidate=<b>XL2596S-5.0(XLSEMI)</b> 逐项比对,产出四态结论——<b>MATCH / MISMATCH / UNKNOWN / CONDITIONAL</b>,并给出风险等级、证据引用与置信度。差异明细 = <b>P-11 差异明细子表</b>(一条参数差异一条记录,difference_item_id);当前为 AI 草稿,<b>FAE 审核通过前不落账</b>。评估参数可能含本次数据工单创建的主数据(确认人背书;未附 datasheet 的参数项会显式标注「人工录入」)。</p>
|
||||
<p><b>AI 已完成的计算</b>:按 GOV 评估规则(锁定版本 <b>R-2026.07</b>,rule_version),以 Original=<b>LM2596S-5.0(TI)</b> 为基准,对 <b data-slot="out.candidate_count">2</b> 个候选 PN 分别逐项比对,每项产出四态结论——<b>MATCH / MISMATCH / UNKNOWN / CONDITIONAL</b>,并给出风险等级、证据引用与置信度;再按候选汇总出下方的【候选 PN 结论汇总】(一个候选一条结论)。差异明细 = <b>P-11 差异明细子表</b>(一条参数差异一条记录,difference_item_id,按 candidate_pn 分组);结论汇总 = <b>P-11 主表草稿</b>。当前均为 AI 草稿,<b>FAE 审核通过前不落账</b>。评估参数可能含本次数据工单创建的主数据(确认人背书;未附 datasheet 的参数项会显式标注「人工录入」)。</p>
|
||||
</div>
|
||||
|
||||
<p class="zone"><b>【验收判据】</b>—— 你据此判断「通过 / 驳回」</p>
|
||||
<div class="criteria">
|
||||
<div class="c-title">判断这份差异评估结论是否可信,请逐项核对</div>
|
||||
<ul>
|
||||
<li><b>关键参数差异均有明确状态</b>:逐项结论无漏项,每个参数都有四态之一的判定;</li>
|
||||
<li><b>汇总结论与明细一致</b>:结论表中每个候选的推荐程度 / 风险级别,与其下方差异明细表的四态分布吻合(存在 MISMATCH 硬约束或悬空 UNKNOWN 的候选不得给「推荐」);</li>
|
||||
<li><b>关键参数差异均有明确状态</b>:每个候选的逐项结论无漏项,每个参数都有四态之一的判定;</li>
|
||||
<li><b>UNKNOWN 项均有去向</b>:每个 UNKNOWN 都挂了验证任务(如 VAL-2026-0188)或补来源动作,不允许悬空;</li>
|
||||
<li><b>证据链完整</b>:每项结论可追溯至 P-08 / P-10 / P-06 或 EXT-02 的具体记录,或追溯至数据工单创建记录(标注:人工录入 · 数据工单号 · 确认人);</li>
|
||||
<li><b>硬约束项未被自动判 MATCH</b>:封装 / 工艺等硬约束未经证据支持不得判 MATCH。</li>
|
||||
<li><b>证据链完整</b>:每项结论可追溯至 P-08 / P-10 / P-06 或 EXT-02 的具体记录,或追溯至数据工单创建记录(标注:人工录入 · 数据工单号 · 确认人);硬约束项未经证据支持不得判 MATCH。</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="zone"><b>【AI 产出的差异明细】</b>—— 只读展示(P-11 差异明细子表草稿 · 一条参数一条记录 difference_item_id)</p>
|
||||
<div class="tbl-wrap">
|
||||
<p class="zone"><b>【候选 PN 结论汇总】</b>—— 每个候选一条结论,内容 = 对应下方明细表的汇总判定(P-11 主表草稿)</p>
|
||||
<div class="tbl-wrap" style="margin-bottom:20px">
|
||||
<table>
|
||||
<thead><tr><th style="width:40px">#</th><th data-h="参数项 parameter_name">参数项 parameter_name</th><th data-h="原PN值 original_value">原 PN 值 original_value</th><th data-h="候选PN值 candidate_value">候选 PN 值 candidate_value</th><th data-h="单位 parameter_unit">单位 parameter_unit</th><th data-h="约束类型 constraint_type">约束类型 constraint_type</th><th data-h="结论 difference_status">结论 difference_status</th><th data-h="风险等级">风险等级</th><th data-h="证据引用 evidence_ref">证据引用 evidence_ref</th><th data-h="AI置信度">AI 置信度</th></tr></thead>
|
||||
<tbody data-rows="out.difference_items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">#</th>
|
||||
<th data-h="候选PN candidate_pn">候选 PN</th>
|
||||
<th data-h="品牌 brand_name">品牌</th>
|
||||
<th data-h="推荐程度 recommendation">推荐程度</th>
|
||||
<th data-h="风险级别 risk_level">风险级别</th>
|
||||
<th data-h="差异统计 diff_stats">差异统计(四态)</th>
|
||||
<th data-h="结论摘要 conclusion_summary">结论摘要</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-rows="out.candidate_conclusions">
|
||||
<tr>
|
||||
<td class="num">1</td>
|
||||
<td data-field="parameter_name" class="cust">输出电压</td>
|
||||
<td data-field="original_value" class="mono">5.0</td>
|
||||
<td data-field="candidate_value" class="mono">5.0</td>
|
||||
<td data-field="parameter_unit">V</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.98</td>
|
||||
<td data-field="candidate_pn" class="cust">XL2596S-5.0</td>
|
||||
<td data-field="brand_name">XLSEMI 芯龙</td>
|
||||
<td data-field="recommendation"><span class="rec cond">有条件推荐</span></td>
|
||||
<td data-field="risk_level"><span class="risk mid">中</span></td>
|
||||
<td data-field="diff_stats" class="stat"><b class="m">一致 4</b> · <b class="x">差异 1</b> · <b class="u">未知 1</b> · <b class="c">附条件 1</b></td>
|
||||
<td data-field="conclusion_summary" class="reason">电气主参数一致、工作温度覆盖更宽;使能阈值未披露需挂验证,生命周期凭供货承诺函附条件通过。</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">2</td>
|
||||
<td data-field="parameter_name" class="cust">输出电流</td>
|
||||
<td data-field="original_value" class="mono">3</td>
|
||||
<td data-field="candidate_value" class="mono">3</td>
|
||||
<td data-field="parameter_unit">A</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.97</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">3</td>
|
||||
<td data-field="parameter_name" class="cust">开关频率</td>
|
||||
<td data-field="original_value" class="mono">150</td>
|
||||
<td data-field="candidate_value" class="mono">150</td>
|
||||
<td data-field="parameter_unit">kHz</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.95</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">4</td>
|
||||
<td data-field="parameter_name" class="cust">封装</td>
|
||||
<td data-field="original_value" class="mono">TO-263-5</td>
|
||||
<td data-field="candidate_value" class="mono">TO-263-5</td>
|
||||
<td data-field="parameter_unit">—</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.99</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">5</td>
|
||||
<td data-field="parameter_name" class="cust">工作温度</td>
|
||||
<td data-field="original_value" class="mono">-40~+85</td>
|
||||
<td data-field="candidate_value" class="mono">-40~+125</td>
|
||||
<td data-field="parameter_unit">℃</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st miss">MISMATCH</span></td>
|
||||
<td data-field="candidate_pn" class="cust">AP1501A-5.0</td>
|
||||
<td data-field="brand_name">Diodes</td>
|
||||
<td data-field="recommendation"><span class="rec no">不推荐</span></td>
|
||||
<td data-field="risk_level"><span class="risk hi">高</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-10</td>
|
||||
<td data-field="confidence" class="mono">0.93</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">6</td>
|
||||
<td data-field="parameter_name" class="cust">使能阈值</td>
|
||||
<td data-field="original_value" class="mono">1.4</td>
|
||||
<td data-field="candidate_value" class="mono">未披露</td>
|
||||
<td data-field="parameter_unit">V</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st unknown">UNKNOWN</span></td>
|
||||
<td data-field="risk_level"><span class="risk mid">中</span></td>
|
||||
<td data-field="evidence_ref" class="mono">挂 VAL-2026-0188</td>
|
||||
<td data-field="confidence" class="mono">—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">7</td>
|
||||
<td data-field="parameter_name" class="cust">生命周期</td>
|
||||
<td data-field="original_value" class="mono">Active</td>
|
||||
<td data-field="candidate_value" class="mono">Active</td>
|
||||
<td data-field="parameter_unit">—</td>
|
||||
<td data-field="constraint_type">软约束</td>
|
||||
<td data-field="difference_status"><span class="st cond">CONDITIONAL</span></td>
|
||||
<td data-field="risk_level"><span class="risk mid">中</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-10(候选供货承诺函)</td>
|
||||
<td data-field="confidence" class="mono">0.90</td>
|
||||
<td data-field="diff_stats" class="stat"><b class="m">一致 3</b> · <b class="x">差异 2</b> · <b class="u">未知 1</b></td>
|
||||
<td data-field="conclusion_summary" class="reason">使能逻辑与原设计相反,替换需改原理图;静态电流偏高。替换代价大于收益。</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p class="zone"><b>【差异明细 · 按候选 PN 分组】</b>—— 每个候选一张表,与原 PN 逐项对比(P-11 差异明细子表草稿 · 一条参数一条记录 difference_item_id)</p>
|
||||
|
||||
<section class="cand" data-candidate="XL2596S-5.0">
|
||||
<div class="cand-head">
|
||||
<span class="cand-idx">1</span>
|
||||
<span class="cand-name" data-field="candidate_pn">XL2596S-5.0</span>
|
||||
<span class="cand-brand" data-field="brand_name">XLSEMI 芯龙</span>
|
||||
<span class="cand-vs">vs 原 PN · LM2596S-5.0(TI)</span>
|
||||
<span class="cand-con"><span class="rec cond" data-field="recommendation">有条件推荐</span><span class="risk mid" data-field="risk_level">风险 中</span></span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">#</th>
|
||||
<th data-h="参数项 parameter_name">参数项</th>
|
||||
<th data-h="原PN值 original_value">原 PN 值</th>
|
||||
<th data-h="候选PN值 candidate_value">候选 PN 值</th>
|
||||
<th data-h="单位 parameter_unit">单位</th>
|
||||
<th data-h="约束类型 constraint_type">约束类型</th>
|
||||
<th data-h="结论 difference_status">结论</th>
|
||||
<th data-h="风险等级">风险等级</th>
|
||||
<th data-h="证据引用 evidence_ref">证据引用</th>
|
||||
<th data-h="AI置信度">AI 置信度</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-rows="out.difference_items">
|
||||
<tr>
|
||||
<td class="num">1</td>
|
||||
<td data-field="parameter_name" class="cust">输出电压</td>
|
||||
<td data-field="original_value" class="mono">5.0</td>
|
||||
<td data-field="candidate_value" class="mono">5.0</td>
|
||||
<td data-field="parameter_unit">V</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.98</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">2</td>
|
||||
<td data-field="parameter_name" class="cust">输出电流</td>
|
||||
<td data-field="original_value" class="mono">3</td>
|
||||
<td data-field="candidate_value" class="mono">3</td>
|
||||
<td data-field="parameter_unit">A</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.97</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">3</td>
|
||||
<td data-field="parameter_name" class="cust">开关频率</td>
|
||||
<td data-field="original_value" class="mono">150</td>
|
||||
<td data-field="candidate_value" class="mono">150</td>
|
||||
<td data-field="parameter_unit">kHz</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.95</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">4</td>
|
||||
<td data-field="parameter_name" class="cust">封装</td>
|
||||
<td data-field="original_value" class="mono">TO-263-5</td>
|
||||
<td data-field="candidate_value" class="mono">TO-263-5</td>
|
||||
<td data-field="parameter_unit">—</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.99</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">5</td>
|
||||
<td data-field="parameter_name" class="cust">工作温度</td>
|
||||
<td data-field="original_value" class="mono">-40~+85</td>
|
||||
<td data-field="candidate_value" class="mono">-40~+125</td>
|
||||
<td data-field="parameter_unit">℃</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st miss">MISMATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk hi">高</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-10</td>
|
||||
<td data-field="confidence" class="mono">0.93</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">6</td>
|
||||
<td data-field="parameter_name" class="cust">使能阈值</td>
|
||||
<td data-field="original_value" class="mono">1.4</td>
|
||||
<td data-field="candidate_value" class="mono">未披露</td>
|
||||
<td data-field="parameter_unit">V</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st unknown">UNKNOWN</span></td>
|
||||
<td data-field="risk_level"><span class="risk mid">中</span></td>
|
||||
<td data-field="evidence_ref" class="mono">挂 VAL-2026-0188</td>
|
||||
<td data-field="confidence" class="mono">—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">7</td>
|
||||
<td data-field="parameter_name" class="cust">生命周期</td>
|
||||
<td data-field="original_value" class="mono">Active</td>
|
||||
<td data-field="candidate_value" class="mono">Active</td>
|
||||
<td data-field="parameter_unit">—</td>
|
||||
<td data-field="constraint_type">软约束</td>
|
||||
<td data-field="difference_status"><span class="st cond">CONDITIONAL</span></td>
|
||||
<td data-field="risk_level"><span class="risk mid">中</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-10(候选供货承诺函)</td>
|
||||
<td data-field="confidence" class="mono">0.90</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cand" data-candidate="AP1501A-5.0">
|
||||
<div class="cand-head">
|
||||
<span class="cand-idx">2</span>
|
||||
<span class="cand-name" data-field="candidate_pn">AP1501A-5.0</span>
|
||||
<span class="cand-brand" data-field="brand_name">Diodes</span>
|
||||
<span class="cand-vs">vs 原 PN · LM2596S-5.0(TI)</span>
|
||||
<span class="cand-con"><span class="rec no" data-field="recommendation">不推荐</span><span class="risk hi" data-field="risk_level">风险 高</span></span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">#</th>
|
||||
<th data-h="参数项 parameter_name">参数项</th>
|
||||
<th data-h="原PN值 original_value">原 PN 值</th>
|
||||
<th data-h="候选PN值 candidate_value">候选 PN 值</th>
|
||||
<th data-h="单位 parameter_unit">单位</th>
|
||||
<th data-h="约束类型 constraint_type">约束类型</th>
|
||||
<th data-h="结论 difference_status">结论</th>
|
||||
<th data-h="风险等级">风险等级</th>
|
||||
<th data-h="证据引用 evidence_ref">证据引用</th>
|
||||
<th data-h="AI置信度">AI 置信度</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-rows="out.difference_items">
|
||||
<tr>
|
||||
<td class="num">1</td>
|
||||
<td data-field="parameter_name" class="cust">输出电压</td>
|
||||
<td data-field="original_value" class="mono">5.0</td>
|
||||
<td data-field="candidate_value" class="mono">5.0</td>
|
||||
<td data-field="parameter_unit">V</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.98</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">2</td>
|
||||
<td data-field="parameter_name" class="cust">输出电流</td>
|
||||
<td data-field="original_value" class="mono">3</td>
|
||||
<td data-field="candidate_value" class="mono">3</td>
|
||||
<td data-field="parameter_unit">A</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.96</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">3</td>
|
||||
<td data-field="parameter_name" class="cust">开关频率</td>
|
||||
<td data-field="original_value" class="mono">150</td>
|
||||
<td data-field="candidate_value" class="mono">150</td>
|
||||
<td data-field="parameter_unit">kHz</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st ok">MATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk low">低</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-08 · P-10</td>
|
||||
<td data-field="confidence" class="mono">0.94</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">4</td>
|
||||
<td data-field="parameter_name" class="cust">使能逻辑</td>
|
||||
<td data-field="original_value" class="mono">高电平有效</td>
|
||||
<td data-field="candidate_value" class="mono">低电平有效</td>
|
||||
<td data-field="parameter_unit">—</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st miss">MISMATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk hi">高</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-10</td>
|
||||
<td data-field="confidence" class="mono">0.92</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">5</td>
|
||||
<td data-field="parameter_name" class="cust">静态电流</td>
|
||||
<td data-field="original_value" class="mono">10</td>
|
||||
<td data-field="candidate_value" class="mono">20</td>
|
||||
<td data-field="parameter_unit">mA</td>
|
||||
<td data-field="constraint_type">软约束</td>
|
||||
<td data-field="difference_status"><span class="st miss">MISMATCH</span></td>
|
||||
<td data-field="risk_level"><span class="risk mid">中</span></td>
|
||||
<td data-field="evidence_ref" class="mono">P-10</td>
|
||||
<td data-field="confidence" class="mono">0.90</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="num">6</td>
|
||||
<td data-field="parameter_name" class="cust">使能阈值</td>
|
||||
<td data-field="original_value" class="mono">1.4</td>
|
||||
<td data-field="candidate_value" class="mono">未披露</td>
|
||||
<td data-field="parameter_unit">V</td>
|
||||
<td data-field="constraint_type">硬约束</td>
|
||||
<td data-field="difference_status"><span class="st unknown">UNKNOWN</span></td>
|
||||
<td data-field="risk_level"><span class="risk mid">中</span></td>
|
||||
<td data-field="evidence_ref" class="mono">挂 VAL-2026-0189</td>
|
||||
<td data-field="confidence" class="mono">—</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="flow"><b>审批:</b>本工单只承载内容;「通过 / 驳回」请在对话区的【验收卡】中进行。审核意见与补充条件写入 P-06(验证要求 verification_requirement);<b>通过后去向:</b>进入步骤 5 · 评审放行与落账确认。</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# ACT-WORK-05 关键台账数据看板 · 数据溯源说明
|
||||
|
||||
对应页面:`ACT-WORK-05-关键台账数据.html`
|
||||
|
||||
本文档逐项说明看板中**每一个数据的取值来源**。来源分两类:
|
||||
|
||||
- **直读**:取自台账数据文件(Excel),逐字段一一对应;
|
||||
- **推导**:该台账暂无独立数据文件,由 P-08 / P-06 记录中的引用关系、参数集比对或活动流程规则推导得出,用于演示(页面图例中的琥珀色点)。
|
||||
|
||||
## 数据来源文件
|
||||
|
||||
| 来源 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| P-08 数据文件 | `activity/SS02-需求分析与方案匹配/P-08-芯片主数据台账-模拟数据V0.1.xlsx`(sheet「字段总表」,共 20 条) | 直读 |
|
||||
| P-06 数据文件 | `activity/SS02-需求分析与方案匹配/P-06-样品验证记录台账-模拟数据V0.1.xlsx`(sheet「字段总表」,共 20 条) | 直读 |
|
||||
| 字段口径 | `SS02-SS03-SS04_Demo台账字段细化与统一方案.md` | 台账字段定义依据 |
|
||||
| 活动逻辑 | `ACT-WORK-05-活动流程与工单说明.md`、`activity/SS02-需求分析与方案匹配/SS02_ACT-WORK-05_差异评估_E04-I01架构版_V1.2.html` | 推导规则依据 |
|
||||
|
||||
---
|
||||
|
||||
## 一、页头(mast)
|
||||
|
||||
| 看板上的值 | 来源 | 取值说明 |
|
||||
|---|---|---|
|
||||
| REQ-20260826-001 | 直读 | P-06 文件,记录 P06-0001(VAL-2026-0188)的 `request_id` 字段 |
|
||||
| CUS-2025-0007 | 直读 | P-06 文件 P06-0001 的 `customer_id` 字段 |
|
||||
| PRJ-PSU-40V | 直读 | P-06 文件 P06-0001 的 `project_id` 字段 |
|
||||
| LM2596S-5.0(TI)/ XL2596S-5.0(XLSEMI)/ LM2596S-ADJ(TI) | 直读 | P-08 文件记录 P08-0001 / P08-0002 / P08-0003 的 `internal_pn` + `brand_name` 字段 |
|
||||
| 规则版本 R-2026.07 | 推导 | GOV 评估规则库在本次运行锁定的版本号,演示设定值(GOV 为系统级台账,无数据文件) |
|
||||
|
||||
## 二、重要性分层条(5 张分层卡)
|
||||
|
||||
5 张卡片的台账编号、名称、角色描述(核心输入/核心产出/证据链/闭环去向/上下文)均来自《Demo台账字段细化与统一方案.md》中各台账的定义,以及《ACT-WORK-05-活动流程与工单说明.md》中本活动对各台账的读写关系(P-08 查无硬阻塞、P-11 落账、P-10 证据、P-06 收口、P-01 回写)。**推导**(角色定位描述,非台账数据)。
|
||||
|
||||
## 三、P-01 客户需求主台账(KV 卡,标注「回链推导 · 1 条」)
|
||||
|
||||
P-01 无数据文件,整条记录为推导展示:
|
||||
|
||||
| 看板字段 | 值 | 来源 |
|
||||
|---|---|---|
|
||||
| 需求编号 | REQ-20260826-001 | 直读链:P-06 P06-0001.`request_id` |
|
||||
| 客户 | CUS-2025-0007 | 直读链:P-06 P06-0001.`customer_id` |
|
||||
| 项目 | PRJ-PSU-40V | 直读链:P-06 P06-0001.`project_id` |
|
||||
| 需求版本 | V1(启动新建) | 推导:活动「一键启动」规则——口述需求无 request_id 时启动新建 V1 |
|
||||
| 需求描述 | 工业电源 12V→5V 电源位替代:原 LM2596S-5.0(NRND,PCN-2025-118 通知 2027-03 停产) | 推导:由 P-08 P08-0001.`lifecycle_status`/`eol_pcn_status` + P-06 P06-0001.`test_condition`(U3 电源位、12V 输入)拼装 |
|
||||
| 应用场景 | 12V/24V/40V 输入三档 · 0.5A~3A 负载 · 工业温域 | 推导:P-06 P06-0001.`test_condition`(输入三档、负载三档)+ P-08 P08-0001.`application_scenarios`(工业电源) |
|
||||
| BOM 位 | U3 电源位 | 直读链:P-06 P06-0001.`test_condition`「12V→5V 电源位(U3)」 |
|
||||
| 原内部料号 | LM2596S-5.0 | 直读链:P-08 P08-0001.`internal_pn` |
|
||||
| 候选内部料号 | XL2596S-5.0 · LM2596S-ADJ | 直读链:P-08 P08-0002/P08-0003.`internal_pn` |
|
||||
| 风险等级(回写) | 中 | 推导:P-11-SUB-0001 风险等级(见下),活动结束回写 P-01 |
|
||||
| 验证要求(回写) | VAL-2026-0188 | 直读链:P-06 P06-0001.`validation_id`,由其 `next_validation_action`「回链 P-11-SUB-0001」挂接 |
|
||||
| 当前阶段 | 提交 ACT-GATE-03 | 推导:活动流程——验收工单02 放行后进入 GATE-03 评审 |
|
||||
| 下一步动作 | 提交 ACT-GATE-03 评审放行(FAE · 李工 · 1 个工作日) | 推导:活动流程 SLA;「李工」直读链自 P-08/P-06 的 `data_owner`=FAE·李工 |
|
||||
|
||||
## 四、P-08 芯片主数据台账(表,标注「数据文件直读 · 3 条」)
|
||||
|
||||
三行分别对应 P-08 文件的记录 **P08-0001 / P08-0002 / P08-0003**,全部为直读。列与字段映射:
|
||||
|
||||
| 看板列 | P-08 字段 | 备注 |
|
||||
|---|---|---|
|
||||
| 内部料号(如 LM2596S-5.0) | `internal_pn` | 第二行小字「P08-0001 · v3」= `record_id` + `record_version` |
|
||||
| 品牌 / 制造商 | `brand_name` / `manufacturer_name` | |
|
||||
| 规格描述 | `specification_description` | 页面做了截短展示(如 P08-0001 原文末尾「开关频率,TO-263-5 封装」未显示,封装已单列) |
|
||||
| 封装 / 工艺 | `package` / `process_technology` | 三条均为 TO-263-5 / BCD |
|
||||
| 生命周期 | `lifecycle_status` + `eol_pcn_status` | P08-0001=NRND +「PCN-2025-118 已通知,2027-03 停止供货」;另两条 Active |
|
||||
| Datasheet | `datasheet_version` | Rev H(2023-09)/ Rev C(2025-06)/ Rev H(2023-09) |
|
||||
| 标准化参数集(8 项 chips) | `normalized_parameter_set`(JSON) | 8 个瓷贴 = JSON 里 8 个参数逐项直读:输入电压范围/输出电压/输出电流/开关频率/静态电流/工作温度/使能阈值/反馈网络。P08-0002 的「EN 阈值 未披露」即 JSON 原值「未披露」 |
|
||||
| 适配场景 | `application_scenarios` | |
|
||||
|
||||
参数集版本「v2026-08」(差异明细表证据列中引用)= JSON 内「参数集版本」字段。
|
||||
|
||||
## 五、P-11 替代选型与批准关系库(标注「回链推导 · 2 条」+ 差异明细 6 条)
|
||||
|
||||
P-11 无数据文件。主记录 2 条:
|
||||
|
||||
| 看板字段 | P11-SUB-0001 的值 | P11-SUB-0002 的值 | 来源 |
|
||||
|---|---|---|---|
|
||||
| 替代关系 ID | P11-SUB-0001 | P11-SUB-0002 | 直读链:P08-0001/0002.`pin_to_pin_relation_ref`=P11-SUB-0001;P08-0003.=P11-SUB-0002 |
|
||||
| 原 → 候选 | LM2596S-5.0 → XL2596S-5.0 | LM2596S-5.0 → LM2596S-ADJ | 推导:由 P-08 记录的三方引用关系确定 |
|
||||
| 替代类型 | Pin-to-Pin | 功能替代 | 直读链:P-06 P06-0001.`validation_type`=Pin-to-Pin;ADJ 需改反馈网络,按规则判为功能替代 |
|
||||
| 推荐等级 | 条件推荐 | 备选 | 直读链:P06-0001.`next_validation_action`「未闭环前维持**条件推荐**」;P06-0017(VAL-2026-0040).`next_validation_action`「作为**备选**结论回链 P-11-SUB-0002」 |
|
||||
| 分析状态 | FAE确认 | FAE确认 | 推导:流程状态——差异评估已完成、待 GATE-03,FAE=李工(data_owner) |
|
||||
| 风险 | 中 | 低 | 直读链:P06-0001.`issue_risk`「…风险=中」;P06-0017.`issue_risk`「…风险=低」 |
|
||||
| 验证要求 / 回链 | VAL-2026-0188(使能阈值实测,进行中) | VAL-2026-0040(条件通过:外部分压精度 ±2.1%) | 直读链:两条 P-06 记录的 `validation_id` / `validation_status` / `test_result` |
|
||||
| 规则版本 | R-2026.07 | R-2026.07 | 推导:演示锁定的 GOV 规则版本 |
|
||||
| 客户批准(只读) | 未提交 | 未提交 | 推导:流程未走到客户批准节点 |
|
||||
|
||||
差异明细子表 6 条(非 MATCH 项),由双方 P-08 `normalized_parameter_set` 逐项比对**推导**得出:
|
||||
|
||||
| 所属 | 参数项 | 原值 → 候选值 | 结论/风险 | 证据引用 | 取值来源 |
|
||||
|---|---|---|---|---|---|
|
||||
| SUB-0001 | 生命周期 | NRND(PCN-2025-118)→ Active | MISMATCH · 高 | P-08 · P08-0001/0002 | 两记录 `lifecycle_status`/`eol_pcn_status` 直读比对;「本次替代的驱动因素」为影响说明(推导) |
|
||||
| SUB-0001 | 工作温度 | -40~+85℃ → -40~+125℃ | MISMATCH · 中 | P-08 参数集 v2026-08 | 参数集 JSON 直读比对;「候选温域更宽,覆盖原需求」为影响说明 |
|
||||
| SUB-0001 | 使能阈值 | 1.4V → 未披露 | UNKNOWN · 中 | 挂 VAL-2026-0188 | 参数集 JSON 直读比对;UNKNOWN 收口动作直读链自 P06-0001(`validation_id`/`issue_risk`/`next_validation_action`) |
|
||||
| SUB-0001 | 静态电流 | 5mA → 4.2mA | MISMATCH · 低 | P-08 参数集 v2026-08 | 参数集 JSON 直读比对;「候选更优」为影响说明 |
|
||||
| SUB-0002 | 输出电压 | 5.0V 固定 → 1.23~37V 可调 | CONDITIONAL · 中 | VAL-2026-0040 | 参数集 JSON 直读比对;「精度 ±2.1%(固定版 ±1%)」直读链自 P06-0017.`test_result` |
|
||||
| SUB-0002 | 反馈网络 | 内置固定分压 → 外部分压电阻 | CONDITIONAL · 中 | VAL-2026-0040 | 参数集 JSON 直读比对;「BOM 增加 2 颗 0.1% 电阻」由 P06-0017.`issue_risk`「精度敏感场景需 0.1% 电阻」推导 |
|
||||
|
||||
约束列(硬约束/软约束):推导——电性能参数按 GOV 规则默认硬约束,生命周期/静态电流按软约束处理(演示口径)。
|
||||
|
||||
## 六、P-10 原厂技术资料库(标注「回链推导 · 2 条」)
|
||||
|
||||
P-10 无数据文件,两条均由 P-08 的 `datasheet_ref` / `datasheet_version` / `brand_name` 直读链推导:
|
||||
|
||||
| 行 | 关联料号 | 资料文件 | 版本 | 来源 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | LM2596S-5.0 · LM2596S-ADJ | ti.com/lit/ds/snvsbt0/snvsbt0.pdf | Rev H(2023-09) | P08-0001 与 P08-0003 的 `datasheet_ref` 相同(两条 TI 料共用一份 datasheet),合并为一条;页面显示去掉了 `https://www.` 前缀 |
|
||||
| 2 | XL2596S-5.0 | xlsemi.com/datasheet/XL2596S-5.0.pdf | Rev C(2025-06) | P08-0002.`datasheet_ref` / `datasheet_version` |
|
||||
|
||||
「资料类型 = Datasheet」「状态 = 有效」为推导(`record_status`=有效 沿用)。
|
||||
|
||||
## 七、P-06 样品验证记录台账(表,标注「数据文件直读 · 3 条」)
|
||||
|
||||
三行对应 P-06 文件记录 **P06-0001(VAL-2026-0188)/ P06-0017(VAL-2026-0040)/ P06-0018(VAL-2026-0032)**,全部直读。列与字段映射:
|
||||
|
||||
| 看板列 | P-06 字段 | 备注 |
|
||||
|---|---|---|
|
||||
| 验证 ID | `validation_id` | |
|
||||
| 关联需求 / 项目 | `request_id` / `project_id` | VAL-2026-0040 的 project_id 原文为「—」,页面如实显示 |
|
||||
| 验证料号 | `validation_internal_pn` | |
|
||||
| 验证类型 | `validation_type` | Pin-to-Pin / 功能 / 可靠性 |
|
||||
| 测试条件 | `test_condition` | VAL-2026-0188 原文前缀「样品上板验证:」页面简写为「样品上板:」,其余原文 |
|
||||
| 结果 / 状态 | `validation_status` + `test_result` | 状态做 pill;`test_result` 原文放入小字(如「排期 2026-08-28」「精度 ±2.1%(固定版 ±1%),温漂 +0.6%」「壳温 108℃(加散热片),输出漂移 +0.8%」);批次号 = `sample_lot`(XL-202607-03);RPT 编号 = `evidence_ref`(RPT-2026-0040 / RPT-2026-0032,页面去掉 .pdf 后缀) |
|
||||
| 问题与风险 | `issue_risk` | 原文直读;VAL-2026-0032 原文「—」如实显示 |
|
||||
| 后续动作 | `next_validation_action` | 原文直读;VAL-2026-0032 的「(作为本次评估历史证据引用)」为页面补充说明(推导) |
|
||||
|
||||
未展示字段:`record_id`、`record_version`、`customer_id`(已在页头)、`sample_version`、`data_owner`、`created_at`/`updated_at`/`last_verified_at` 等管理字段。
|
||||
|
||||
## 八、次要台账条(P-09 / EXT-02 / GOV)
|
||||
|
||||
三张卡片只有台账编号、名称和一句角色描述,**无台账数据**。描述文字为推导,依据《Demo台账字段细化与统一方案.md》的台账定义 + 本活动读写关系(P-09 提供 BOM 位、EXT-02 登记可信外部来源、GOV 锁定四态判定口径版本 R-2026.07)。
|
||||
|
||||
## 九、页脚
|
||||
|
||||
「数据来源:P-08-芯片主数据台账-模拟数据V0.1.xlsx · P-06-样品验证记录台账-模拟数据V0.1.xlsx · 字段口径:Demo台账字段细化与统一方案」——即本文档第一节的三个来源。
|
||||
|
||||
---
|
||||
|
||||
## 附:取值原则
|
||||
|
||||
1. **能直读不推导**:P-08 / P-06 有数据文件的字段全部逐字段直读,不改语义(仅做显示层截短/排版,如上各表「备注」列注明处)。
|
||||
2. **推导必标注**:P-01 / P-10 / P-11 无数据文件,看板右上角计数器与页头图例均以琥珀色标注「回链推导」;推导链条在本文档中逐字段写明。
|
||||
3. **不虚构事实类数据**:P-06 属事实证据类,凡页面出现的验证结论、精度数值、报告编号均可回溯到 P-06 记录原文,无凭空编造的测试数据。
|
||||
@@ -0,0 +1,409 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>ACT-WORK-05 差异评估 · 关键台账数据 · SS02 需求分析与方案匹配</title>
|
||||
<style>
|
||||
:root{
|
||||
--ink:#1f2329; --ink-2:#41464e; --ink-3:#646a73; --ink-4:#8f959e;
|
||||
--line:#dee0e3; --line-soft:#e8eaed; --soft:#f8f9fb;
|
||||
--brand:#3370ff; --brand-deep:#245bdb; --brand-soft:#e1eaff; --brand-wash:#f0f4ff;
|
||||
--data:#3370ff; --data-soft:#e1eaff; --data-line:#c3d6ff;
|
||||
--human:#d97706; --human-soft:#fdf1dc; --human-line:#f0d8a8;
|
||||
--ledger:#16a34a; --ledger-soft:#e6f6ec; --ledger-line:#b7e5c6;
|
||||
--ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9;
|
||||
--amber:#8f6a12; --amber-soft:#fdf3d7; --amber-line:#ecd9a0;
|
||||
--mono:"SF Mono",Menlo,Consolas,monospace;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
html,body{margin:0;padding:0}
|
||||
body{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:#fff;color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
|
||||
.page{max-width:none;margin:0;padding:0}
|
||||
|
||||
/* 头部 */
|
||||
.mast{background:#fff;border:1px solid var(--line-soft);border-radius:14px;padding:22px 26px;position:relative;overflow:hidden}
|
||||
.mast::before{content:"";position:absolute;inset:0 0 auto 0;height:4px;background:linear-gradient(90deg,var(--brand) 0%,var(--brand-deep) 100%)}
|
||||
.mast .kick{font-size:11px;letter-spacing:.12em;color:var(--ink-4);font-weight:800}
|
||||
.mast h1{margin:4px 0 6px;font-size:23px;font-weight:800;line-height:1.3}
|
||||
.mast h1 .code{font-family:var(--mono);font-size:14px;font-weight:700;color:var(--brand-deep);background:var(--brand-wash);border:1px solid var(--brand-soft);border-radius:8px;padding:3px 10px;margin-right:10px;vertical-align:3px}
|
||||
.mast .sub{font-size:13px;color:var(--ink-3)}
|
||||
.mast .sub b{color:var(--ink-2)}
|
||||
|
||||
/* 数据来源图例 */
|
||||
.legend{display:flex;gap:10px;flex-wrap:wrap;margin:12px 0 0;font-size:12px;color:var(--ink-3)}
|
||||
.legend .li{display:inline-flex;align-items:center;gap:6px;background:#fff;border:1px solid var(--line-soft);border-radius:999px;padding:3px 12px}
|
||||
.dot{width:8px;height:8px;border-radius:50%;flex:none}
|
||||
.dot.full{background:var(--brand)}
|
||||
.dot.half{background:var(--amber)}
|
||||
|
||||
/* 分层图例 */
|
||||
.layers{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin:14px 0 18px}
|
||||
.layer{background:#fff;border:1px solid var(--line-soft);border-radius:11px;padding:11px 14px;font-size:12px;color:var(--ink-2);border-top:3px solid var(--brand)}
|
||||
.layer b{display:block;font-size:12.5px;color:var(--ink);margin-bottom:2px}
|
||||
.layer .lg{font-family:var(--mono);font-weight:800;color:var(--brand-deep)}
|
||||
.layer.core-out{border-top-color:var(--ledger)} .layer.core-out .lg{color:var(--ledger)}
|
||||
.layer.evid{border-top-color:var(--human)} .layer.evid .lg{color:var(--human)}
|
||||
.layer.loop{border-top-color:var(--amber)} .layer.loop .lg{color:var(--amber)}
|
||||
.layer.ctx{border-top-color:var(--ink-4)} .layer.ctx .lg{color:var(--ink-3)}
|
||||
|
||||
/* 区块 */
|
||||
section{background:#fff;border:1px solid var(--line-soft);border-radius:14px;padding:18px 22px;margin-bottom:16px}
|
||||
.sec-head{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap}
|
||||
.sec-head h2{margin:0;font-size:15.5px;font-weight:800}
|
||||
.sec-head h2 .lid{font-family:var(--mono);font-size:12px;color:var(--brand-deep);background:var(--brand-wash);border:1px solid var(--brand-soft);border-radius:6px;padding:1px 8px;margin-right:8px}
|
||||
.ltag{font-size:10.5px;font-weight:800;padding:2px 9px;border-radius:999px;border:1px solid transparent;white-space:nowrap}
|
||||
.ltag.in{color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft)}
|
||||
.ltag.out{color:var(--ledger);background:var(--ledger-soft);border-color:var(--ledger-line)}
|
||||
.ltag.evid{color:var(--human);background:var(--human-soft);border-color:var(--human-line)}
|
||||
.ltag.loop{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.ltag.ctx{color:var(--ink-3);background:var(--soft);border-color:var(--line)}
|
||||
.sec-head .why{font-size:12px;color:var(--ink-4)}
|
||||
.sec-head .cnt{margin-left:auto;font-size:11.5px;color:var(--ink-4);font-family:var(--mono)}
|
||||
|
||||
/* 表格 */
|
||||
.tbl-wrap{border:1px solid var(--line-soft);border-radius:10px;overflow:hidden}
|
||||
table{width:100%;border-collapse:collapse;font-size:12.5px}
|
||||
th{text-align:left;background:var(--soft);font-size:11px;letter-spacing:.05em;font-weight:800;color:var(--ink-3);padding:9px 12px;border-bottom:1px solid var(--line)}
|
||||
td{padding:9px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top}
|
||||
tr:last-child td{border-bottom:0}
|
||||
tbody tr{transition:background .15s}
|
||||
tbody tr:hover{background:var(--brand-wash)}
|
||||
.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
|
||||
.pn{font-weight:700}
|
||||
|
||||
/* 状态 pill */
|
||||
.st{display:inline-block;padding:1px 9px;border-radius:999px;font-size:11px;font-weight:800;white-space:nowrap;border:1px solid transparent}
|
||||
.st.ok{color:var(--ok);background:var(--ok-soft);border-color:#bfe6b4}
|
||||
.st.miss{color:var(--danger);background:var(--danger-soft);border-color:#f3b9b5}
|
||||
.st.unknown{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line)}
|
||||
.st.cond{color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft)}
|
||||
.st.gray{color:var(--ink-3);background:var(--soft);border-color:var(--line)}
|
||||
.st.warn{color:var(--human);background:var(--human-soft);border-color:var(--human-line)}
|
||||
|
||||
/* P-01 单记录 KV 卡 */
|
||||
.kv{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line-soft);border:1px solid var(--line-soft);border-radius:10px;overflow:hidden}
|
||||
.kv .cell{background:#fff;padding:10px 14px}
|
||||
.kv .k{font-size:11px;font-weight:800;color:var(--ink-4);margin-bottom:2px}
|
||||
.kv .v{font-size:12.5px;color:var(--ink);line-height:1.5}
|
||||
.kv .span2{grid-column:span 2}
|
||||
|
||||
/* 参数集摘要 chips */
|
||||
.pchips{display:flex;flex-wrap:wrap;gap:4px}
|
||||
.pchips span{font-size:11px;font-family:var(--mono);background:var(--soft);border:1px solid var(--line-soft);border-radius:6px;padding:1px 7px;color:var(--ink-2);white-space:nowrap}
|
||||
|
||||
/* 次要台账条 */
|
||||
.minor{display:flex;gap:10px;flex-wrap:wrap}
|
||||
.minor .m{flex:1;min-width:220px;border:1px solid var(--line-soft);border-radius:10px;padding:11px 14px;font-size:12px;color:var(--ink-2)}
|
||||
.minor .m b{display:block;font-size:12.5px;color:var(--ink);margin-bottom:3px}
|
||||
.minor .m .lid{font-family:var(--mono);color:var(--ink-4);font-weight:700;margin-right:6px}
|
||||
|
||||
footer{margin-top:18px;font-size:11.5px;color:var(--ink-4);display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px}
|
||||
@media(max-width:900px){.layers{grid-template-columns:repeat(2,1fr)}.kv{grid-template-columns:1fr 1fr}.kv .span2{grid-column:span 2}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
|
||||
<header class="mast">
|
||||
<div class="kick">SS02 需求分析与方案匹配 · 活动台账视图</div>
|
||||
<h1><span class="code">ACT-WORK-05</span>关键台账数据</h1>
|
||||
<p class="sub">视角:本活动一次运行实例的读数快照 · 关联需求 <b>REQ-20260826-001</b>(客户 CUS-2025-0007 · 项目 PRJ-PSU-40V)· 评估基准 <b>LM2596S-5.0(TI)</b> → 候选 <b>XL2596S-5.0(XLSEMI)</b>、<b>LM2596S-ADJ(TI)</b> · 规则版本 <b>R-2026.07</b></p>
|
||||
<div class="legend">
|
||||
<span class="li"><span class="dot full"></span>台账数据文件直读(P-08 / P-06 模拟数据 V0.1)</span>
|
||||
<span class="li"><span class="dot half"></span>关联回链推导(P-01 / P-10 / P-11 暂无独立数据文件,由 P-08 / P-06 的引用关系与参数集推导展示)</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 重要性分层 -->
|
||||
<div class="layers">
|
||||
<div class="layer"><b><span class="lg">P-08</span> 芯片主数据</b>核心输入 · 评估原材料,查无即硬阻塞</div>
|
||||
<div class="layer core-out"><b><span class="lg">P-11</span> 替代批准关系库</b>核心产出 · 结论与明细的落账地</div>
|
||||
<div class="layer evid"><b><span class="lg">P-10</span> 原厂技术资料库</b>证据链 · 每项结论的版本化出处</div>
|
||||
<div class="layer loop"><b><span class="lg">P-06</span> 样品验证记录</b>闭环去向 · UNKNOWN 的实测收口</div>
|
||||
<div class="layer ctx"><b><span class="lg">P-01</span> 客户需求主台账</b>上下文 · 需求源头与回写对象</div>
|
||||
</div>
|
||||
|
||||
<!-- P-01 -->
|
||||
<section id="p01">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-01</span>客户需求主台账</h2>
|
||||
<span class="ltag ctx">上下文 · R+W</span>
|
||||
<span class="why">启动时新建需求;结束时回写风险 / 验证要求 / 输出链接 / 下一步 / 当前阶段</span>
|
||||
<span class="cnt">回链推导 · 1 条</span>
|
||||
</div>
|
||||
<div class="kv">
|
||||
<div class="cell"><div class="k">需求编号</div><div class="v mono">REQ-20260826-001</div></div>
|
||||
<div class="cell"><div class="k">客户</div><div class="v mono">CUS-2025-0007</div></div>
|
||||
<div class="cell"><div class="k">项目</div><div class="v mono">PRJ-PSU-40V</div></div>
|
||||
<div class="cell"><div class="k">需求版本</div><div class="v mono">V1(启动新建)</div></div>
|
||||
<div class="cell span2"><div class="k">需求描述</div><div class="v">工业电源 12V→5V 电源位替代:原 LM2596S-5.0(NRND,PCN-2025-118 通知 2027-03 停产)</div></div>
|
||||
<div class="cell"><div class="k">应用场景</div><div class="v">12V/24V/40V 输入三档 · 0.5A~3A 负载 · 工业温域</div></div>
|
||||
<div class="cell"><div class="k">BOM 位</div><div class="v mono">U3 电源位</div></div>
|
||||
<div class="cell"><div class="k">原内部料号</div><div class="v mono">LM2596S-5.0</div></div>
|
||||
<div class="cell"><div class="k">候选内部料号</div><div class="v mono">XL2596S-5.0 · LM2596S-ADJ</div></div>
|
||||
<div class="cell"><div class="k">风险等级(回写)</div><div class="v"><span class="st warn">中</span></div></div>
|
||||
<div class="cell"><div class="k">验证要求(回写)</div><div class="v mono">VAL-2026-0188</div></div>
|
||||
<div class="cell"><div class="k">当前阶段</div><div class="v">提交 ACT-GATE-03</div></div>
|
||||
<div class="cell span2"><div class="k">下一步动作</div><div class="v">提交 ACT-GATE-03 评审放行(FAE · 李工 · 1 个工作日)</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- P-08 -->
|
||||
<section id="p08">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-08</span>芯片主数据台账</h2>
|
||||
<span class="ltag in">核心输入 · R(查无 → 数据工单创建)</span>
|
||||
<span class="why">原 PN 与候选 PN 的物料基准 + 标准化参数集,逐项比对的原材料</span>
|
||||
<span class="cnt">数据文件直读 · 3 条(本活动相关)</span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
<thead><tr><th>内部料号</th><th>品牌 / 制造商</th><th>规格描述</th><th>封装 / 工艺</th><th>生命周期</th><th>Datasheet</th><th>标准化参数集(8 项)</th><th>适配场景</th></tr></thead>
|
||||
<tbody data-rows="ledger.p08">
|
||||
<tr>
|
||||
<td class="pn mono">LM2596S-5.0<br><span style="font-weight:400;color:var(--ink-4)">P08-0001 · v3</span></td>
|
||||
<td>TI<br><span style="color:var(--ink-4);font-size:11.5px">Texas Instruments</span></td>
|
||||
<td>降压型 DCDC 稳压器,3A 输出,固定 5.0V,150kHz</td>
|
||||
<td class="mono">TO-263-5<br>BCD</td>
|
||||
<td><span class="st miss">NRND</span><br><span style="font-size:11px;color:var(--ink-3)">PCN-2025-118 已通知,2027-03 停止供货</span></td>
|
||||
<td class="mono">Rev H(2023-09)</td>
|
||||
<td><div class="pchips"><span>输入 4.5~40V</span><span>输出 5.0V 固定</span><span>电流 3A</span><span>150kHz</span><span>静态 5mA</span><span>-40~+85℃</span><span>EN 阈值 1.4V</span><span>内置反馈</span></div></td>
|
||||
<td>工业电源;板载 5V 轨</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pn mono">XL2596S-5.0<br><span style="font-weight:400;color:var(--ink-4)">P08-0002 · v2</span></td>
|
||||
<td>XLSEMI<br><span style="color:var(--ink-4);font-size:11.5px">XLSEMI</span></td>
|
||||
<td>降压型 DCDC 稳压器,3A 输出,固定 5.0V,150kHz,与 LM2596S-5.0 引脚兼容</td>
|
||||
<td class="mono">TO-263-5<br>BCD</td>
|
||||
<td><span class="st ok">Active</span></td>
|
||||
<td class="mono">Rev C(2025-06)</td>
|
||||
<td><div class="pchips"><span>输入 4.5~40V</span><span>输出 5.0V 固定</span><span>电流 3A</span><span>150kHz</span><span>静态 4.2mA</span><span>-40~+125℃</span><span>EN 阈值 未披露</span><span>内置反馈</span></div></td>
|
||||
<td>工业电源;消费电源</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="pn mono">LM2596S-ADJ<br><span style="font-weight:400;color:var(--ink-4)">P08-0003 · v2</span></td>
|
||||
<td>TI<br><span style="color:var(--ink-4);font-size:11.5px">Texas Instruments</span></td>
|
||||
<td>降压型 DCDC 稳压器,3A,可调输出 1.23~37V,150kHz</td>
|
||||
<td class="mono">TO-263-5<br>BCD</td>
|
||||
<td><span class="st ok">Active</span></td>
|
||||
<td class="mono">Rev H(2023-09)</td>
|
||||
<td><div class="pchips"><span>输入 4.5~40V</span><span>输出 1.23~37V 可调</span><span>电流 3A</span><span>150kHz</span><span>静态 5mA</span><span>-40~+125℃</span><span>EN 阈值 1.4V</span><span>外部分压反馈</span></div></td>
|
||||
<td>可调电源;工控</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- P-11 -->
|
||||
<section id="p11">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-11</span>替代选型与批准关系库 · 替代关系主记录</h2>
|
||||
<span class="ltag out">核心产出 · R+W</span>
|
||||
<span class="why">每个候选一条关系记录;客户批准状态为只读边界,本活动不写</span>
|
||||
<span class="cnt">回链推导 · 2 条</span>
|
||||
</div>
|
||||
<div class="tbl-wrap" style="margin-bottom:14px">
|
||||
<table>
|
||||
<thead><tr><th>替代关系 ID</th><th>原 → 候选</th><th>替代类型</th><th>推荐等级</th><th>分析状态</th><th>风险</th><th>验证要求 / 回链</th><th>规则版本</th><th>客户批准(只读)</th></tr></thead>
|
||||
<tbody data-rows="ledger.p11_relations">
|
||||
<tr>
|
||||
<td class="mono">P11-SUB-0001</td>
|
||||
<td class="mono">LM2596S-5.0 → <b>XL2596S-5.0</b></td>
|
||||
<td>Pin-to-Pin</td>
|
||||
<td><span class="st warn">条件推荐</span></td>
|
||||
<td><span class="st cond">FAE确认</span></td>
|
||||
<td><span class="st warn">中</span></td>
|
||||
<td class="mono">VAL-2026-0188(使能阈值实测,进行中)</td>
|
||||
<td class="mono">R-2026.07</td>
|
||||
<td><span class="st gray">未提交</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">P11-SUB-0002</td>
|
||||
<td class="mono">LM2596S-5.0 → <b>LM2596S-ADJ</b></td>
|
||||
<td>功能替代</td>
|
||||
<td><span class="st cond">备选</span></td>
|
||||
<td><span class="st cond">FAE确认</span></td>
|
||||
<td><span class="st ok">低</span></td>
|
||||
<td class="mono">VAL-2026-0040(条件通过:外部分压精度 ±2.1%)</td>
|
||||
<td class="mono">R-2026.07</td>
|
||||
<td><span class="st gray">未提交</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="sec-head" style="margin-bottom:10px">
|
||||
<h2 style="font-size:13.5px"><span class="lid">P-11</span>差异明细子表(非 MATCH 项,由双方 P-08 标准化参数集逐项比对得出)</h2>
|
||||
<span class="cnt">6 条</span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
<thead><tr><th>所属关系</th><th>参数项</th><th>原值 → 候选值</th><th>约束</th><th>结论</th><th>风险</th><th>证据引用</th><th>影响说明</th></tr></thead>
|
||||
<tbody data-rows="ledger.p11_diff_items">
|
||||
<tr>
|
||||
<td class="mono">SUB-0001</td>
|
||||
<td>生命周期</td>
|
||||
<td class="mono">NRND(PCN-2025-118)→ Active</td>
|
||||
<td>软约束</td>
|
||||
<td><span class="st miss">MISMATCH</span></td>
|
||||
<td><span class="st miss">高</span></td>
|
||||
<td class="mono">P-08 · P08-0001/0002</td>
|
||||
<td>原料 2027-03 停产——本次替代的驱动因素</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">SUB-0001</td>
|
||||
<td>工作温度</td>
|
||||
<td class="mono">-40~+85℃ → -40~+125℃</td>
|
||||
<td>硬约束</td>
|
||||
<td><span class="st miss">MISMATCH</span></td>
|
||||
<td><span class="st warn">中</span></td>
|
||||
<td class="mono">P-08 参数集 v2026-08</td>
|
||||
<td>候选温域更宽,覆盖原需求</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">SUB-0001</td>
|
||||
<td>使能阈值</td>
|
||||
<td class="mono">1.4V → 未披露</td>
|
||||
<td>硬约束</td>
|
||||
<td><span class="st unknown">UNKNOWN</span></td>
|
||||
<td><span class="st warn">中</span></td>
|
||||
<td class="mono">挂 VAL-2026-0188</td>
|
||||
<td>原厂未披露,实测闭环前维持条件推荐</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">SUB-0001</td>
|
||||
<td>静态电流</td>
|
||||
<td class="mono">5mA → 4.2mA</td>
|
||||
<td>软约束</td>
|
||||
<td><span class="st miss">MISMATCH</span></td>
|
||||
<td><span class="st ok">低</span></td>
|
||||
<td class="mono">P-08 参数集 v2026-08</td>
|
||||
<td>候选更优,无不利影响</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">SUB-0002</td>
|
||||
<td>输出电压</td>
|
||||
<td class="mono">5.0V 固定 → 1.23~37V 可调</td>
|
||||
<td>硬约束</td>
|
||||
<td><span class="st cond">CONDITIONAL</span></td>
|
||||
<td><span class="st warn">中</span></td>
|
||||
<td class="mono">VAL-2026-0040</td>
|
||||
<td>需外部分压设定 5.0V,精度 ±2.1%(固定版 ±1%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">SUB-0002</td>
|
||||
<td>反馈网络</td>
|
||||
<td class="mono">内置固定分压 → 外部分压电阻</td>
|
||||
<td>硬约束</td>
|
||||
<td><span class="st cond">CONDITIONAL</span></td>
|
||||
<td><span class="st warn">中</span></td>
|
||||
<td class="mono">VAL-2026-0040</td>
|
||||
<td>BOM 增加 2 颗 0.1% 电阻,成本上升</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- P-10 -->
|
||||
<section id="p10">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-10</span>原厂技术资料库</h2>
|
||||
<span class="ltag evid">证据链 · R(查无 → 数据工单创建)</span>
|
||||
<span class="why">每项结论的 datasheet 出处,版本回链</span>
|
||||
<span class="cnt">回链推导 · 2 条(来自 P-08 datasheet_ref)</span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
<thead><tr><th>关联料号</th><th>品牌</th><th>资料类型</th><th>资料文件</th><th>版本</th><th>状态</th></tr></thead>
|
||||
<tbody data-rows="ledger.p10">
|
||||
<tr>
|
||||
<td class="mono">LM2596S-5.0 · LM2596S-ADJ</td>
|
||||
<td>TI</td>
|
||||
<td>Datasheet</td>
|
||||
<td class="mono">ti.com/lit/ds/snvsbt0/snvsbt0.pdf</td>
|
||||
<td class="mono">Rev H(2023-09)</td>
|
||||
<td><span class="st ok">有效</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">XL2596S-5.0</td>
|
||||
<td>XLSEMI</td>
|
||||
<td>Datasheet</td>
|
||||
<td class="mono">xlsemi.com/datasheet/XL2596S-5.0.pdf</td>
|
||||
<td class="mono">Rev C(2025-06)</td>
|
||||
<td><span class="st ok">有效</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- P-06 -->
|
||||
<section id="p06">
|
||||
<div class="sec-head">
|
||||
<h2><span class="lid">P-06</span>样品交付与芯片验证记录台账</h2>
|
||||
<span class="ltag loop">闭环去向 · R + 条件写(不可创建,只能实测产生)</span>
|
||||
<span class="why">UNKNOWN / CONDITIONAL 的收口处;验证完成后回链 P-11</span>
|
||||
<span class="cnt">数据文件直读 · 3 条(本活动相关)</span>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
<thead><tr><th>验证 ID</th><th>关联需求 / 项目</th><th>验证料号</th><th>验证类型</th><th>测试条件</th><th>结果 / 状态</th><th>问题与风险</th><th>后续动作</th></tr></thead>
|
||||
<tbody data-rows="ledger.p06">
|
||||
<tr>
|
||||
<td class="mono">VAL-2026-0188</td>
|
||||
<td class="mono">REQ-20260826-001<br>PRJ-PSU-40V</td>
|
||||
<td class="mono">XL2596S-5.0</td>
|
||||
<td>Pin-to-Pin</td>
|
||||
<td>样品上板:U3 电源位,输入 12V/24V/40V 三档,负载 0.5A/1.5A/3A,25℃</td>
|
||||
<td><span class="st cond">进行中</span><br><span style="font-size:11px;color:var(--ink-3)">待实测,排期 2026-08-28 · 批次 XL-202607-03</span></td>
|
||||
<td>使能阈值差异影响开关机逻辑判定,风险=中</td>
|
||||
<td>完成 EN 阈值实测并回链 P11-SUB-0001;未闭环前维持条件推荐</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">VAL-2026-0040</td>
|
||||
<td class="mono">REQ-20260205-001<br>—</td>
|
||||
<td class="mono">LM2596S-ADJ</td>
|
||||
<td>功能</td>
|
||||
<td>可调输出验证:外部分压设定 5.0V,与固定版输出精度对比</td>
|
||||
<td><span class="st warn">条件通过</span><br><span style="font-size:11px;color:var(--ink-3)">精度 ±2.1%(固定版 ±1%),温漂 +0.6% · RPT-2026-0040</span></td>
|
||||
<td>精度敏感场景需 0.1% 电阻,BOM 成本上升,风险=低</td>
|
||||
<td>作为备选结论回链 P11-SUB-0002</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">VAL-2026-0032</td>
|
||||
<td class="mono">REQ-20260120-004<br>PRJ-PSU-40V</td>
|
||||
<td class="mono">XL2596S-5.0</td>
|
||||
<td>可靠性</td>
|
||||
<td>高温满载:70℃ 环境、40V 输入、5V/3A 输出连续 96h</td>
|
||||
<td><span class="st ok">通过</span><br><span style="font-size:11px;color:var(--ink-3)">壳温 108℃(加散热片),输出漂移 +0.8% · RPT-2026-0032</span></td>
|
||||
<td>—</td>
|
||||
<td>—(作为本次评估历史证据引用)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 次要台账 -->
|
||||
<section id="minor">
|
||||
<div class="sec-head">
|
||||
<h2>次要台账(只读引用,不进主看板)</h2>
|
||||
</div>
|
||||
<div class="minor">
|
||||
<div class="m"><b><span class="lid">P-09</span>客户技术与机会档案</b>提供 BOM 位(U3 电源位)与客户技术栈背景;缺口由执行工单补齐。</div>
|
||||
<div class="m"><b><span class="lid">EXT-02</span>外部来源清单</b>登记本次评估用到的可信外部来源(原厂官网 datasheet 等)。</div>
|
||||
<div class="m"><b><span class="lid">GOV</span>评估规则库</b>四态判定口径;本次锁定版本 R-2026.07,随结论一并落账。</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<span>SS02 · ACT-WORK-05 差异评估 · 关键台账数据视图</span>
|
||||
<span style="font-family:var(--mono)">数据来源:P-08-芯片主数据台账-模拟数据V0.1.xlsx · P-06-样品验证记录台账-模拟数据V0.1.xlsx · 字段口径:Demo台账字段细化与统一方案</span>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+51
-1
@@ -42,6 +42,13 @@ const E2E_CLIENT_SECRET = process.env.KEYCLOAK_E2E_CLIENT_SECRET ?? '';
|
||||
* 不设它才走服务账号那条正路(ADR-012)。
|
||||
*/
|
||||
const DIRECT_BEARER = (process.env.JCAI_E2E_BEARER ?? '').replace(/^Bearer\s+/i, '').trim();
|
||||
/**
|
||||
* **要不要落真库**(`JCAI_E2E_LAND_MASTER=1`)—— 默认关:起单接口默认开着(人手点那条路要看见数据真变),
|
||||
* 而 e2e 关它是为了保护「只能测一次」的样例(A1 新客户来函 / W05 候选缺库:主数据一旦真建进去,
|
||||
* 第二次跑那条路就成了老客户 / 都在库)。开着跑一次能验「数据工单确认即入库」真的落到了正式表 ——
|
||||
* 跑完记得把建进去的料号清掉,不然 W05 案例 0/2 从此测不出缺库那条路。
|
||||
*/
|
||||
const LAND_MASTER = process.env.JCAI_E2E_LAND_MASTER === '1';
|
||||
/** access token 只活 5 分钟:超过 4 分钟就换一枚,免得长案例中途 401 */
|
||||
const TOKEN_REFRESH_MS = 4 * 60 * 1000;
|
||||
|
||||
@@ -553,6 +560,8 @@ const SUITES = {
|
||||
rowKey: 'internal_pn',
|
||||
blankCol: 'brand_name',
|
||||
expectGateBlock: true,
|
||||
// 数据工单确认即入库(2026-08-27 用户定)—— 交卷那一刻这张卡的表就该进正式表
|
||||
landsOnConfirm: true,
|
||||
edits: [],
|
||||
// 案例没点名的料号兜底(不该走到这里 —— 每个案例都在 stageEdits 里逐颗给了)
|
||||
fillAllBlank: {
|
||||
@@ -580,6 +589,7 @@ const SUITES = {
|
||||
rowKey: 'internal_pn',
|
||||
blankCol: 'document_title',
|
||||
expectGateBlock: true,
|
||||
landsOnConfirm: true,
|
||||
edits: [],
|
||||
fillAllBlank: {
|
||||
doc_seq: '01',
|
||||
@@ -838,6 +848,27 @@ function draftRows(drafts, address) {
|
||||
return (drafts ?? []).filter((d) => d.address === address).map((d) => ({ ...d.key, ...d.patch }));
|
||||
}
|
||||
|
||||
/**
|
||||
* **数据工单确认即入库**(2026-08-27 用户定:「数据工单里填的数据,确认后就应该入库」)——
|
||||
* 交卷那一刻就验,不等放行:
|
||||
* · 痕上必须有一条「数据工单确认入库 / 已确认(试跑」(基座在回传路由里同步落的,交卷返回时已在);
|
||||
* · 落真库时(`JCAI_E2E_LAND_MASTER=1`)正式表里必须查得到件上填的那几颗料;
|
||||
* · 不落真库时痕必须如实写「只留在活动缓存」—— 界面不撒谎那一条也要验。
|
||||
* 回 'landed' / 'held' / 'missing'(没这条痕 = 这道门没开)/ 'absent'(说落了、正式表里没有)。
|
||||
*/
|
||||
async function expectLandedOnConfirm(taskId, stage, rows) {
|
||||
const { body } = await api(`/api/gov/testbed/activity/${taskId}`);
|
||||
const note = [...(body.trail ?? [])].reverse().find((t) => t.kind === 'ledger-write' && /数据工单(确认入库|已确认)/.test(t.title ?? ''));
|
||||
if (note === undefined) return 'missing';
|
||||
if (/试跑|未落正式表/.test(note.title)) return LAND_MASTER ? 'absent' : 'held';
|
||||
if (!LAND_MASTER) return 'landed';
|
||||
const [domain, object] = stage.address.split('.');
|
||||
const formal = await api(`/api/gov/data/${domain}/${object}`);
|
||||
const keys = Array.isArray(stage.rowKey) ? stage.rowKey : [stage.rowKey];
|
||||
const present = (row) => (formal.body.rows ?? []).some((f) => keys.every((k) => String(f[k] ?? '') === String(row[k] ?? '')));
|
||||
return rows.every(present) ? 'landed' : 'absent';
|
||||
}
|
||||
|
||||
/** 交卷执行卡 —— 载荷零字段(执行卡上没有任何输入,填写全在件上) */
|
||||
async function submitExecution(cardId) {
|
||||
await api('/api/desk/work-orders/reply', {
|
||||
@@ -1135,7 +1166,7 @@ async function runCase(suite, kase) {
|
||||
data: sample.input,
|
||||
message: sample.message ?? '',
|
||||
ownerId: '',
|
||||
landMaster: false,
|
||||
landMaster: LAND_MASTER,
|
||||
}),
|
||||
});
|
||||
const taskId = started.taskId;
|
||||
@@ -1147,6 +1178,8 @@ async function runCase(suite, kase) {
|
||||
// 录入卡的已答名单单独记 —— 与 decided 共用会把 decideSeq 按 size 取的序号顶掉(实测:点名驳回被跳过)
|
||||
const entered = new Set();
|
||||
let gateBlocked = false;
|
||||
/** 数据工单确认了却没入库(或说入库了而表里没有)—— 收工判失败 */
|
||||
let landingBroken = false;
|
||||
/** 资料文件那一次检查的结论(在办中验,见下面那段注释) */
|
||||
let fileCheck;
|
||||
let gateLeaked = false;
|
||||
@@ -1331,6 +1364,19 @@ async function runCase(suite, kase) {
|
||||
}
|
||||
console.log(` 交卷执行卡:${card.title}`);
|
||||
replied.add(card.id);
|
||||
if (stage.landsOnConfirm === true) {
|
||||
const verdict = await expectLandedOnConfirm(taskId, stage, tables[stage.address] ?? []);
|
||||
console.log(
|
||||
verdict === 'landed'
|
||||
? ` 数据工单确认即入库:${stage.address} 已进正式表`
|
||||
: verdict === 'held'
|
||||
? ` 数据工单已确认(试跑不落主数据,痕如实写「只留在活动缓存」)`
|
||||
: verdict === 'missing'
|
||||
? ` ⚠️ 数据工单确认了,痕上没有「确认入库」那一条 —— 这道门没开,判失败`
|
||||
: ` ⚠️ 痕说入库了,正式表里查不到件上填的那几行 —— 判失败`,
|
||||
);
|
||||
if (verdict === 'missing' || verdict === 'absent') landingBroken = true;
|
||||
}
|
||||
} else if (card.mode === 'acceptance') {
|
||||
if (kase.acceptEdits && !acceptEdited) {
|
||||
acceptEdited = true;
|
||||
@@ -1379,6 +1425,10 @@ async function runCase(suite, kase) {
|
||||
console.log(' ⚠️ 提交闸没拦住空手交卷 —— 判失败');
|
||||
ok = false;
|
||||
}
|
||||
if (landingBroken) {
|
||||
console.log(' ⚠️ 数据工单确认即入库那道门没兑现 —— 判失败');
|
||||
ok = false;
|
||||
}
|
||||
// 「超限才叫人」是 A4 的要害:该叫的那一单没叫,等于底价门禁是摆设
|
||||
if (missedRows.size > 0) {
|
||||
console.log(` ⚠️ 案例点名要填的行,整例跑完也没在件上出现过(${missedRows.size} 处:${[...missedRows].slice(0, 3).join('、')}…)—— 判失败`);
|
||||
|
||||
Reference in New Issue
Block a user