别名机制,不是字面枚举值,这里用 badgeCss 生成 .ct.v-hard / .ct.v-soft,
* 颜色原样照抄目标件那两条声明的数值(DANGER/MUTED 与 .ct.hard / .ct.soft 同一份值)。
*/
${badgeCss('.ct', [
['hard', '硬约束', DANGER],
['soft', '软约束', MUTED],
])}
`;
/* ==================== 执行工单(评估输入清单):徽标别名 ==================== */
const BIND_EXEC = `
/* 存在性核对的两列(角色 / 在库状态)与评估输入清单的状态列共用目标件自己的 .st 徽标基座 ——
取值域互不重叠(found/absent/created/abandoned 与 gap/default/ok 没有一个词撞车)。
四档配色**原样照抄目标件自己的 .st.bound / .st.ok / .st.miss / .st.def 那四条声明**,只换成 v- 版。 */
${badgeCss('.st', [
['found', '在库', OK],
['absent', '不在库', 'color: var(--human); background: var(--human-soft); border-color: var(--human-line);'],
['created', '本单新建', 'color: var(--brand-deep); background: var(--brand-wash); border-color: var(--brand-soft);'],
['abandoned', '已放弃', MUTED],
['gap', '待补*', 'color: var(--human); background: var(--human-soft); border-color: var(--human-line);'],
['default', '默认·可改', 'color: var(--brand-deep); background: var(--brand-wash); border-color: var(--brand-soft);'],
['ok', '齐备', OK],
])}
/* 角色(原 PN / 候选 PN)是分类标签不是状态,目标件里这类描述文字从不配色,这里只补 ::after 文案 */
${badgeCss('.rl', [
['original', '原内部料号'],
['candidate', '候选内部料号'],
])}
/*
* **补充内容按行投影必填**(2026-08-27 实测:11 行全摆红「必填」胶囊,而闸只认 3 行)——
* \`sub_eval.input_gap.supplement\` 的必填是 \`requiredWhen:{status:'gap'}\`,按行不按列;
* 静态 \`class="req"\` 会把每一行都标必填。改成 \`\` 按本行的
* status 值投影,只在 v-gap 那一档出红胶囊与行首红条,default / ok 两档不出。
*/
td.sup.v-gap > .jc-vcell:empty::after {
content: "必填"; display: inline-flex; align-items: center; font-style: normal; font-size: 10px; font-weight: 700;
line-height: 1; padding: 3px 7px; border-radius: 5px; border: 1px dashed #f3b9b5; color: var(--danger); background: var(--danger-soft);
}
tbody tr:has(td.sup.v-gap > .jc-vcell:empty) td { background: #fffbfb; }
tbody tr:has(td.sup.v-gap > .jc-vcell:empty) td.rn { color: var(--danger); font-weight: 800; }
`;
/* ==================== 验收工单 01(差异评估结论审核):徽标别名 ==================== */
const BIND_ACC1 = `
/* 差异四态与推荐等级**都**落在这一屏(本活动数据面的既有约定 —— 各候选推荐等级摘要与
逐项差异明细同屏摆),两者取值域都含 "conditional",光认 .st 分不清是哪一列,
加 .dst / .rec 两个字段级修饰类各自配色(**原样照抄目标件 .st.ok/.miss/.unknown/.cond
四条声明**,只是同一份颜色现在要接两条不同的人读文案)。 */
${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);'],
])}
${badgeCss('.st.rec', [
['recommended', '推荐', OK],
['conditional', '条件推荐', 'color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line);'],
['alternate', '备选', AMBER],
['not_recommended', '不推荐', DANGER],
])}
/*
* 风险等级(原样照抄目标件 .risk.low/.mid/.hi 三条声明)——加 critical 一档:这一屏「各候选
* 推荐等级」摘要读的是 substitution.relation.risk_level(声明了 low/medium/high/critical
* 四档),差异明细本身的 risk_level 只有三档,共用同一族选择器,多出的第四档不会撞车。
*/
${badgeCss('.risk', [
['low', '低', 'color: var(--ok);'],
['medium', '中', 'color: #8f6a12;'],
['high', '高', 'color: var(--danger);'],
['critical', '危急', 'color: var(--danger); font-weight: 900;'],
])}
/*
* 约束类型(硬/软)—— 目标件的差异明细表里这一列是纯文字,没有配色(数据工单-01 的 .ct.hard/
* .ct.soft 才是这两个值真正的徽标声明,只是它长在另一份目标件里)。这里把那两条颜色声明
* 原样搬过来当 v- 版(数值不改,只换了外壳类名,因为这一页的样式表里从未定义过 .ct)。
*/
.con { display: inline-block; font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: 999px; border: 1px solid transparent; white-space: nowrap; }
${badgeCss('.con', [
['hard', '硬约束', DANGER],
['soft', '软约束', MUTED],
])}
/* 替代类型 —— 目标件里也是纯文字,不配色,只补文案 */
${badgeCss('.enumtxt', [
['pin_to_pin', 'Pin-to-Pin'],
['functional', '功能替代'],
['parametric', '参数替代'],
['other', '其他'],
])}
`;
/* ==================== 验收工单 02(评审放行与落账确认):徽标别名 ==================== */
const BIND_ACC2 = `
/* 这一屏四个枚举列(推荐等级 / 分析状态 / 需求状态 / 当前阶段)取值域两两不重叠,共用 .st 即可。
推荐等级、分析状态目标件里本就是 .st 徽标(原样照抄 .st.ok/.miss/.unknown/.cond 四条声明);
需求状态 / 当前阶段目标件没有这两列,借同一套配色,不新配颜色。 */
${badgeCss('.st', [
['recommended', '推荐', OK],
['conditional', '条件推荐', 'color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line);'],
['alternate', '备选', AMBER],
['not_recommended', '不推荐', DANGER],
['ai_draft', 'AI 草稿', AMBER],
['fae_confirmed', 'FAE确认', OK],
['pending_customer', '待客户验证', 'color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line);'],
['customer_approved', '客户已批准', OK],
['rejected', '不批准', DANGER],
['void', '作废', MUTED],
['pending', '待处理', MUTED],
['responded', '已响应', 'color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line);'],
['won', '已成交', OK],
['abandoned', '已放弃', DANGER],
['closed', '已关闭', MUTED],
['assessing', '评估中', MUTED],
['gate03', '提交 ACT-GATE-03', OK],
])}
/* 风险等级比验收 01 多一档 critical(P-11 主记录的 risk_level 声明了它,差异明细没有) */
${badgeCss('.risk', [
['low', '低', 'color: var(--ok);'],
['medium', '中', 'color: #8f6a12;'],
['high', '高', 'color: var(--danger);'],
['critical', '危急', 'color: var(--danger); font-weight: 900;'],
])}
/* 替代类型 —— 目标件里是纯文字,不配色,只补文案(与验收 01 同一套值域,各自页面各存一份) */
${badgeCss('.enumtxt', [
['pin_to_pin', 'Pin-to-Pin'],
['functional', '功能替代'],
['parametric', '参数替代'],
['other', '其他'],
])}
`;
/** 三层壳照目标件:``,不再套 `.proto-root`/`.app-shell`/`.jc-stage`
* (那是 E04/I01 自己的视觉底约定,不是平台要求 —— ui-kit / view-render 从未引用过这几个类名;
* 目标件本身就是直接 `page > card`,搬版面就该原样搬这一层)。
* 收件人 / 关联任务两格由引擎注入;目标件的「最迟交回」(`card.deadline`)本仓没有真数据源,不摆;
* 工单编号(`card.id`)换成本次评估案号 `eval_ref`。
*/
const doc = (input: { css: string; alias: string; badge: string; hic?: string; tag: string; kicker: string; title: string; step: string; body: string; footTag: string }): string =>
`
`;
/* ==================== 内联 SVG 图标 —— 逐字节搬自「数据工单-01」目标件(它们是版面语言的一部分) ==================== */
const HIC =
' ';
const ZIC_TASK =
' ';
const ZIC_TABLE =
' ';
/* ==================== 通用绑定小工具 ==================== */
const zone = (label: string, aside: string, icon = ''): string => ` ${icon}【${label}】—— ${aside} `;
const note = (items: readonly string[]): string => ` ${items.map((p) => ` ${p} `).join('')} `;
const criteria = (title: string, items: readonly string[]): string =>
` ${title} ${items.map((i) => `- ${i}
`).join('')} `;
const flow = (text: string): string => ` ${text} `;
const editGate = (address: string, label: string): string => `
${label}
`;
const gapbar = (object: string, what: string): string => `
还差 行${what}没填 —— 。按「编辑」开表,红框那几格就是要填的。补齐了才确认得了。
`;
const addrow = (address: string, label: string, hint: string): string => `
${hint}
`;
/** 可改格:只读那一份留空,渲染器自动配孪生 ` `(手写 input 会不填值,人一点编辑就是白框) */
const cell = (col: string, cls = ''): string => ` `;
/** 只读格:即便挂在可改的表里也不许被 `table.on` 藏起来 —— 目标件自己就有这条覆盖(`.jc-vcell.ro`) */
const ro = (col: string, cls = ''): string => ` `;
const select = (col: string, options: ReadonlyArray , required = false): string =>
``;
/**
* 枚举徽标。可改表里挨着 ` |