From e18611006bbb327de63b558b9923b6dfe7694ca0 Mon Sep 17 00:00:00 2001 From: xcs Date: Mon, 31 Aug 2026 13:03:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(w05):=20=E4=B8=89=E5=BC=A0=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E4=BB=B6=E8=A7=86=E5=9B=BE=E5=B1=82=E9=87=8D=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=20=E2=80=94=E2=80=94=20=E7=94=B5=E8=B7=AF=E6=9D=BF?= =?UTF-8?q?=E5=A4=9C=E6=99=AF=20hero=20+=20=E7=B2=BE=E5=AF=86=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E6=8A=A5=E5=91=8A=E7=89=88=E9=9D=A2,=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E7=BB=91=E5=AE=9A=E9=80=90=E9=A1=B9=E4=BF=9D=E7=95=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户定:中央工作区不要后台管理端的样子,按 C 端界面重设计,可加主题 SVG 与动画, 只保留功能。三张件换成「精密检测报告」语言: · 题头深色电路板 hero,三张各一幕 —— 建档台(两颗料的芯片铭牌,由 mine:sub_eval.part 铺行,不在库虚线描边)/ 对决量尺(原 PN → 候选 PN + 推荐等级徽章)/ 落账席(慢转 印章环 + 一句话结论);信号点流动、晶粒呼吸、入场浮起,全部 transform/opacity, prefers-reduced-motion 全静。 · 正文瓷白报告版面:丝印小标 + 简报卡 + 报告表格;比对光谱(四态分布带 + 刻度)、 落账三卡(大数)、四态计数丸。验收两件仍是用户定的验收绿 #0aa294,数据工单数据蓝。 · 设计系统收进 views/style.ts;目标件时代的 target-style.ts 退役(报表样式只此一处真源); report.ts 里与 badge.ts 重复的 vtok/badgeCss 收归一处(销一笔 debt)。 功能一个不动:可编辑表的 DOM 结构逐字节保留(data-rows/data-edit/data-col/编辑闸/ 种子行/主键钥匙/thead 后置/红带),机制规则(序号计数器、jc-row-static 显隐、 gate-bar :has(:empty)、overflow-x)逐字保留并仍被包内测试钉着。 修掉三个自审逮到的洞:kv 占位破折号只认直接子级(嵌套徽标被「—」盖掉)、光谱条里 不渗计数字、加行钮补 base display:none(从前没开编辑就露着)。 104 包内测 + 2516 全仓测绿;两条新锚(主题色/hero 外壳)变异验证各红过一次; 2.6.0 已装库并 SQL 核过(hero/主题色/种子行/vtok/零脚本逐件中)。 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet --- .../__tests__/activity.test.ts | 39 +- .../src/manifest.ts | 2 +- .../src/views/report.ts | 856 ++++++------------ .../src/views/style.ts | 260 ++++++ .../src/views/target-style.ts | 318 ------- 5 files changed, 580 insertions(+), 895 deletions(-) create mode 100644 activities/part-substitution-assessment/src/views/style.ts delete mode 100644 activities/part-substitution-assessment/src/views/target-style.ts diff --git a/activities/part-substitution-assessment/__tests__/activity.test.ts b/activities/part-substitution-assessment/__tests__/activity.test.ts index 60bfd6c..de66897 100644 --- a/activities/part-substitution-assessment/__tests__/activity.test.ts +++ b/activities/part-substitution-assessment/__tests__/activity.test.ts @@ -486,12 +486,17 @@ describe('报告模版:编辑面与只读面各就各位', () => { await expect(host.base.interaction.pushHtml('
')).rejects.toThrow(/无脚本执行权/); }); - /* 解封(2026-08-29,Task 9):`landing-confirm` 补齐,三张全能验了 —— 都走同一个 `doc()` 壳。 */ - it('三张模版的外壳都是搬自目标件的 page/card,不再含 E04/I01 那套视觉底(.proto-root)的痕迹', () => { + /* + * 解封(2026-08-29,Task 9):三张全走同一个 `doc()` 壳。2026-08-31 视图层重设计后, + * 壳不再「搬自目标件」而是活动自己的设计系统(style.ts),但骨架类名不变: + * card-head 是电路板夜景 hero,card-foot 是丝印条;E04/I01 那套视觉底(.proto-root)仍不许出现。 + */ + it('三张模版共用同一个 page/card 外壳(card-head hero + card-foot),不含 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).toContain('class="hero-title"'); expect(html, view).not.toContain('proto-root'); } }); @@ -1039,19 +1044,25 @@ const CONTRACT = { discretion: [], } as const; -/* 验收件题头是验收绿(2026-08-27 用户定:与对话区验收卡同色,不再是目标件的红) */ -describe('两张验收件的主题色', () => { - it('ACC1 / ACC2 的 --ledger 是验收绿 #0aa294,题头渐变不再带红;CONDITIONAL 徽标保留语义红', async () => { - const { ACC1_CSS, ACC2_CSS } = await import('../src/views/target-style.ts'); - for (const css of [ACC1_CSS, ACC2_CSS]) { - expect(css).toContain('--ledger:#0aa294'); - expect(css).not.toContain('--ledger:#b23a2e'); - expect(css).not.toContain('#fdf3f1'); - expect(css).toContain('rgba(10,162,148,.25)'); +/* + * 验收件的强调色是验收绿(2026-08-27 用户定:与对话区验收卡同色,不再是目标件的红)。 + * 2026-08-31 视图层重设计后,样式真源从 target-style.ts(逐字节抽自目标件,随重设计退役) + * 换成 style.ts 的强调色令牌 —— 这条钉的用户口径不变:验收两件 #0aa294、数据工单数据蓝、 + * CONDITIONAL 保持独立语义色(第四态,不与 MATCH 绿 / MISMATCH 红 / UNKNOWN 琥珀混用)、 + * 目标件时代的题头红 #b23a2e 不再出现。 + */ +describe('三张件的主题锚', () => { + it('验收两件强调色 #0aa294;数据工单数据蓝;CONDITIONAL 独立语义色;目标件的红不再出现', () => { + const review = viewHtml('difference-review'); + const landing = viewHtml('landing-confirm'); + for (const html of [review, landing]) { + expect(html).toContain('--acc:#0aa294'); + expect(html).toContain('--ledger:#0aa294'); + expect(html).not.toContain('#b23a2e'); } - // ACC2 的 CONDITIONAL 徽标保留目标件的语义红;ACC1 目标件 2026-08-27 改版把它改成了品牌蓝,照抄 - expect(ACC2_CSS).toContain('.st.cond{color:#b23a2e'); - expect(ACC1_CSS).toContain('.st.cond{color:var(--brand-deep)'); + expect(viewHtml('input-supplement')).toContain('--acc:#2e6bff'); + expect(review).toContain('--cond:#5661f0'); + expect(review).toContain('.st.v-conditional'); }); }); diff --git a/activities/part-substitution-assessment/src/manifest.ts b/activities/part-substitution-assessment/src/manifest.ts index 66289b8..6b45f28 100644 --- a/activities/part-substitution-assessment/src/manifest.ts +++ b/activities/part-substitution-assessment/src/manifest.ts @@ -54,7 +54,7 @@ export const manifest: ActivityManifest = { activityId: ACTIVITY_ID, name: 'ACT-WORK-05 · 差异评估', /* 重写不是改 —— 同版重装是 no-op(静默丢失,踩过) */ - packageVersion: '2.4.0', + packageVersion: '2.6.0', category: '需求分析与方案匹配', sdkVersion: '0.1.0-m5', checksum: 'dev-checksum-part-substitution-assessment', diff --git a/activities/part-substitution-assessment/src/views/report.ts b/activities/part-substitution-assessment/src/views/report.ts index e7f0dbd..dea7017 100644 --- a/activities/part-substitution-assessment/src/views/report.ts +++ b/activities/part-substitution-assessment/src/views/report.ts @@ -1,232 +1,67 @@ /** * ACT-WORK-05 差异评估的 HTML 报告模版 —— **活动自己持有的资产**,随包版本冻结。 * - * **2026-08-29 Task 7 重写**:五张旧局面(P-08 数据工单 / P-10 数据工单 / 评估输入清单 / - * 差异评估结论审核 / 评审放行与落账确认)按 spec §8 全部作废,S1 那一步不再分成 - * 「先核对存在性 → 分别派 P-08/P-10 数据工单 → 再摆评估输入清单」三个局面 —— - * 新的四步案例模型只有一张数据工单卡(`variant: 'data'`),这里对应**一张**新局面 - * `input-supplement`(评估输入补全):**四块竖排**(spec §6.1,Task 7b 补第②a 块)—— - * ① 要评估什么(两颗料的存在性 + 主数据,`sub_eval.part` 铺行 / `parts.profile` 承载编辑); - * ②a 芯片类型(每颗料各自的类型选择,选项从 `parts.chip_type` 现读;类型下拉里没有合适的 - * 就在这里现新建一个,`parts.chip_type` 承载编辑); - * ②b 核心参数字段清单(新建类型时要填的字段清单,`parts.type_param` 承载编辑,供加行); - * ③ 参数值(逐条核心参数的实测 / 规格值,一字段一行,`parts.parameter`)。 - * 顶部一条红带摆 S1 配方算好的 `gate_reason`(「还差什么」的一句话,配方 §see case-model.ts - * 的 step④),够不够齐、该不该出现由样式表判(§5「模版不许算」)。 + * **2026-08-31 视图层整体重设计**(用户定:「中间这一块不要搞的像后台管理端,要像给客户 + * 使用的 C 端界面;可以按主题加 SVG 图形与动画;只保留功能,视图层可以推翻重新设计」): + * 三张件换成「精密检测报告」语言 —— 深色电路板夜景 hero(芯片封装 SVG + 流动信号点, + * 三张件各一幕:建档台 / 对决量尺 / 落账席),正文回到瓷白纸面的报告排版。设计系统在 + * `./style.ts`(SHELL_CSS + 两套强调色);目标件时代的 `target-style.ts` 随之退役。 * - * `difference-review`(件② 差异评估结论审核)已由 Task 8 重做并交付(见文件尾「局面:差异评估 - * 结论审核」一节);`landing-confirm`(件③ 落账确认)已由 Task 9 重做并交付(见文件尾 - * 「局面:落账确认」一节)—— 三张件此刻齐了。 + * **功能一个不动**:三张件的绑定面(data-rows / data-edit / data-col / 编辑闸 / 加删行 / + * 种子行 / 主键钥匙 / 红带与还差什么)与 2.4.0 逐项相同 —— 可编辑表的 DOM 结构逐字节 + * 保留(收值链路 collect / resolveRowKey / addRow 都按结构认元素,动结构就是动功能); + * 重设计只落在外壳、hero、只读块与表格皮肤上。 * - * **Task 7b(2026-08-29)补②a 块**:件① 交付时「新建类型」只有一句 guide 文字,没有可 - * 落笔的地方(类型下拉只能挑**已有**的)。零平台改动补齐(查证与三条候选路见 Task 7b 报告): - * `parts.chip_type` 与 `parts.type_param` 两张表新开局都是零行,`ViewContainer.addRow` - * 靠克隆最后一行添新行、零行时无样可克隆——两张表各加一个**不受 `data-rows` 管辖的 - * 静态种子行**(不经 `cell()`/`data-slot`,字面量手写 `data-col` 输入格,详见 - * `CHIP_TYPE_TABLE`/`TYPE_PARAM_TABLE` 头注)。查证过程中额外揪出并顺手治死两处平台级 - * 潜伏坑(`resolveRowKey` 的续号步骤抢在 `autoKeys()` 续号器前面 / 引用列声明成 `integer` - * 会把补零字符串的前导零削掉致使 `refersTo` 失配)——两者的共同根因是`parts.chip_type.type_id` - * 是本仓**唯一**「auto:true 又是 integer」的主键,改声明成 `text`(与其六处同一身份链路的 - * 引用列一起改)后两处坑自然绕开,详见 manifest.ts 该字段的大注释。 - * - * 版面语言仍是「搬,不要照着做」(《HTML报告生成规范》§7):`P08_CSS`(逐字节抽自 - * `docs/SS02-ACT-WORK-05-html/ACT-WORK-05-数据工单-01-芯片主数据创建.html`, - * 见 `./target-style.ts` 头注)是**唯一**的样式来源 —— 三块内容原来分属 P-08 数据工单 / - * P-10 数据工单(复用 P08_CSS)/ 执行工单(EXEC_CSS)三张局面,合并成一张之后 - * 统一沿用 P08_CSS 这一套版面语言(EXEC_CSS 随之退休,见 target-style.ts 头注)。 - * `BIND_COMMON`/`BIND_P08` 是平台绑定层加的东西(缺项红带、编辑闸/增删行、 - * `data-class-of` 的 `v-*` 别名):目标件是写死数据的静态 demo,没有「N 行草稿」 - * 「编辑态与归档态二选一」这些平台概念。 + * 三张局面: + * · `input-supplement`(S1 数据工单):四块竖排 —— 要评估什么(`sub_eval.part` 铺行 / + * `parts.profile` 承载编辑)/ 芯片类型(`parts.chip_type`,含静态种子行)/ 核心参数 + * 字段清单(`parts.type_param`,含种子行与加删行)/ 参数值(`parts.parameter`); + * 顶部红带摆配方算好的 `gate_reason`。 + * · `difference-review`(S3 验收工单):对决 hero(原 PN → 候选 PN + 推荐等级大徽章)+ + * 四态光谱 + 逐条差异明细(可就地改四态)+ 收口四格(可就地改,2026-08-31 用户定)。 + * · `landing-confirm`(T_release 终局验收工单):全只读,答「这一签下去发生什么」—— + * 印章 hero + 落账去向 + 四态计数与硬约束点名 + 待验项。 */ -import { P08_CSS, ACC1_CSS, ACC2_CSS } from './target-style.ts'; +import { vtok, badgeCss } from './badge.ts'; +import { SHELL_CSS, ACCENT_DATA, ACCENT_LEDGER } from './style.ts'; import { D } from '../constants.ts'; -/* ==================================================================================== - * 绑定层公共开关 —— 三张模版共用(此刻只有一张),与目标件自己的样式表分开存(那份要保持逐字节可比) - * ==================================================================================== */ -const BIND_COMMON = ` -/* ── 2026-08-27 用户四连指出的件上毛病,病根三处都在「目标件的样式与平台的编辑态没对上」 ── */ -/* ① 表宽超出就得能横着滑(E04/I01 08-23 同款):两种包装都管 —— 数据工单/执行件用平台的 .jc-tbl-wrap, - 两张验收件照目标件用 .tbl-wrap,而验收版目标件写的是 overflow:hidden(只有数据工单那版补了 overflow-x:auto)。 - 2026-08-27 用户:「差异评估结论审核这个页面,表格部分不能左右滑动」—— 上一刀只管了前者 */ -.jc-tbl-wrap, .tbl-wrap { overflow-x: auto; overflow-y: hidden; } -/* ② 编辑态只留输入格:目标件 #tbl1 .jc-vcell{display:inline}(id 特异度)盖过了 table.on td>.jc-vcell{display:none}, - 于是表 1 每格都是「只读字 + 输入框」并排 —— 内部料号那格恰好有字,人看见的就是它 */ -#tbl1.on td > .jc-vcell:not(.ro) { display: none; } -/* ③ 一行里的 input 与 select 同高同线:select 天生比 input 矮 4px,编辑态里一排格子高低不齐 */ -input.jc-cell, select.jc-cell { height: 32px; box-sizing: border-box; padding-top: 0; padding-bottom: 0; vertical-align: middle; } -/* ④ 加行 / 删行要看得见(2026-08-27 用户:「加一行后点旁边的叉没有反应」):E04 那套记号样式挂在它自己的 - 外壳类下,本件按目标件重做后表是 table.on —— 一条都没跟过来,× 按了类是切了、屏上没动静 */ -table.on tr.jc-row-new td { background: #f2fbf7; } -table.on tr.jc-row-gone td { background: #fff6f6; opacity: .55; } -table.on tr.jc-row-gone .jc-cell { text-decoration: line-through; color: var(--ink-3); } -table.on tr.jc-row-gone .jc-rowdel { border-color: var(--danger); color: var(--danger); background: #fff; } -/* 只在「待处理」这一态露面;归档 / 验收只读态即便 HTML 里还带着 data-edit 也不摆闸和加行钮 - (目标件是静态 demo,不区分这两态;html.editable 是平台在 iframe 根节点上真开的关) */ -html:not(.editable) .jc-editgate, html:not(.editable) .jc-addrow { display: none !important; } -/* 「加一行」钮跟着紧邻的表进不进编辑态现身(目标件靠 JS 脚本的 classList.toggle('show',on), - 沙箱零脚本,改用 :has() 认「紧挨着的表是不是 .on」) */ -.jc-tbl-wrap:has(table.on) + .jc-addrow { display: flex; align-items: center; gap: 8px; } -/* 序号列交给 CSS 计数器 —— 目标件的 JS 脚本在增删行后重写 .jc-rn-num / .num 的文本, - 沙箱零脚本,新增的行 / 删掉的行让计数器自己算对,不必比对哪一行手改过数字。 - 两种列名都要接(.rn 用于 P08/P10/执行工单 —— 目标件里那三份自己就用它; - .num 用于两份验收工单 —— 目标件里那两份自己就用它,静态数字,这里换成动态计数)。 - 两种包装类都要接(2026-08-29 评审 Important 逮到):数据工单 / 执行件的表用平台的 - .jc-tbl-wrap,两份验收件照目标件用 .tbl-wrap —— 这五条规则原来只认了 .tbl-wrap, - input-supplement 的三张表(以及已删除的旧 P08/P10 三张)全走 .jc-tbl-wrap, - 序号列因而从来没数过,只读态与编辑态下 # 列逐行都是空白。 */ -.jc-tbl-wrap table, .tbl-wrap table { counter-reset: rn; } -.jc-tbl-wrap table td.rn, .tbl-wrap table td.rn { counter-increment: rn; } -.jc-tbl-wrap table td.rn .jc-rn-num::before, .tbl-wrap table td.rn .jc-rn-num::before { content: counter(rn); } -.jc-tbl-wrap table td.num, .tbl-wrap table td.num { counter-increment: rn; } -.jc-tbl-wrap table td.num::before, .tbl-wrap table td.num::before { content: counter(rn); } -/* 缺项红带 —— 目标件没有这个概念(它是静态 demo,不会「缺东西」); - 这是本仓的必填提示机制,与提交闸同源,配色用目标件自己 :root 里那两个 --danger 变量 - (四份目标件的 :root 对这两个变量给的是同一组值,借用不算改目标件的数值)。 */ -.jc-gapbar { display: none; } -html.editable .jc-gapbar { - display: flex; align-items: flex-start; gap: 8px; margin: 0 0 10px; padding: 9px 12px; - border-radius: 9px; background: #fff5f5; border: 1px solid #f3b9b5; color: var(--danger); font-size: 12px; line-height: 1.65; -} -.jc-gapbar b { font-weight: 800; } -.jc-gapbar span { color: #9a3b36; } -html.editable .jc-gapbar.v-0 { display: none; } -/* - * 顶部「还差什么」红带(2026-08-29,Task 7 新增,不是照抄 .jc-gapbar):gate_reason - * 是一句中文自由文本(配方拼的整句话,如「有料号库里查不到 —— 在下面把它的主数据建起来。」), - * 不是像 _missing 那样的整数计数 —— data-class-of 把值消毒成 class 时只留 [a-z0-9-], - * 中文字符全被剥空,v- 永远是空 token(既取不出 v-0 也取不出任何有意义的档位), - * 靠它去挑「空 → 隐藏」这条路本身就走不通(核对过 view-render.ts 的 classToken 实现)。 - * 改用更结实的信号:data-slot 配 data-blank 让空值真的渲成空文本节点,CSS 用 :has(:empty) - * 认「这句话是不是空的」—— 真正管显隐的是下面这条 :empty 规则。 - * - * 不给这个元素再挂那个按值投影的属性了(2026-08-29 评审 Minor 修正,第一版留了它): - * 上面这段已经交代清楚它在这个字段上永远算不出 v-token,留着就是源码里躺着一个 - * 永远不起作用的标记 —— 下一个读的人会以为它有用(那也是一种界面/源码层面的「撒谎」)。 - * 判断只留一处:data-blank 出的空文本节点 + CSS :empty。 - */ -.jc-gate-bar { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 14px; padding: 10px 14px; - border-radius: 9px; background: #fff5f5; border: 1px solid #f3b9b5; color: var(--danger); font-size: 12.5px; line-height: 1.65; } -.jc-gate-bar b { font-weight: 800; } -.jc-gate-bar:has(.jc-gate-text:empty) { display: none; } -/* - * 不给删行的两张表,编辑态里 # 号不能空着:P08_CSS 的 table.on td.rn .jc-rn-num{display:none} - * 是配 .jc-rowdel 一起写的(删行按钮腾出位置)—— 要评估什么(#tbl1)与参数值(#tbl3)两张表 - * 行集固定(人不加行、系统按 sub_eval.part 与 parts.type_param 铺),没有删行按钮可换,编辑态里 - * 用 id 选择器把计数器重新点亮(id 特异度压过 P08_CSS 的类选择器)。 - */ -#tbl1.on td.rn .jc-rn-num, #tbl3.on td.rn .jc-rn-num { display: inline; } -/* - * **新建行(Task 7b,件① 补「新建芯片类型」)**:parts.chip_type / parts.type_param - * 两张表新增一条**字面量静态行**(不走 data-rows,不受行数所限,ViewContainer.addRow - * 找不到 tr:last-of-type 可克隆时也照常在——这一条从来不指望被克隆出来,它本身就是种子)。 - * 只在编辑态露面:读的时候看见一行「系统生成 / 占位提示」的空壳子是界面撒谎的另一种形状。 - * table.on(与其余 .jc-cell/.jc-vcell 同一个开关)已经个别管住了里面每个输入格的显隐, - * 这条补的是**行本身**(#、静态提示文字这类不挂 .jc-cell 的内容不受那条规则约束)。 - */ -table:not(.on) tr.jc-row-static { display: none; } -`; +/* ==================== 徽标配色(值与文案成对交给 badgeCss,选择器从值算,不手写) ==================== */ +const OK = 'color: var(--ok); background: var(--ok-soft); border-color: #c3ecd3;'; +const DANGER = 'color: var(--danger); background: var(--danger-soft); border-color: #f6c3bc;'; +const AMBER = 'color: var(--amber); background: var(--amber-soft); border-color: #eeda9e;'; +const MUTED = 'color: var(--ink-3); background: #edf1f5; border-color: var(--line);'; +const COND = 'color: var(--cond); background: var(--cond-soft); border-color: #cdd2fb;'; -/* - * ==================== 徽标别名的生成器 ==================== - * - * **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-]`, - * **吃掉下划线**,`pin_to_pin` → `v-pintopin`,封顶 24 字);基座读数名走 `engines.ts` 的 - * `slug`(只留 `[a-z0-9_]`,吃掉连字符)。两套规则不一样,tally 值一旦带下划线,手写的 - * `.v-xxx` 选择器就必然是错的。**判据那一侧(读数名)一个字都不碰**——那已经审查通过、 - * 与 `slug` 一致;这里改的只是展示层:选择器一律用 `vtok()` 从 tally 值**算**出来,不再手写。 - */ -/** 必须与 `classToken` 一字不差:小写、只留 `[a-z0-9-]`、封顶 24 字。 */ -const vtok = (v: string): string => v.toLowerCase().replace(/[^a-z0-9-]/g, '').slice(0, 24); -/** 一族徽标的 CSS:选择器与文案从 `[值, 人读名, 可选颜色声明]` 表算出来,值与文案成对写在一处 */ -type BadgeSpec = readonly [value: string, label: string, color?: string]; -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'); - -const OK = 'color: var(--ok); background: var(--ok-soft); border-color: #c9ecc2;'; -const DANGER = 'color: var(--danger); background: var(--danger-soft); border-color: #f3b9b5;'; -const AMBER = 'color: #8f6a12; background: #fdf3d7; border-color: #ecd9a0;'; -const MUTED = 'color: var(--ink-3); background: #eef1f6; border-color: var(--line);'; - -/* - * ==================== input-supplement 的徽标别名 ==================== - * - * 沿用 P08_CSS 已带的两个基座形状:`.stx`(生命周期状态那一族用的胶囊)与 `.ct`(约束类型)—— - * 不新起一个 `.st` 基座类(那是已退休的 EXEC_CSS 定义的,P08_CSS 里没有它的 display/padding - * 这些基础属性,借用类名而没有基座样式,徽标会是一段无样式的裸文字)。 - */ -const BIND_P08 = ` -/* 生命周期状态(parts.profile)与在库状态(sub_eval.part.exists_status)共用 .stx 胶囊 —— - 取值域互不重叠(active/nrnd/eol/discontinued/risk 与 found/absent 没有一个词撞车)。 */ -.stx { display: inline-block; font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: 999px; border: 1px solid transparent; white-space: nowrap; } -${badgeCss('.stx', [ - ['active', 'Active', OK], - ['nrnd', 'NRND', AMBER], - ['eol', 'EOL', DANGER], - ['discontinued', '停产', MUTED], - ['risk', '风险', DANGER], - ['found', '在库', OK], - ['absent', '不在库', AMBER], -])} -/* 约束类型(硬/软)—— parts.type_param.constraint_type,目标件 P08_CSS 已带 .ct 基座形状与这两条颜色声明 */ -${badgeCss('.ct', [ - ['hard', '硬约束', DANGER], - ['soft', '软约束', MUTED], -])} -/* 角色(原 PN / 候选 PN)是分类标签不是状态,不配色,只补 ::after 文案 */ -${badgeCss('.rl', [ - ['original', '原内部料号'], - ['candidate', '候选内部料号'], -])} -`; - -/** 三层壳照目标件:`
`,不再套 `.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 => - ` -
-
-
${input.badge}
- ${input.hic ?? ''} -
-
${input.kicker}
-

${input.title}

-
收件人: · 关联任务:
-
-
- ${input.tag} - ${input.step} -
-
-
${input.body}
-
- ${input.kicker} · ${input.title} - ${input.footTag} · -
-
`; - -/* ==================== 内联 SVG 图标 —— 逐字节搬自「数据工单-01」目标件(它们是版面语言的一部分) ==================== */ -const HIC = - ''; +/* ==================== 内联 SVG 图形 ==================== */ +/** 分区小图标(丝印风,描边取 currentColor) */ const ZIC_TASK = - ''; + ''; const ZIC_TABLE = - ''; + ''; +/** + * 芯片封装(SOIC 俯视,铜引脚 + 晶粒)—— hero 舞台的主角。全部样式走 CSS class + * (c-body / c-pin / c-die / c-dot),不用 defs 渐变:同一份文档里出现两次时渐变 id 会撞。 + */ +const CHIP = + ''; -/* ==================== 通用绑定小工具 ==================== */ -const zone = (label: string, aside: string, icon = ''): string => `

${icon}【${label}】—— ${aside}

`; -const note = (items: readonly string[]): string => `
${items.map((p) => `

${p}

`).join('')}
`; +/* ==================== 通用绑定小工具(输出形状被包内测试钉死,改字就是改契约) ==================== */ +const zone = (label: string, aside: string, icon = ZIC_TASK): string => + `
${icon}【${label}】${aside}
`; +const note = (items: readonly string[]): string => ``; const flow = (text: string): string => `
${text}
`; const editGate = (address: string, label: string): string => `
${label} @@ -243,39 +78,98 @@ const addrow = (address: string, label: string, hint: string): string => `
`; /** 可改格:只读那一份留空,渲染器自动配孪生 ``(手写 input 会不填值,人一点编辑就是白框) */ const cell = (col: string, cls = ''): string => ``; -/** 只读格:即便挂在可改的表里也不许被 `table.on` 藏起来 —— 目标件自己就有这条覆盖(`.jc-vcell.ro`) */ +/** 只读格:即便挂在可改的表里也不许被 `table.on` 藏起来 */ const ro = (col: string, cls = ''): string => ``; const select = (col: string, options: ReadonlyArray, required = false): string => ``; /** * 枚举徽标。可改表里挨着 `` 的内容 - * 是一串 `