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:
@@ -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)}
|
||||
|
||||
Reference in New Issue
Block a user