diff --git a/activities/part-substitution-assessment/__tests__/activity.test.ts b/activities/part-substitution-assessment/__tests__/activity.test.ts index 5eb036c..9589f97 100644 --- a/activities/part-substitution-assessment/__tests__/activity.test.ts +++ b/activities/part-substitution-assessment/__tests__/activity.test.ts @@ -2,7 +2,8 @@ * ACT-WORK-05 差异评估的包内自测 —— **只准 import @sdk / @contracts / @sfeel**。 * 案例活动没有 `run`,自测不跑回合;测的是清单本身与授权面对齐,结构照 E04 / I01。 * - * 五组:清单本身合规 / 台账声明 / 案例模型与清单的对齐 / 报告模版:编辑面与只读面各就各位 / 活动入口。 + * 六组:清单本身合规 / 台账声明 / 案例模型与清单的对齐 / 报告模版:编辑面与只读面各就各位 / + * 徽标别名与值域相关的坑(2026-08-27 实测账,回归网)/ 活动入口。 */ import { describe, expect, it } from 'vitest'; import { activityManifestSchema } from '@contracts'; @@ -237,6 +238,70 @@ describe('报告模版:编辑面与只读面各就各位', () => { const host = createMockHost({ contract: CONTRACT }); await expect(host.base.interaction.pushHtml('
')).rejects.toThrow(/无脚本执行权/); }); + + it('五张模版的外壳都是搬自目标件的 page/card,不再含 E04/I01 那套视觉底(.proto-root)的痕迹', () => { + for (const view of VIEWS) { + const html = viewHtml(view); + expect(html, view).toContain('class="card-head"'); + expect(html, view).toContain('class="card-foot"'); + expect(html, view).not.toContain('proto-root'); + } + }); +}); + +/* + * 2026-08-27 实测账,两条都真截图 + SQL 复核过: + * ① **带下划线的枚举值一律显示成「待定」**——平台有两套互相打架的消毒规则: + * `data-class-of` 投影出的 class 走 `view-render.ts` 的 `classToken`(只留 `[a-z0-9-]`, + * 吃掉下划线,`pin_to_pin` → `v-pintopin`);基座读数名走 `engines.ts` 的 `slug` + * (只留 `[a-z0-9_]`,吃掉连字符)。手写 `.v-pin_to_pin` 那种选择器永远匹配不上 —— + * 这条测试把 `manifest.declarations.ledger` 里每一个「模版真的摆了徽标」的 tally 列过一遍, + * 用与 `classToken` 一字不差的 `vtok` 算出选择器,断言对应的 CSS 规则确实存在。 + * ② **缺口表补充内容每一行都摆红「必填」,而闸只认 3 行**——`requiredWhen` 是按行不按列, + * 静态 `class="req"` 把整列都标了必填。 + */ +describe('徽标别名与值域相关的坑(2026-08-27 实测账,回归网)', () => { + /** 必须与 `apps/api/src/modules/interaction/internal/domain/view-render.ts` 的 `classToken` 一字不差 */ + const vtok = (v: string): string => v.toLowerCase().replace(/[^a-z0-9-]/g, '').slice(0, 24); + + /** 每张模版真的摆了徽标的那几列(带下划线的 tally 值最容易漏,漏了就是「待定」那次事故) */ + const BADGED: ReadonlyArray<{ view: string; domain: string; object: string; column: string }> = [ + { view: 'p08-master-create', domain: 'parts', object: 'profile', column: 'lifecycle_status' }, + { view: 'p10-document-create', domain: 'parts', object: 'document', column: 'document_type' }, + { view: 'p10-document-create', domain: 'parts', object: 'document', column: 'document_status' }, + { view: 'eval-input-list', domain: D, object: 'pn_check', column: 'exists_status' }, + { view: 'eval-input-list', domain: D, object: 'pn_check', column: 'role' }, + { view: 'eval-input-list', domain: D, object: 'input_gap', column: 'status' }, + { view: 'difference-review', domain: 'substitution', object: 'relation', column: 'substitution_type' }, + { view: 'difference-review', domain: 'substitution', object: 'relation', column: 'recommendation_level' }, + { view: 'difference-review', domain: 'substitution', object: 'relation', column: 'risk_level' }, + { view: 'difference-review', domain: 'substitution', object: 'difference_item', column: 'constraint_type' }, + { view: 'difference-review', domain: 'substitution', object: 'difference_item', column: 'difference_status' }, + { view: 'difference-review', domain: 'substitution', object: 'difference_item', column: 'risk_level' }, + { view: 'landing-confirm', domain: 'substitution', object: 'relation', column: 'substitution_type' }, + { view: 'landing-confirm', domain: 'substitution', object: 'relation', column: 'recommendation_level' }, + { 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' }, + ]; + + it('每张模版摆了徽标的每个 tally 列,声明里的每个值都有对应的 v- 规则(选择器是从值算出来的,不是手写的)', () => { + for (const { view, domain, object, column } of BADGED) { + const tally = byAddress(domain, object)?.fields.find((f) => f.name === column)?.tally ?? []; + expect(tally.length, `${domain}.${object}.${column} 没有声明 tally`).toBeGreaterThan(0); + const html = viewHtml(view); + for (const value of tally) { + expect(html, `${view}: ${domain}.${object}.${column}=${value} → 应有 .v-${vtok(value)}::after`).toContain(`.v-${vtok(value)}::after`); + } + } + }); + + it('缺口表补充内容按行投影必填,不是整列静态 req(requiredWhen 是按行的,不是按列的)', () => { + const html = viewHtml('eval-input-list'); + expect(html).not.toContain('class="req" data-h="补充内容"'); + expect(html).toContain('data-class-of="status"'); + expect(html).toContain('.sup.v-gap'); + }); }); describe('活动入口', () => { diff --git a/activities/part-substitution-assessment/src/manifest.ts b/activities/part-substitution-assessment/src/manifest.ts index 4d32c57..320fe38 100644 --- a/activities/part-substitution-assessment/src/manifest.ts +++ b/activities/part-substitution-assessment/src/manifest.ts @@ -84,7 +84,7 @@ export const manifest: ActivityManifest = { identity: { activityId: ACTIVITY_ID, name: 'ACT-WORK-05 · 差异评估', - packageVersion: '1.0.1', + packageVersion: '1.1.0', category: '需求分析与方案匹配', sdkVersion: '0.1.0-m5', checksum: 'dev-checksum-part-substitution-assessment', diff --git a/activities/part-substitution-assessment/src/views/prd-style.ts b/activities/part-substitution-assessment/src/views/prd-style.ts deleted file mode 100644 index 4f252b3..0000000 --- a/activities/part-substitution-assessment/src/views/prd-style.ts +++ /dev/null @@ -1,158 +0,0 @@ -/** - * ACT-WORK-05 差异评估 · 视觉底 —— 逐字节抄自 I01(`brand-content-toolkit/src/views/prd-style.ts`)。 - * - * 本活动的四份目标件(`docs/SS02-ACT-WORK-05-html/*.html`)与 E04 / I01 的目标件是同一套 - * 设计语言产出的(卡壳 / 卡头渐变 / 判据框 / 表格排版全同);`activities/*` 只准 import - * `@sdk` / `@contracts`,包之间没有代码通道,只能各自持有一份。改这份不要改口径: - * 数据驱动的开关(三档占位 / 缺项红带 / 状态徽 / 编辑闸)在 `report.ts` 的 `BIND_CSS`。 - */ - -export const PRD_CSS = ` -.proto-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; - --human:#a9711e; --human-soft:#f6ecd8; --human-line:#e6d3a8; - --ledger:#b23a2e; --ledger-soft:#f7e4e0; --ledger-line:#ecc5bd; - --ok:#278717; --ok-soft:#e8f8e4; - --danger:#d83931; --danger-soft:#feeae9; - --warn-accent:#a9711e; --warn-soft:#f6ecd8; - --mono: "SF Mono", Menlo, Consolas, monospace; - --t-fast: .16s; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; - color: var(--ink); - font-size: 14px; - line-height: 1.7; -} -.proto-root, .proto-root * { box-sizing: border-box; } - -/* ==================== 卡壳(嵌进工作区,不自带浮起——外层已经是一张卡)==================== */ -.proto-root .jc-report { background: #fff; overflow: hidden; } - -.proto-root .jc-rp-head { display: flex; align-items: center; gap: 14px; padding: 18px 22px; border-bottom: 2px solid var(--ink); } -.proto-root .jc-report.tone-human .jc-rp-head { background: linear-gradient(120deg, #fffaf1 0%, #fff 55%, #fbf6ea 100%); } -.proto-root .jc-report.tone-ledger .jc-rp-head { background: linear-gradient(120deg, #fdf3f1 0%, #fff 55%, #fbf2f0 100%); } - -.proto-root .jc-rp-badge { - flex: none; width: 44px; height: 44px; border-radius: 10px; - display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 13px; -} -.proto-root .jc-report.tone-human .jc-rp-badge { background: var(--human); box-shadow: 0 6px 16px rgba(169,113,30,.25); } -.proto-root .jc-report.tone-ledger .jc-rp-badge { background: var(--ledger); box-shadow: 0 6px 16px rgba(178,58,46,.25); } - -.proto-root .jc-rp-tit { flex: 1; min-width: 0; } -.proto-root .jc-rp-tit em { font-style: normal; font-size: 11px; letter-spacing: .08em; color: var(--ink-4); font-weight: 700; } -.proto-root .jc-rp-tit h3 { margin: 2px 0 0; font-size: 19px; font-weight: 800; line-height: 1.3; } -.proto-root .jc-rp-sub { font-size: 12px; color: var(--ink-3); margin-top: 3px; } - -.proto-root .jc-rp-side { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; } -/* 目标件 side 第二行:步骤(静态文案),同目标件 .step 的字号字色 */ -.proto-root .jc-rp-step { font-size: 12px; color: var(--ink-3); } -/* 关联任务号:全长 UUID 如实给,排版上截尾 —— 截断是排版,不是数据 */ -.proto-root .jc-rp-taskid { - display: inline-block; max-width: 150px; overflow: hidden; text-overflow: ellipsis; - white-space: nowrap; vertical-align: bottom; font-family: var(--mono); font-size: 11px; -} -.proto-root .jc-rp-tag { font-size: 11px; font-weight: 800; padding: 2px 10px; border-radius: 999px; border: 1px solid; } -.proto-root .jc-report.tone-human .jc-rp-tag { color: var(--human); background: var(--human-soft); border-color: var(--human-line); } -.proto-root .jc-report.tone-ledger .jc-rp-tag { color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line); } -.proto-root .jc-rp-wait { font-size: 12px; color: var(--ink-3); } -.proto-root .jc-rp-wait.warn { color: var(--danger); font-weight: 700; } - -.proto-root .jc-rp-bd { padding: 20px 22px; } - -/* 【做什么】/【交回什么】这类分区小标——括号label + 破折号说明,同一行 */ -.proto-root .jc-rp-part { font-size: 11px; font-weight: 800; letter-spacing: .12em; color: var(--ink-4); margin: 20px 0 8px; } -.proto-root .jc-rp-part:first-child { margin-top: 0; } -.proto-root .jc-rp-part b { color: var(--ink-3); } - -/* AI 已完成 / 需要你 —— 说明框,左侧色条按 tone 走 */ -.proto-root .jc-derive { border: 1px solid var(--line); border-left: 3px solid; border-radius: 8px; background: var(--soft); padding: 14px 16px; margin-bottom: 16px; } -.proto-root .jc-report.tone-human .jc-derive { border-left-color: var(--human); } -.proto-root .jc-report.tone-ledger .jc-derive { border-left-color: var(--ledger); } -.proto-root .jc-derive p { margin: 0; font-size: 13px; color: var(--ink-2); } -.proto-root .jc-derive p + p { margin-top: 6px; } -.proto-root .jc-derive b { color: var(--ink); } -.proto-root .jc-derive .done { color: var(--ok); font-weight: 700; } -.proto-root .jc-report.tone-human .jc-derive .need { color: var(--human); font-weight: 700; } -.proto-root .jc-report.tone-ledger .jc-derive .need { color: var(--ledger); font-weight: 700; } - -/* 验收判据框——目标件里两份验收工单同一色(赭红),不随 tone 变 */ -.proto-root .jc-criteria { border: 1px solid var(--ledger-line); border-radius: 10px; background: var(--ledger-soft); padding: 13px 16px; margin-bottom: 18px; } -.proto-root .jc-criteria-t { font-size: 11px; font-weight: 800; letter-spacing: .08em; color: var(--ledger); margin-bottom: 7px; } -.proto-root .jc-criteria ul { margin: 0; padding-left: 18px; font-size: 12.5px; color: var(--ink-2); } -.proto-root .jc-criteria li { margin: 4px 0; } -.proto-root .jc-criteria b { color: var(--ink); } - -/* 表格基础排版(交互态的显隐开关在 BIND_CSS) */ -/* - * **表宽超出就得能横着滑**(2026-08-23 用户:「表格已经显示不全了,不能左右滑动」)。 - * 从前这里是 overflow: hidden —— 那是为了让圆角裁住表头,可它同时把超出的列 - * **直接裁掉且滑不动**:列一多(或某列为了放下下拉框加宽)就看不全,人还没有任何办法。 - * quote-* 各包一直是 overflow-x: auto,这两个新包抄版式时把这一条抄丢了。 - * (注释里不写反引号 —— 整段 CSS 是模版字符串,一个反引号就把它截断,本轮踩第三次。) - * 竖向仍 hidden:件是整篇铺开跟着外层滚的,表格自己不该再套一层竖滚动条。 - */ -.proto-root .jc-tbl-wrap { border: 1px solid var(--line-soft); border-radius: 10px; overflow-x: auto; overflow-y: hidden; margin-bottom: 4px; } - -/* - * 资料名 = 可点开的那一格(2026-08-23)。**看得出能点**才会有人点: - * 品牌蓝 + 下划虚线 + 手型;悬停实线。点了去哪由外层接(件里一行脚本也没有)。 - */ -.proto-root .jc-fileln { color: var(--brand); border-bottom: 1px dashed var(--brand-soft); cursor: pointer; transition: all var(--t-fast); } -.proto-root .jc-fileln:hover { border-bottom-style: solid; background: var(--brand-wash); } -/* 空标题不该长得像能点开 —— 那一格根本没有资料 */ -.proto-root .jc-fileln:empty { border-bottom: 0; cursor: default; background: none; } - -/* 格式徽:摆的是这份资料交出去时的样子(md / html / docx / xlsx) */ -.proto-root .jc-fmt { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 19px; - padding: 1px 7px; border-radius: 5px; font-size: 10px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; - background: var(--soft); color: var(--ink-3); border: 1px solid var(--line); } -.proto-root .jc-fmt.v-docx { background: #eaf1ff; color: #2b5fd9; border-color: #c3d6ff; } -.proto-root .jc-fmt.v-xlsx { background: #e9f7ee; color: #1f7a45; border-color: #bfe6cd; } -.proto-root .jc-fmt.v-html { background: #fdf0e6; color: #b25e15; border-color: #f3d3b4; } -.proto-root .jc-fmt.v-md { background: #f2f3f5; color: #5a6068; border-color: #dfe1e5; } -.proto-root .jc-tbl-in { width: 100%; border-collapse: collapse; font-size: 13px; } -.proto-root .jc-tbl-in th { text-align: left; background: var(--soft); font-size: 11px; letter-spacing: .04em; font-weight: 800; color: var(--ink-3); padding: 9px 11px; border-bottom: 1px solid var(--line); } -.proto-root .jc-tbl-in th.req::after { content: " *"; color: var(--danger); font-size: 11px; } -.proto-root .jc-tbl-in th.sug::after { content: " 建议"; color: var(--warn-accent); font-size: 10px; font-weight: 600; } -.proto-root .jc-tbl-in th.opt::after { content: " 选填"; color: var(--ink-4); font-size: 10px; font-weight: 600; } -.proto-root .jc-tbl-in td { padding: 9px 11px; border-bottom: 1px solid var(--line-soft); vertical-align: top; } -.proto-root .jc-tbl-in tr:last-child td { border-bottom: 0; } -.proto-root .jc-tbl-in td.jc-rn { width: 38px; white-space: nowrap; font-family: var(--mono); font-size: 11px; color: var(--ink-4); text-align: center; position: relative; } - -.proto-root .jc-vcell { display: block; font-size: 12.5px; color: var(--ink); line-height: 1.5; overflow-wrap: anywhere; } -.proto-root .jc-vcell.mono { font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); } -.proto-root .jc-vcell.cust { font-weight: 700; } -.proto-root .jc-vcell.dim { color: var(--ink-4); text-decoration: line-through; } -.proto-root .jc-diffnew { font-weight: 800; color: var(--ok); } - -.proto-root .jc-cell, .proto-root select.jc-cell, .proto-root textarea.jc-cell { - width: 100%; min-width: 60px; border: 1px solid var(--line); border-radius: 6px; - padding: 6px 8px; font: inherit; font-size: 12.5px; color: var(--ink); background: #fff; -} -.proto-root .jc-cell.mono { font-family: var(--mono); font-size: 11.5px; } -.proto-root .jc-cell:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-wash); outline: none; } - -.proto-root .jc-rowdel { - width: 22px; height: 22px; margin: 0 auto; cursor: pointer; - border: 1px solid var(--line); border-radius: 6px; padding: 0; - font: inherit; font-size: 14px; line-height: 1; color: var(--ink-3); background: #fff; - transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast); -} -.proto-root .jc-rowdel:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); } - -.proto-root .jc-addrow em { font-style: normal; font-size: 11.5px; color: var(--ink-4); } -.proto-root .jc-addrow button { - cursor: pointer; border: 1px solid var(--brand-soft); border-radius: 7px; padding: 5px 12px; - font: inherit; font-size: 12px; font-weight: 700; color: var(--brand-deep); background: var(--brand-wash); -} -.proto-root .jc-addrow button:hover { background: var(--brand-soft); } - -/* 本工单只承载内容,提交/审批请在对话区——目标件三份文件都有这一条 */ -.proto-root .jc-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); } -.proto-root .jc-flow b { color: var(--ink); } - -.proto-root .jc-rp-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; } -.proto-root .jc-rp-foot span:last-child { font-family: var(--mono); } -`; diff --git a/activities/part-substitution-assessment/src/views/report.ts b/activities/part-substitution-assessment/src/views/report.ts index ceb3637..4983aaa 100644 --- a/activities/part-substitution-assessment/src/views/report.ts +++ b/activities/part-substitution-assessment/src/views/report.ts @@ -1,724 +1,612 @@ /** * ACT-WORK-05 差异评估的 HTML 报告模版 —— **活动自己持有的资产**,随包版本冻结。 * - * 五个局面各一张: - * · `p08-master-create` —— S0d 摆,数据工单(P-08 芯片主数据),可加行、可编辑; - * · `p10-document-create` —— S0d 摆,数据工单(P-10 原厂技术资料),可加行、可编辑; - * · `eval-input-list` —— S0/S1 摆,评估输入清单:绑定区只读 + 缺口表可编辑; - * · `difference-review` —— S2/S3/S4 摆,各候选推荐等级 + 差异明细,**只读**(通过/驳回在对话区决策卡); - * · `landing-confirm` —— S5/T_release 摆,拟写 P-11 / 拟回写 P-01,**只读**,放行后即归档件。 + * 五个局面各一张,版面语言**逐块搬自** `docs/SS02-ACT-WORK-05-html/` 的四份目标件 + * (《HTML报告生成规范》§7:有目标件时「搬」,不要「照着做」——样式表整段搬,标记逐块搬, + * 只把写死的数据换成绑定): + * · `p08-master-create` —— S0d 摆,数据工单(P-08 芯片主数据),搬自「数据工单-01」; + * · `p10-document-create` —— S0d 摆,数据工单(P-10 原厂技术资料),**没有自己的目标件** + * (规格里数据工单是「一个统一模板按目标台账实例化」),复用「数据工单-01」的样式表与版面骨架; + * · `eval-input-list` —— S0/S1 摆,评估输入清单,搬自「执行工单-01」; + * · `difference-review` —— S2/S3/S4 摆,差异评估结论审核,搬自「验收工单-01」; + * · `landing-confirm` —— S5/T_release 摆,评审放行与落账确认,搬自「验收工单-02」。 * - * 版面语言逐字量自 `docs/SS02-ACT-WORK-05-html/` 四份目标件;取值三纪律:顶层只取汇总列与单值列, - * 逐条走 `mine:域.对象`,列名逐字照 `declarations.ledger` 抄。**模版不算不判**。 + * 目标件的样式表逐字节存在 `./target-style.ts`(`P08_CSS`/`EXEC_CSS`/`ACC1_CSS`/`ACC2_CSS`, + * 抽取与 diff 验证过程见 task-5-report.md)。**这份文件只做取值绑定,不算不判**; + * `BIND_COMMON`/`BIND_P08`/`BIND_EXEC`/`BIND_ACC1`/`BIND_ACC2` 是平台绑定层必须新增的东西 + * (目标件是写死数据的静态demo,没有「N 行草稿」「编辑态与归档态二选一」这些平台概念): + * 缺项红带、编辑闸/增删行按 `html.editable` 收起、序号列换成 CSS 计数器(目标件靠 JS 脚本 + * 重排数字,沙箱零脚本改用它)、`data-class-of` 的 `v-*` 别名(枚举列不许摆 ASCII 原值 —— + * 有色徽标的地方原样复制目标件自己那几条颜色声明当 `v-` 版,目标件本来是纯文字的地方 + * 就只补 `::after` 文案、不额外配色)。 */ -import { PRD_CSS } from './prd-style.ts'; +import { P08_CSS, EXEC_CSS, ACC1_CSS, ACC2_CSS } from './target-style.ts'; import { D } from '../constants.ts'; -/* ==================== - * 绑定期补的样式(原样复制自 E04 `activities/crm-relationship-coverage/src/views/report.ts` - * 第 25–211 行的 `BIND_CSS`,共 187 行 —— 不是 I01 那份(裁决:见任务交底)。 - * 原因:本活动的件里有「只读格与可改格同表混排」(枚举列是 `(手写 input 会不填值,人一点编辑就是白框) */ const cell = (col: string, cls = ''): string => ``; -const ro = (col: string, cls = ''): string => ``; +/** 只读格:即便挂在可改的表里也不许被 `table.on` 藏起来 —— 目标件自己就有这条覆盖(`.jc-vcell.ro`) */ +const ro = (col: string, cls = ''): string => ``; const select = (col: string, options: ReadonlyArray, required = false): string => ``; +/** 枚举徽标(可改表里用,旁边挨着 `.jc-cell` 孪生件时要包一层 `.ro` 才不被编辑态藏起来) */ +const badge = (klass: string, col: string, wrapRo = false): string => { + const inner = ``; + return wrapRo ? `${inner}` : inner; +}; -/* ==================== 局面 0 · 数据工单 P-08 ==================== */ +/* ==================== 局面 0 · 数据工单 P-08(搬自「数据工单-01」)==================== */ -const P08_TABLE = `
+const P08_TABLE = `
- - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + +
内部料号品牌制造商规格描述封装工艺生命周期EOL / PCNDatasheet 引用Datasheet 版本适配场景标准化参数集(一行一参数:参数名 | 值 | 单位 | hard/soft | 说明)#内部料号 internal_pn全链路统一基准,不可自由文本品牌 brand_name与制造商、供应商分开制造商 manufacturer_name与品牌不一致时分开记录规格描述 specification_description按原厂资料口径封装 package影响硬约束比对工艺 process_technology硬约束比较项生命周期 lifecycle_statusActive/NRND/EOL/停产/风险EOL/PCN eol_pcn_status通知/影响/生效时间Datasheet 引用 datasheet_refDatasheet 版本 datasheet_version与引用成对适配场景 application_scenarios判断实际适用性标准化参数集 normalized_parameter_set一行一参数:参数名|值|单位|hard/soft|说明
${cell('internal_pn', 'mono')}${cell('brand_name')}${cell('manufacturer_name')}${cell('specification_description')}${cell('package', 'mono')}${cell('process_technology')}${select('lifecycle_status', [['active', 'Active'], ['nrnd', 'NRND'], ['eol', 'EOL'], ['discontinued', '停产'], ['risk', '风险']], true)}${tag('t-life', 'lifecycle_status')}${cell('eol_pcn_status')}${cell('datasheet_ref', 'mono')}${cell('datasheet_version')}${cell('application_scenarios')}${cell('internal_pn', 'mono')}${cell('brand_name')}${cell('manufacturer_name')}${cell('specification_description')}${cell('package', 'mono')}${cell('process_technology')}${badge('stx', 'lifecycle_status', true)}${select('lifecycle_status', [['active', 'Active'], ['nrnd', 'NRND'], ['eol', 'EOL'], ['discontinued', '停产'], ['risk', '风险']], true)}${cell('eol_pcn_status')}${cell('datasheet_ref', 'mono')}${cell('datasheet_version')}${cell('application_scenarios')}
`; export const P08_MASTER_CREATE = doc({ - tone: 'human', + css: P08_CSS, + alias: BIND_P08, badge: '数据', + hic: HIC, tag: '数据工单', - kicker: 'SS02 · ACT-WORK-05 差异评估 · 数据工单(P-08)', - title: '芯片主数据创建', + kicker: 'SS02 · ACT-WORK-05 差异评估 · 数据工单 1/2', + title: '芯片主数据创建(P-08)', step: '步骤 0.5 · 等待数据', - state: `待建 / 行`, + footTag: '工单类型:数据', body: - part('做什么', '批量创建 P-08 主数据记录') + - `
-

模板定位:本单是「数据工单」的实例 —— 一单一类(可多条):目标台账 = 芯片主数据(P-08); - 字段即表头、每行一条新记录;标准化参数集是这条记录的一个字段(一行一参数)。

-

触发原因:系统按内部料号查芯片主数据查无记录 —— 是「完全没有」,不是字段缺失(那归执行工单)。

-

AI 预填:上传了 datasheet 的料号 AI 已按资料预填,标着值的格子请核对;没上传的料号全部手填,同为合法路径。

-

纪律:必填列全齐才允许确认;确认后这批记录进本单草稿,放行时并入正式库并留痕(确认人 = 数据责任人);只建主数据,验证记录等事实类不在此建。

-
` + - part('创建什么', '主数据记录(每行一条,*为必填列)') + + zone('做什么', '批量创建 P-08 主数据记录', ZIC_TASK) + + note([ + '模板定位:本单是「数据工单」统一模板的实例——一单一类(可多条):目标台账 = 芯片主数据(P-08);字段即表头、每行一条新记录;标准化参数集是这条记录的一个字段(一行一参数)。', + '触发原因:系统按内部料号查芯片主数据查无记录——是「完全没有」,不是字段缺失(那归执行工单)。', + 'AI 预填:上传了 datasheet 的料号 AI 已按资料预填,标着值的格子请核对;没上传的料号全部手填,同为合法路径。', + '纪律:必填列全齐才允许确认;确认后这批记录进本单草稿,放行时并入正式库并留痕(确认人 = 数据责任人);只建主数据,验证记录等事实类不在此建。', + ]) + + zone('创建什么', '主数据记录(每行一条,*为必填列)', ZIC_TABLE) + gapbar('parts_profile', '必填') + editGate('parts.profile', `待建 条记录,点「编辑」核对预填、补齐空缺;「+ 加一行」= 再建一条`) + - `
必填列(*)全齐才允许确认;原厂未披露的参数值请直接写「未披露」,它会进入 UNKNOWN 并挂验证任务;删一行 = 该记录不建。改动只落任务草稿层,保存不等于放行。
` + P08_TABLE + - `
- - 新行的内部料号必须写(它是这一行的钥匙);其余必填列全部填写后才允许确认。 -
` + + addrow('parts.profile', '+ 加一行(再建一条记录)', '新行的内部料号必须写(它是这一行的钥匙);其余必填列全部填写后才允许确认;删一行 = 该记录不建') + flow('提交 / 确认:本工单只承载内容;确认请在对话区的【执行卡】中进行。确认后活动自动从「等待数据」唤醒。'), - foot: sign('SS02 · ACT-WORK-05 差异评估 · 数据工单 · 芯片主数据创建(P-08)', '工单类型:数据'), }); -/* ==================== 局面 0′ · 数据工单 P-10 ==================== */ +/* ==================== 局面 0′ · 数据工单 P-10(复用「数据工单-01」的样式与骨架,没有独立目标件)==================== */ -const P10_TABLE = `
+const P10_TABLE = `
- - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + +
关联料号序号资料类型品牌资料标题版本文件链接证据定位状态#关联料号 internal_pn对应 P-08 那条记录资料序号 doc_seq同一料号下 01/02… 自己续资料类型 document_type品牌 brand_name资料标题 document_title资料版本 document_version文件链接 document_ref证据定位 citation_locator页码/章节/表格资料状态 document_status
${cell('internal_pn', 'mono')}${cell('doc_seq', 'mono')}${select('document_type', [['datasheet', 'Datasheet'], ['app_note', '应用笔记'], ['reference_design', '参考设计'], ['white_paper', '白皮书'], ['sample_doc', '样片资料'], ['commitment_letter', '承诺函'], ['other', '其他']], true)}${tag('t-doc', 'document_type')}${cell('brand_name')}${cell('document_title')}${cell('document_version')}${cell('document_ref', 'mono')}${cell('citation_locator')}${select('document_status', [['valid', '有效'], ['expired', '过期'], ['pending', '待核实'], ['void', '作废']], true)}${tag('t-docst', 'document_status')}${cell('internal_pn', 'mono')}${cell('doc_seq', 'mono')}${badge('stx', 'document_type', true)}${select('document_type', [['datasheet', 'Datasheet'], ['app_note', '应用笔记'], ['reference_design', '参考设计'], ['white_paper', '白皮书'], ['sample_doc', '样片资料'], ['commitment_letter', '承诺函'], ['other', '其他']], true)}${cell('brand_name')}${cell('document_title')}${cell('document_version')}${cell('document_ref', 'mono')}${cell('citation_locator')}${badge('stx', 'document_status', true)}${select('document_status', [['valid', '有效'], ['expired', '过期'], ['pending', '待核实'], ['void', '作废']], true)}
`; export const P10_DOCUMENT_CREATE = doc({ - tone: 'human', + css: P08_CSS, + alias: BIND_P08, badge: '数据', + hic: HIC, tag: '数据工单', - kicker: 'SS02 · ACT-WORK-05 差异评估 · 数据工单(P-10)', - title: '原厂技术资料创建', + kicker: 'SS02 · ACT-WORK-05 差异评估 · 数据工单 2/2', + title: '原厂技术资料创建(P-10)', step: '步骤 0.5 · 等待数据', - state: `待建 / 行`, + footTag: '工单类型:数据', body: - part('做什么', '为本单新建的料号登记原厂资料(P-10)') + - `
-

触发原因:按内部料号查原厂技术资料库查无记录。一份资料一行;同一料号多份资料序号 01/02… 自己续。

-

为什么要它:差异明细的证据引用要指到具体资料的版本与页码 —— 没有这一行,结论就追溯不到来源。

-
` + - part('创建什么', '资料记录(每行一条,*为必填列)') + + zone('做什么', '为本单新建的料号登记原厂资料(P-10)', ZIC_TASK) + + note([ + '模板定位:与 P-08 同一套「数据工单」统一模板——目标台账 = 原厂技术资料库(P-10);一份资料一行,同一料号多份资料序号 01/02… 自己续。', + '触发原因:按内部料号查原厂技术资料库查无记录(P-08 那张先确认过,这一批料号才会走到这里)。', + '为什么要它:差异明细的证据引用要指到具体资料的版本与页码——没有这一行,结论就追溯不到来源。', + ]) + + zone('创建什么', '资料记录(每行一条,*为必填列)', ZIC_TABLE) + gapbar('parts_document', '必填') + editGate('parts.document', `待建 条资料记录,点「编辑」补齐`) + - `
资料类型、标题、版本、文件链接、状态为必填;证据定位写页码或章节。改动只落任务草稿层,保存不等于放行。
` + P10_TABLE + - `
- - 关联料号与序号是这一行的钥匙,新行都要写;必填列全齐才允许确认。 -
` + + addrow('parts.document', '+ 加一行(再登记一份资料)', '关联料号与序号是这一行的钥匙,新行都要写;必填列全齐才允许确认;删一行 = 该资料不建') + flow('提交 / 确认:本工单只承载内容;确认请在对话区的【执行卡】中进行。'), - foot: sign('SS02 · ACT-WORK-05 差异评估 · 数据工单 · 原厂技术资料创建(P-10)', '工单类型:数据'), }); -/* ==================== 局面 1 · 评估输入清单(S0/S1)==================== */ +/* ==================== 局面 1 · 评估输入清单(搬自「执行工单-01」)==================== */ -const PN_CHECK_TABLE = `
+const PN_CHECK_TABLE = `
- - - - - + + + + + - - - - - + + + + +
料号角色在库状态备注 / 放弃原因#料号角色在库状态备注 / 放弃原因
${ro('internal_pn', 'mono')}${tag('t-role', 'role')}${tag('t-exist', 'exists_status')} ${ro('internal_pn', 'mono')}${badge('st', 'exists_status', true)}${ro('note')} ${ro('abandon_reason')}
`; -const GAP_TABLE = `
+const GAP_TABLE = `
- - - - - - - + + + + + + - - - - - - - + + + + + +
键输入项来源状态绑定值 / 缺口说明补充内容#输入项来源状态绑定值 / 缺口说明补充内容
${cell('item_key', 'mono')}${cell('input_item')}${cell('source_ledger', 'mono')}${select('status', [['gap', '待补'], ['default', '默认·可改'], ['ok', '齐备']])}${tag('t-gap', 'status')}${cell('detail')}${cell('input_item')}${cell('source_ledger', 'mono')}${badge('st', 'status', true)}${cell('detail')}${cell('supplement')}
`; export const EVAL_INPUT_LIST = doc({ - tone: 'human', + css: EXEC_CSS, + alias: BIND_EXEC, badge: '执行', tag: '执行工单', kicker: 'SS02 · ACT-WORK-05 差异评估 · 执行工单 1/1', title: '评估输入与资料补齐确认', step: '步骤 1/5 · 建立评估上下文', - state: `待补 项`, + footTag: '工单类型:执行', body: - part('做什么', '启动 4 项已绑定,其余信息在工单里补齐') + - `
-

AI 已完成:系统已按启动传入的 4 项完成绑定 —— 客户、客户需求(新建 P-01 · 版本 V1)、原 PN、候选 PN(数组,逐个评估)—— 并生成输入快照。

-

需要你补齐:启动时未收的信息(应用场景、BOM 位)直接在下表补;默认值(替代类型 / 规则版本 / 负责人期限)可确认可改。本单缺口只覆盖「有而不全」;「完全没有」(料号不在库)已由数据工单创建。未补齐的缺口项将按 UNKNOWN 进入差异评估。

-
` + - part('已绑定', '启动时冻结,工单内不可改 —— 绑错请退回启动人重新启动') + - `
- 客户 - 客户需求 · V1 · - 原内部料号 - 规则版本 -
` + + zone('做什么', '启动 4 项已绑定,其余信息在工单里补齐') + + note([ + 'AI 已完成:系统已按启动传入的 4 项完成绑定——客户、客户需求(新建 P-01 · 版本 V1)、原 PN、候选 PN(数组,逐个评估)——并生成输入快照。', + '需要你补齐:启动时未收的信息(应用场景、BOM 位)直接在下表补;默认值(替代类型 / 规则版本 / 负责人期限)可确认可改。本单缺口只覆盖「有而不全」;「完全没有」(料号不在库)已由数据工单创建。未补齐的缺口项将按 UNKNOWN 进入差异评估。', + ]) + + zone('料号存在性核对', '只读参考 · 与下表「补充内容」互不冲突') + PN_CHECK_TABLE + - part('交回什么', '评估输入清单(已绑定项只读核对,缺口项补齐,*为必填)') + + zone('交回什么', '评估输入清单(已绑定项照实核对,缺口项补齐,*为必填)') + gapbar(`${D}_input_gap`, '补充内容') + - editGate(`${D}.input_gap`, `还有 项待补 / 待确认,点「编辑」在「补充内容」列填入`) + - `
加一行 = 补充 AI 未列出的资料项(新行的「输入项」与「补充内容」必填);删一行 = 该输入项不适用;补不了的写「留 UNKNOWN」或「挂验证任务」—— 那也是一个答案。改动只落任务草稿层,保存不等于放行。
` + + editGate(`${D}.input_gap`, `还有 项待补 / 待确认,点「编辑」在「补充内容」列填入 —— 已绑定那几行的「输入项/来源/绑定值」抄的是启动入参,发现记录本身有误请退回触发方重新启动,不要在这里改`) + GAP_TABLE + - `
- - 键写一个英文短名(如 thermal_note);「绑定值 / 缺口说明」栏写清这项资料是什么、AI 为什么拿不到。 -
` + - flow('审批 / 提交:本工单只承载内容;「提交」请在对话区的【执行卡】中进行。提交后去向:进入步骤 2 · AI 读取与标准化,仍缺失的项将按 UNKNOWN 进入差异评估。'), - foot: sign('SS02 · ACT-WORK-05 差异评估 · 执行工单 1/1 · 评估输入与资料补齐确认', '工单类型:执行'), + addrow(`${D}.input_gap`, '+ 加一行(补充资料项)', '新加行的「输入项」与「补充内容」为必填;删一行 = 该输入项不适用;补不了的写「留 UNKNOWN」或「挂验证任务」') + + flow( + '审批 / 提交:本工单只承载内容;「提交」请在对话区的【执行卡】中进行。提交后去向:进入步骤 2 · AI 读取与标准化,仍缺失的项将按 UNKNOWN 进入差异评估。注意:启动参数如有误,需退回触发方修订后重新触发,本单不可改。', + ), }); -/* ==================== 局面 2 · 差异评估结论审核(S2/S3/S4,只读)==================== */ +/* ==================== 局面 2 · 差异评估结论审核(搬自「验收工单-01」)==================== */ -const RELATION_TABLE = `
+const RELATION_SUMMARY_TABLE = `
- - - - - - - - - + + + + + + + - - - - - - - - - + + + + + + +
候选料号替代类型推荐等级推荐理由差异摘要风险验证要求置信度#候选料号替代类型推荐等级风险等级推荐理由差异摘要
${ro('candidate_internal_pn', 'mono')}${tag('t-sub', 'substitution_type')}${tag('t-rec', 'recommendation_level')}${ro('recommendation_reason')}${ro('difference_summary')}${tag('t-risk', 'risk_level')}${ro('verification_requirement')}${ro('confidence_score', 'mono')}${badge('st rec', 'recommendation_level')}${badge('risk', 'risk_level')}
`; -const ITEM_TABLE = `
- - - - - - - - - - - - - - - +const DIFFERENCE_ITEM_TABLE = `
关系参数项原 PN 值候选 PN 值单位约束类型结论风险证据引用影响说明UNKNOWN 去向置信度
+ - - - - - - - - - - - - - + + + + + + + + + +
#参数项 parameter_name原 PN 值 original_value候选 PN 值 candidate_value单位 parameter_unit约束类型 constraint_type结论 difference_status风险等级证据引用 evidence_refAI 置信度
${ro('substitution_relation_id', 'mono')}${ro('original_value', 'mono')}${ro('candidate_value', 'mono')}${ro('parameter_unit')}${tag('t-con', 'constraint_type')}${tag('t-diff', 'difference_status')}${tag('t-risk', 'risk_level')}${ro('evidence_ref', 'mono')}${ro('impact_statement')}${ro('unknown_disposition')}${ro('confidence', 'mono')}${badge('st dst', 'difference_status')}${badge('risk', 'risk_level')}
`; export const DIFFERENCE_REVIEW = doc({ - tone: 'ledger', + css: ACC1_CSS, + alias: BIND_ACC1, badge: '验收', tag: '验收工单', kicker: 'SS02 · ACT-WORK-05 差异评估 · 验收工单 1/2', title: '差异评估结论审核', step: '步骤 3~4/5 · 逐项差异评估 + FAE/RI 审核', - state: `共 个候选 · 条比对`, + footTag: '工单类型:验收', body: - part('AI 结论说明', '结论是怎么算出来的') + - `
-

AI 已完成的计算:按 GOV 评估规则(锁定版本 ),对原 PN - 与每个候选逐项比对,四态结论 —— MATCH / - MISMATCH / - UNKNOWN / - CONDITIONAL ,并给出风险等级、证据引用与置信度。 - 差异明细 = P-11 差异明细子表(一条参数一条记录);当前为 AI 草稿,审核通过前不落账。本单数据工单创建的主数据,其参数证据标注「人工录入」。

-
` + - part('验收判据', '你据此判断「通过 / 驳回」') + + zone('AI 结论说明', '结论是怎么算出来的') + + note([ + 'AI 已完成的计算:按 GOV 评估规则(锁定版本 ),对原 PN 与每个候选逐项比对,产出四态结论——MATCH / MISMATCH / UNKNOWN / CONDITIONAL,并给出风险等级、证据引用与置信度。差异明细 = P-11 差异明细子表(一条参数差异一条记录);当前为 AI 草稿,FAE 审核通过前不落账。评估参数可能含本次数据工单创建的主数据(确认人背书;未附 datasheet 的参数项会显式标注「人工录入」)。', + ]) + criteria('判断这份差异评估结论是否可信,请逐项核对', [ '关键参数差异均有明确状态:逐项结论无漏项,每个参数都有四态之一的判定;', 'UNKNOWN 项均有去向:每个 UNKNOWN 都挂了验证任务或补来源动作,不允许悬空;', - '证据链完整:每项结论可追溯至 P-08 / P-10 / P-06 的具体记录,或本单数据工单的创建记录(人工录入);', + '证据链完整:每项结论可追溯至 P-08 / P-10 / P-06 的具体记录,或本单数据工单的创建记录(标注:人工录入);', '硬约束项未被自动判 MATCH:封装 / 工艺等硬约束未经证据支持不得判 MATCH。', ]) + - part('各候选推荐等级', '只读展示 · 每个候选一条 P-11 主记录草稿') + - RELATION_TABLE + - part('AI 产出的差异明细', '只读展示 · P-11 差异明细子表草稿') + - ITEM_TABLE + - flow('审批:本工单只承载内容;「通过 / 驳回」请在对话区的【验收卡】中进行。审核意见与补充条件写入 P-06(验证要求);通过后去向:进入步骤 5 · 评审放行与落账确认。'), - foot: sign('SS02 · ACT-WORK-05 差异评估 · 验收工单 1/2 · 差异评估结论审核', '工单类型:验收'), + zone('各候选推荐等级', '只读展示(P-11 主记录草稿,一个候选一条)') + + RELATION_SUMMARY_TABLE + + zone('AI 产出的差异明细', '只读展示(P-11 差异明细子表草稿 · 一条参数一条记录 difference_item_id)') + + DIFFERENCE_ITEM_TABLE + + flow( + '审批:本工单只承载内容;「通过 / 驳回」请在对话区的【验收卡】中进行。审核意见与补充条件写入 P-06(验证要求 verification_requirement);通过后去向:进入步骤 5 · 评审放行与落账确认。', + ), }); -/* ==================== 局面 3 · 评审放行与落账确认(S5/T_release,只读)==================== */ +/* ==================== 局面 3 · 评审放行与落账确认(搬自「验收工单-02」)==================== */ -const P11_TABLE = `
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/** 字段:值 两列表 —— 逐字节搬自目标件「拟写 P-11」「拟回写 P-01」的版式(一行一个字段), + * 用 `data-rows` 包一整张小表当行模版,一个候选 / 一条需求各重复出一份,天然支持多候选。 */ +const P11_FIELD_TABLE = `
替代关系ID替代类型原内部料号候选内部料号推荐等级推荐理由差异摘要替代分析报告分析状态客户批准状态风险验证要求证据可信度规则版本
${ro('substitution_relation_id', 'mono')}${tag('t-sub', 'substitution_type')}${ro('original_internal_pn', 'mono')}${ro('candidate_internal_pn', 'mono')}${tag('t-rec', 'recommendation_level')}${ro('recommendation_reason')}${ro('difference_summary')}${ro('analysis_report_ref', 'mono')}${tag('t-anal', 'analysis_status')}未提交 由审批流程维护,本活动不产生${tag('t-risk', 'risk_level')}${ro('verification_requirement')}${ro('confidence_score', 'mono')}${ro('rule_version', 'mono')}
+ + + + + + + + + + + + + + + +
#字段拟写入值
替代类型 substitution_type
原内部料号 original_internal_pn
候选内部料号 candidate_internal_pn
推荐等级 recommendation_level${badge('st', 'recommendation_level')} (枚举:推荐 / 条件推荐 / 备选 / 不推荐,四态之一)
推荐理由 recommendation_reason
差异摘要 difference_summary
替代分析报告 analysis_report_ref
分析状态 analysis_status${badge('st', 'analysis_status')} (枚举:AI草稿 / FAE确认 / 待客户验证 / 客户已批准 / 不批准 / 作废)
客户批准状态 customer_approval_status未提交 (由审批流程维护,本活动不产生)
风险等级 risk_level${badge('risk', 'risk_level')}
验证要求 verification_requirement
证据可信度 confidence_score
差异规则版本 rule_version
`; -const P01_TABLE = `
- - - - - - - - - - - - - - - - - - - - +const P01_FIELD_TABLE = `
需求编号风险等级验证要求输出链接下一步动作当前阶段需求状态
${ro('request_id', 'mono')}${tag('t-risk', 'risk_level')}${ro('verification_requirement')}${ro('output_ref', 'mono')}${ro('next_action')}${tag('t-stage', 'current_stage')}${tag('t-reqstat', 'request_status')}
+ + + + + + + + +
#字段拟写入值
风险等级 risk_level${badge('risk', 'risk_level')}
验证要求 verification_requirement
输出链接 output_ref
下一步动作 next_action
当前阶段 current_stage${badge('st', 'current_stage')}
需求状态 request_status${badge('st', 'request_status')}
`; export const LANDING_CONFIRM = doc({ - tone: 'ledger', + css: ACC2_CSS, + alias: BIND_ACC2, badge: '验收', tag: '验收工单', kicker: 'SS02 · ACT-WORK-05 差异评估 · 验收工单 2/2', title: '评审放行与落账确认', step: '步骤 5/5 · 提交 ACT-GATE-03', - state: `拟落账 条 P-11`, + footTag: '工单类型:验收', body: - part('AI 结论说明', '本单确认什么') + - `
-

本活动以 ACT-GATE-03 评审放行为终点。本单确认拟落账内容:评估结论层写 P-11 替代关系主记录(每个候选一条)与差异明细子表,需求状态回写 P-01(风险等级 / 验证要求 / 输出链接 / 下一步动作 / 当前阶段)。 - 客户批准不属于本活动 —— 客户批准状态由审批流程维护,本单只写分析层(分析状态 = FAE 确认)。

-
` + - part('验收判据', '你据此判断「通过 / 驳回」') + + zone('AI 结论说明', '本单确认什么') + + note([ + '本活动以 ACT-GATE-03 评审放行为终点。本单确认拟落账内容:评估结论层写 P-11 替代关系主记录(替代类型 / 原内部料号 / 候选内部料号 / 推荐等级 / 推荐理由 / 差异摘要 / 替代分析报告 / 分析状态 / 风险等级 / 验证要求 / 证据可信度 / 差异规则版本),需求状态回写 P-01(风险等级 / 验证要求 / 输出链接 / 下一步动作 / 当前阶段)。客户批准不属于本活动——客户批准状态由审批流程维护,本单只写分析层(分析状态 = FAE 确认),customer_approval_status 保持「未提交」,不由差异评估产生。', + ]) + criteria('放行与落账前,请逐项核对', [ - '推荐等级与差异明细一致:存在 UNKNOWN / CONDITIONAL 的候选,推荐等级不得给「推荐」;', - '分析状态与客户批准状态分离:本单只写分析层(FAE 确认),客户批准状态保持「未提交」;', + '推荐等级与差异明细一致:差异明细中存在 UNKNOWN / CONDITIONAL 时,推荐等级不得给「推荐」;', + '分析状态与客户批准状态分离:本单只写分析层(分析状态 = FAE 确认),客户批准状态保持「未提交」;', 'GOV 规则版本已锁定:规则版本随结论一并落账;', '回写 P-01 字段完整:风险等级、验证要求、输出链接、下一步动作、当前阶段五项齐全。', ]) + - part('拟写 P-11 · 替代关系主记录', '只读展示') + - P11_TABLE + - part('拟回写 P-01 · 需求状态', '只读展示') + - P01_TABLE + - flow('审批:本工单只承载内容;「通过 / 驳回」请在对话区的【验收卡】中进行。通过后去向:P-11 落账、P-01 回写、放行;结论供 ACT-WORK-08 证据归集消费。'), - foot: sign('SS02 · ACT-WORK-05 差异评估 · 验收工单 2/2 · 评审放行与落账确认', '工单类型:验收'), + zone('拟写 P-11 · 替代关系主记录', '只读展示') + + P11_FIELD_TABLE + + zone('拟回写 P-01 · 需求状态', '只读展示') + + P01_FIELD_TABLE + + flow( + '审批:本工单只承载内容;「通过 / 驳回」请在对话区的【验收卡】中进行。通过后去向:在对话区卡提交 ACT-GATE-03 评审放行;放行后结论供 ACT-WORK-08 证据归集消费。', + ), }); diff --git a/activities/part-substitution-assessment/src/views/target-style.ts b/activities/part-substitution-assessment/src/views/target-style.ts new file mode 100644 index 0000000..3026657 --- /dev/null +++ b/activities/part-substitution-assessment/src/views/target-style.ts @@ -0,0 +1,336 @@ +/** + * ACT-WORK-05 差异评估的四份目标件样式表 —— **机械抽取,一个数值都不许改** + * (《HTML报告生成规范》§7:有目标件时「搬」,不要「照着做」;样式表整段搬,标记逐块搬)。 + * + * 来源(`docs/SS02-ACT-WORK-05-html/`): + * · `P08_CSS` ← `ACT-WORK-05-数据工单-01-芯片主数据创建.html` 的两段 `` 之间的原文,再拿抽出来的内容包回 + * `` 与源文件同一行区间做 `diff`,四份全部「零差异」——过程写在 + * task-5-report.md,这里不重复贴证据。 + * + * 这份文件只装**目标件自己的样式**,不装平台绑定用的开关(三态占位、缺项红带、 + * `data-class-of` 的 `v-*` 别名这类)——那些是本活动自己加出来的东西,活在 + * `report.ts` 的 `BIND_CSS_*` 常量里,两处不要混。 + */ + +export const P08_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; + --ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9; + --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:#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,#f0f5ff 0%,#fff 55%,#eef4ff 100%)} +.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--data);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(51,112,255,.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} +.tit .sub{font-size:12px;color:var(--ink-3);margin-top:3px} +.side{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:none} +.tag{font-size:11px;font-weight:800;padding:2px 10px;border-radius:999px;color:var(--data);background:var(--data-soft);border:1px solid var(--data-line)} +.step{font-size:12px;color:var(--ink-3)} +.deadline{font-size:12px;color:var(--ink-3)} +.deadline b{color:var(--danger)} +.card-bd{padding:20px 22px} +.zone{font-size:11px;font-weight:800;letter-spacing:.12em;color:var(--ink-4);margin:0 0 8px} +.zone b{color:var(--ink-3)} +.note{border:1px solid var(--line);border-left:3px solid var(--data);border-radius:8px;background:var(--soft);padding:14px 16px;margin-bottom:16px} +.note p{margin:0 0 6px;font-size:13px;color:var(--ink-2)} +.note p:last-child{margin-bottom:0} +.note b{color:var(--ink)} +.note .done{color:var(--ok);font-weight:700} +.note .need{color:var(--data);font-weight:700} +.jc-editgate{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:14px 0 10px;padding:9px 12px;border-radius:9px;background:var(--soft);border:1px solid var(--line-soft);font-size:12px;color:var(--ink-3)} +.jc-editgate-t{flex:1 1 auto;min-width:0} +.jc-editgate-t b{color:var(--ink-2);font-weight:700} +.jc-egbtn{flex:none;display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:1px solid var(--line);border-radius:7px;padding:6px 13px;font:inherit;font-size:12px;font-weight:700;color:var(--ink-2);background:#fff;transition:border-color .16s,color .16s,background .16s} +.jc-egbtn:hover{border-color:var(--brand);color:var(--brand)} +.jc-egbtn.save{color:#fff;background:var(--data);border-color:var(--data)} +.jc-egbtn.save:hover{filter:brightness(1.06);color:#fff} +.jc-editgate .eg-cancel,.jc-editgate .eg-save{display:none} +.jc-editgate.on{background:var(--brand-wash);border-color:var(--data-line);color:#1e40af} +.jc-editgate.on .eg-open{display:none} +.jc-editgate.on .eg-cancel,.jc-editgate.on .eg-save{display:inline-flex} +.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:.03em;font-weight:800;color:var(--ink-3);padding:9px 10px;border-bottom:1px solid var(--line)} +th.req::after{content:" *";color:var(--danger);font-size:11px} +td{padding:8px 10px;border-bottom:1px solid var(--line-soft);vertical-align:middle} +tr:last-child td{border-bottom:0} +td.rn{position:relative;width:38px;white-space:nowrap;font-family:var(--mono);font-size:11px;color:var(--ink-4);text-align:center} +.jc-vcell{display:block;font-size:12.5px;color:var(--ink);line-height:1.5;overflow-wrap:anywhere} +.jc-vcell.mono{font-family:var(--mono);font-size:11.5px;color:var(--ink-2)} +.jc-cell{display:none;width:100%;min-width:60px;border:1px solid var(--line);border-radius:6px;padding:6px 8px;font:inherit;font-size:12.5px;color:var(--ink);background:#fff} +.jc-cell.mono{font-family:var(--mono);font-size:11.5px} +.jc-cell:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-wash);outline:none} +table.on td>.jc-vcell{display:none} +table.on td>.jc-cell{display:block} +td.rn .jc-rowdel{display:none;width:22px;height:22px;margin:0 auto;cursor:pointer;border:1px solid var(--line);border-radius:6px;padding:0;font:inherit;font-size:14px;line-height:1;color:var(--ink-3);background:#fff} +td.rn .jc-rowdel:hover{border-color:var(--danger);color:var(--danger);background:var(--danger-soft)} +table.on td.rn .jc-rn-num{display:none} +table.on td.rn .jc-rowdel{display:block} +.jc-addrow{display:none;margin:8px 0 0;padding:8px 12px;border-radius:9px;background:var(--soft);border:1px dashed var(--line);font-size:12px;color:var(--ink-3)} +.jc-addrow.show{display:flex;align-items:center;gap:8px} +.jc-addrow button{cursor:pointer;border:1px solid var(--brand-soft);border-radius:7px;padding:5px 12px;font:inherit;font-size:12px;font-weight:700;color:var(--brand-deep);background:var(--brand-wash)} +.jc-addrow button:hover{background:var(--brand-soft)} +.jc-addrow em{font-style:normal;font-size:11.5px;color:var(--ink-4)} +.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}} +/* 补充:数据工单专用标识(仅追加,不改动基件样式) */ +.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)} +.pre{font-style:normal;font-size:10.5px;font-weight:800;color:var(--data);background:var(--data-soft);border:1px solid var(--data-line);border-radius:999px;padding:0 7px;margin-left:6px;white-space:nowrap} +table.on td>.pre{display:none} +.ct{display:inline-block;font-size:11px;font-weight:700;padding:1px 8px;border-radius:999px;border:1px solid transparent;white-space:nowrap} +.ct.hard{color:var(--danger);background:var(--danger-soft);border-color:#f3b9b5} +.ct.soft{color:var(--ink-3);background:#eef1f6;border-color:var(--line)} +.tbl-gap{margin-top:18px} +/* ===== 视觉补充段 v3(通用批量模板:字段即表头、每行一条;不改基件样式与 JS 钩子) ===== */ +.hic{flex:none;width:26px;height:26px;color:var(--data)} +.zic{width:14px;height:14px;color:var(--ink-3);vertical-align:-2px;margin-right:3px} +/* 表头内字段说明(第二行小字) */ +.thd{display:block;font-size:10px;font-weight:600;color:var(--ink-4);letter-spacing:0;margin-top:1px;line-height:1.4} +/* 表 1:字段即表头,内容多列,允许横向滚动 */ +#tbl1{min-width:1240px} +#tbl1 .jc-vcell{display:inline} +/* 表 2 列宽 */ +#tbl2 th:nth-child(2){width:150px} +#tbl2 th:nth-child(3){width:18%} +#tbl2 th:nth-child(4){width:14%} +#tbl2 th:nth-child(5){width:8%;text-align:center;white-space:nowrap} +#tbl2 th:nth-child(6){width:13%;text-align:center;white-space:nowrap} +#tbl2 td:nth-child(5),#tbl2 td:nth-child(6){text-align:center;white-space:nowrap} +/* 说明列(只读注释,编辑态保持可见) */ +.desc{color:var(--ink-3);font-size:12px;line-height:1.5} +table.on td>.jc-vcell.ro{display:block} +.tbl-wrap{overflow-x:auto} +@media (prefers-reduced-motion: reduce){*{animation:none!important;transition:none!important}} +`; + +export const EXEC_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; + --human:#a9711e; --human-soft:#f6ecd8; --human-line:#e6d3a8; + --ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9; + --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:#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,#fffaf1 0%,#fff 55%,#fbf6ea 100%)} +.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--human);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(169,113,30,.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} +.tit .sub{font-size:12px;color:var(--ink-3);margin-top:3px} +.side{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:none} +.tag{font-size:11px;font-weight:800;padding:2px 10px;border-radius:999px;color:var(--human);background:var(--human-soft);border:1px solid var(--human-line)} +.step{font-size:12px;color:var(--ink-3)} +.deadline{font-size:12px;color:var(--ink-3)} +.deadline b{color:var(--danger)} +.card-bd{padding:20px 22px} +.zone{font-size:11px;font-weight:800;letter-spacing:.12em;color:var(--ink-4);margin:0 0 8px} +.zone b{color:var(--ink-3)} +.note{border:1px solid var(--line);border-left:3px solid var(--human);border-radius:8px;background:var(--soft);padding:14px 16px;margin-bottom:16px} +.note p{margin:0;font-size:13px;color:var(--ink-2)} +.note b{color:var(--ink)} +.note .done{color:var(--ok);font-weight:700} +.note .need{color:var(--human);font-weight:700} +.jc-editgate{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:14px 0 10px;padding:9px 12px;border-radius:9px;background:var(--soft);border:1px solid var(--line-soft);font-size:12px;color:var(--ink-3)} +.jc-editgate-t{flex:1 1 auto;min-width:0} +.jc-editgate-t b{color:var(--ink-2);font-weight:700} +.jc-egbtn{flex:none;display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:1px solid var(--line);border-radius:7px;padding:6px 13px;font:inherit;font-size:12px;font-weight:700;color:var(--ink-2);background:#fff;transition:border-color .16s,color .16s,background .16s} +.jc-egbtn:hover{border-color:var(--brand);color:var(--brand)} +.jc-egbtn.save{color:#fff;background:var(--human);border-color:var(--human)} +.jc-egbtn.save:hover{filter:brightness(1.06);color:#fff} +.jc-editgate .eg-cancel,.jc-editgate .eg-save{display:none} +.jc-editgate.on{background:var(--human-soft);border-color:var(--human-line);color:#7c4a12} +.jc-editgate.on .eg-open{display:none} +.jc-editgate.on .eg-cancel,.jc-editgate.on .eg-save{display:inline-flex} +.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:.03em;font-weight:800;color:var(--ink-3);padding:9px 10px;border-bottom:1px solid var(--line)} +th.req::after{content:" *";color:var(--danger);font-size:11px} +td{padding:8px 10px;border-bottom:1px solid var(--line-soft);vertical-align:middle} +tr:last-child td{border-bottom:0} +td.rn{position:relative;width:38px;white-space:nowrap;font-family:var(--mono);font-size:11px;color:var(--ink-4);text-align:center} +.jc-vcell{display:block;font-size:12.5px;color:var(--ink);line-height:1.5;overflow-wrap:anywhere} +.jc-vcell.mono{font-family:var(--mono);font-size:11.5px;color:var(--ink-2)} +.jc-cell{display:none;width:100%;min-width:60px;border:1px solid var(--line);border-radius:6px;padding:6px 8px;font:inherit;font-size:12.5px;color:var(--ink);background:#fff} +.jc-cell.mono{font-family:var(--mono);font-size:11.5px} +.jc-cell:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-wash);outline:none} +table.on td>.jc-vcell{display:none} +table.on td>.jc-cell{display:block} +td.rn .jc-rowdel{display:none;width:22px;height:22px;margin:0 auto;cursor:pointer;border:1px solid var(--line);border-radius:6px;padding:0;font:inherit;font-size:14px;line-height:1;color:var(--ink-3);background:#fff} +td.rn .jc-rowdel:hover{border-color:var(--danger);color:var(--danger);background:var(--danger-soft)} +table.on td.rn .jc-rn-num{display:none} +table.on td.rn .jc-rowdel{display:block} +.jc-addrow{display:none;margin:8px 0 0;padding:8px 12px;border-radius:9px;background:var(--soft);border:1px dashed var(--line);font-size:12px;color:var(--ink-3)} +.jc-addrow.show{display:flex;align-items:center;gap:8px} +.jc-addrow button{cursor:pointer;border:1px solid var(--brand-soft);border-radius:7px;padding:5px 12px;font:inherit;font-size:12px;font-weight:700;color:var(--brand-deep);background:var(--brand-wash)} +.jc-addrow button:hover{background:var(--brand-soft)} +.jc-addrow em{font-style:normal;font-size:11.5px;color:var(--ink-4)} +.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}} +/* 补充:评估输入清单状态标识(仅追加,不改动基件样式) */ +.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)} +.st{display:inline-block;font-size:11px;font-weight:700;padding:1px 8px;border-radius:999px;border:1px solid transparent;white-space:nowrap} +.st.bound{color:var(--ink-3);background:#eef1f6;border-color:var(--line)} +.st.ok{color:var(--ok);background:var(--ok-soft);border-color:#c9ecc2} +.st.miss{color:var(--human);background:var(--human-soft);border-color:var(--human-line)} +.st.def{color:var(--brand-deep);background:var(--brand-wash);border-color:var(--brand-soft)} +tr.ro td{background:var(--soft)} +table.on td>.jc-vcell.ro{display:block} +`; + +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; + --ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9; + --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:#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)} +.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} +.tit .sub{font-size:12px;color:var(--ink-3);margin-top:3px} +.side{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:none} +.tag{font-size:11px;font-weight:800;padding:2px 10px;border-radius:999px;color:var(--ledger);background:var(--ledger-soft);border:1px solid var(--ledger-line)} +.step{font-size:12px;color:var(--ink-3)} +.deadline{font-size:12px;color:var(--ink-3)} +.deadline b{color:var(--danger)} +.card-bd{padding:20px 22px} +.zone{font-size:11px;font-weight:800;letter-spacing:.12em;color:var(--ink-4);margin:0 0 8px} +.zone b{color:var(--ink-3)} +.note{border:1px solid var(--line);border-left:3px solid var(--ledger);border-radius:8px;background:var(--soft);padding:14px 16px;margin-bottom:16px} +.note p{margin:0;font-size:13px;color:var(--ink-2)} +.note b{color:var(--ink)} +.criteria{border:1px solid var(--ledger-line);border-radius:10px;background:var(--ledger-soft);padding:13px 16px;margin-bottom:18px} +.criteria .c-title{font-size:11px;font-weight:800;letter-spacing:.08em;color:var(--ledger);margin-bottom:7px} +.criteria ul{margin:0;padding-left:18px;font-size:12.5px;color:var(--ink-2)} +.criteria li{margin:4px 0} +.criteria b{color:var(--ink)} +.tbl-wrap{border:1px solid var(--line-soft);border-radius:10px;overflow:hidden} +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} +.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 与风险等级(仅追加,不改动基件样式) */ +.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)} +.risk{font-weight:800;font-size:12.5px} +.risk.low{color:var(--ok)} +.risk.mid{color:#8f6a12} +.risk.hi{color:var(--danger)} +.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)} +`; + +export const ACC2_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; + --ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9; + --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:#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)} +.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} +.tit .sub{font-size:12px;color:var(--ink-3);margin-top:3px} +.side{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:none} +.tag{font-size:11px;font-weight:800;padding:2px 10px;border-radius:999px;color:var(--ledger);background:var(--ledger-soft);border:1px solid var(--ledger-line)} +.step{font-size:12px;color:var(--ink-3)} +.deadline{font-size:12px;color:var(--ink-3)} +.deadline b{color:var(--danger)} +.card-bd{padding:20px 22px} +.zone{font-size:11px;font-weight:800;letter-spacing:.12em;color:var(--ink-4);margin:0 0 8px} +.zone b{color:var(--ink-3)} +.note{border:1px solid var(--line);border-left:3px solid var(--ledger);border-radius:8px;background:var(--soft);padding:14px 16px;margin-bottom:16px} +.note p{margin:0;font-size:13px;color:var(--ink-2)} +.note b{color:var(--ink)} +.criteria{border:1px solid var(--ledger-line);border-radius:10px;background:var(--ledger-soft);padding:13px 16px;margin-bottom:18px} +.criteria .c-title{font-size:11px;font-weight:800;letter-spacing:.08em;color:var(--ledger);margin-bottom:7px} +.criteria ul{margin:0;padding-left:18px;font-size:12.5px;color:var(--ink-2)} +.criteria li{margin:4px 0} +.criteria b{color:var(--ink)} +.tbl-wrap{border:1px solid var(--line-soft);border-radius:10px;overflow:hidden} +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} +.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 与状态强调(仅追加,不改动基件样式) */ +.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)} +.risk{font-weight:800;font-size:12.5px} +.risk.mid{color:#8f6a12} +.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)} +.tbl-gap{margin-top:18px} +`;