@qilitt-mickey/vue3-temp-skill 1.1.54 → 1.1.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SKILL.md CHANGED
@@ -51,7 +51,7 @@ tags: [vue3, typescript, element-plus, pinia, vite, unocss, crud, demo, code-qua
51
51
  | `files-and-editors` | 附件、预览、下载、富文本、二维码 | `file-management.md`、`download-export.md`、`rich-text.md`、`qrcode-barcode.md` |
52
52
  | `realtime-and-mobile` | WebSocket、移动端、微信、验证码、动效 | 对应专项 reference |
53
53
  | `data-compare` | 编辑页变更对比和汇总 | `data-compare.md` |
54
- | `design-apply` | 设计变更集落地:语义 ID 三级匹配、结构/形态/两层样式转换、锚点与结构施工、覆写提权、渲染态验收、合规闸门 | `design-apply.md`、`mapping/`、`parser/` |
54
+ | `design-apply` | 设计变更集落地:语义 ID 三级匹配、结构/形态/两层样式转换、锚点与结构施工、覆写提权、渲染态验收、合规闸门。**主入口 `design-apply.md`(红线+契约+步骤索引),各步骤拆分册 `references/steps/`——做到哪一步读哪一份,禁止一次全部通读** | `design-apply.md`、`steps/`、`mapping/`、`parser/` |
55
55
 
56
56
  ## 工作流
57
57
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qilitt-mickey/vue3-temp-skill",
3
- "version": "1.1.54",
3
+ "version": "1.1.55",
4
4
  "type": "module",
5
5
  "description": "Vue 3 企业级中后台项目开发规范技能包 — core-kernel 架构、按需功能模块",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated_at": "2026-09-22T01:04:15.248Z",
2
+ "generated_at": "2026-09-22T03:10:19.033Z",
3
3
  "oracle": "E:\\work\\Project\\Template\\skills\\vue3-temp-skill\\parser\\fixtures\\verify\\oracle.json",
4
4
  "actual": "E:\\work\\Project\\Template\\skills\\vue3-temp-skill\\parser\\fixtures\\verify\\actual-clean.json",
5
5
  "points": {
@@ -30,6 +30,13 @@ parser match(确定性翻译)→ 施工坐标 → AI 按坐标改代码 →
30
30
 
31
31
  无论哪条来路,落地流程一律走下文「执行流程」。
32
32
 
33
+ **上下文纪律(防上下文溢出,与流程红线同级)**:
34
+
35
+ 1. **词典走 parser,禁直读全文**:`mapping/` 下 JSON 是 parser 的事实源,不是给人(AI)通读的——查点位用 `parser query <id>`、查清单用 `parser list`,**禁止整文件读入 `mapping/scenes/*.json` / `mapping/basic/*.json`**(仅 validator/regression 维护场景或 parser 明确报错需要人工核对单条时,用 `Grep` 精确抽取相关条目,不整读)。
36
+ 2. **落地会话禁读设计侧规范库**:设计技能的 `page-specs/`(规范/令牌/效果图)不属于项目侧视野——项目侧消费的是**变更集 + oracle.json + 登记表**三个交付物;`oracle.mockup` 指向的效果图由 `resolveFirstExisting` 跨库解析给 parser 使用,但人(AI)**不打开、不阅读设计侧效果图与规范文件**。
37
+ 3. **效果图只读一次**:期望值优先直接消费设计侧交付的 `oracle.json`;确需现场抽取时(无产物降级路径),抽取完成后值落盘,**后续轮次禁止反复打开效果图 HTML/JPG**。
38
+ 4. **做到哪一步读哪一份**:各步骤细节在 `steps/` 子文件(见下方索引),按当前阶段加载,禁止一次全部通读。
39
+
33
40
  ## 出厂中性 · 变更集驱动(架构红线,违反即返工)
34
41
 
35
42
  **同一份模板源码,换一份变更集 = 换一套外观。** 任何「本次设计的结论」都不许固化进源码:
@@ -103,459 +110,22 @@ parser match(确定性翻译)→ 施工坐标 → AI 按坐标改代码 →
103
110
  - `pending` 数组声明的是设计侧新点位,直接归入 L3 处理(不是错误)。**注意:pending 不是施工指令**——L3 施工的内容以 `changes[]` 中同 ID 新条目声明的意图为准;设计侧只登记 pending、未在 changes[] 声明意图的点位,落地时按出厂现状处理并在缺口清单中反馈「该点位设计意图缺失」。
104
111
  - parser 校验已实现:schema 硬校验、mapping_version 缺失/不匹配拒绝、禁词与 hex 位置校验、语义 ID 命名校验、`layer` / `apply_via` / `structure_ops` 结构校验。
105
112
 
106
- ## 执行流程(按序,禁止跳步)
107
-
108
- ### 第 0 步 · 版本与场景检查 · 对接匹配(适配前置)· 运行时清场
109
-
110
- **0.1 版本与场景检查**
111
-
112
- - 变更集 `schema` 版本不在支持范围 → 停止,向上游(用户/设计侧)报告版本不匹配,不降级猜测。
113
- - `scene` 在 `parser list` 场景清单中无对应域 → 报告并列出支持的场景,等待确认。
114
-
115
- **0.2 对接匹配(适配前置)——把散落的匹配收拢为一个前置阶段**
116
-
117
- 在施工前,把「设计意图 ⇄ 模板能力」整体对一遍,输出匹配结论,供**生成前**决策(而不是落地时才发现对不上)。三步判定:
118
-
119
- | 级 | 判定 | 依据 |
120
- |---|---|---|
121
- | **布局级** | `layout_type` 命中标准枚举? | 命中 → 切布局模板池(§5.2);未命中 → 变体派生 / 定制生成骨架(§5.3 / §5.4) |
122
- | **点位级** | 逐 id 三级匹配 | 一级完整命中 / 二级父级命中 / 三级未命中(§4.1) |
123
- | **形态级** | `form` 在条目 `forms` 枚举内?`structure_ops` 所需 DOM 钩子是否存在? | 词典 `forms` / 模板源码 / `audit` |
124
-
125
- **输出三类结论,处置全在项目侧**:
126
-
127
- | 结论 | 判据 | 处置 |
128
- |---|---|---|
129
- | 完全匹配 | L1 ∧ form 在枚举 ∧ 无需结构 | 直接施工 |
130
- | 可派生 | L2 / 变体布局 / form 可映射 | 派生骨架或继承父级后施工 |
131
- | 需适配 | L3 / 定制布局 / 缺通道 / 需新 DOM | **先补通道 / 结构增量 / 生成骨架,再生成**;交付说明单列申报 |
132
-
133
- > **总原则(红线):设计为主,项目侧适配。** 设计效果是目标态,模板是待适配的一方。"设计 ↔ 模板对不上"的出口**永远在项目侧**——**不回流设计侧改设计**。只有「设计侧未给值 / 值非法」(**意图缺口**)才回流设计侧。严禁以「模板不支持」为由要求设计改图。
134
-
135
- **0.3 运行时主题清场(T 通道先于 D/S/C)**
136
-
137
- 主色 / 主题走的是**运行时通道**:`setEpThemeColor()` 把 `--el-color-primary` 写成 `documentElement` 的**内联样式**并持久化到 localStorage(读取优先级 = 浏览器持久化 ?? `platform-config.json`)。**内联样式 + 运行时持久化 ⇒ 设计层 CSS 与词典 selector 都赢不了。**
138
-
139
- - 落地前先读 localStorage(键 `responsive-layout`)的 `theme` / `epThemeColor`,与本变更集主题**不一致时清 key 或显式重设**;
140
- - 清场动作与结果写入交付说明(可回溯);
141
- - **不清场则颜色类差异全部失真**——归因前必须先确认起点已对齐,否则会把「环境残留」误判成「落地失败」。
142
- - **机检对账(G4)**:`parser audit` 会自动比对 `global.brand_primary` ↔ `platform-config.EpThemeColor`、页签 form ↔ `ShowModel`、`visible:false` ↔ 显隐开关,不一致即 `exit 1`——人工清场 + 机检对账双保险。
143
-
144
- **0.3b T 通道持久化三件套(页签形态 / 主题类字段施工必做)**
145
-
146
- 运行时配置读 localStorage,而 localStorage 只在 `platform-config.Version` 变化时经 `responsive.ts invalidateStorageIfConfigVersionChanged` 重灌。凡施工涉及 `ShowModel` / `Theme` / `EpThemeColor` 等 T 通道字段,**三件套缺一不可**:
147
-
148
- 1. 改 `platform-config.json` 实值(如 `ShowModel: "card"`);
149
- 2. **`Version` 自增一位**(如 0.0.6 → 0.0.7)——漏此步 = 代码对但运行时仍旧形态(历史事故:只改 ShowModel 未动 Version,页签零变化);
150
- 3. **渲染取证**:断言新形态类实际挂载(如 `.scroll-item.card-item` 出现在 DOM)——不许只看代码改没改。
151
-
152
- 词典 `admin.layout.tabs.preconditions` 有同款硬闸描述;本三件套对任意 T 通道字段通用。
153
-
154
- ### 第 1 步 · parser 确定性匹配
155
-
156
- ```bash
157
- # 单份变更集
158
- node parser/index.js match <changeset.json>
159
- # 项目级批量(设计侧项目级模式产出:全局变更集 + 各页面变更集目录)
160
- node parser/index.js match --batch <changesets-dir>
161
- ```
162
-
163
- 读取输出的**转换计划**,它包含:
164
-
165
- | 分级 | 含义 | 处理 |
166
- |------|------|------|
167
- | **L1 完整命中** | ID 在词典中直接命中 | 按条目施工坐标直接落地(预期 100% 还原) |
168
- | **L2 父级命中** | ID 的父模块命中 | 继承父模块样式约定,按子级定位施工(85-90% 还原) |
169
- | **L3 未命中** | 词典无此 ID(新增点位) | **当场按第 4 步定制布局落地**并写入 mapping 临时映射;只有设计侧未给完整意图(无值 / 值非法)才进缺口清单 |
170
- | **字段级未命中** | ID 命中但 `style` 某字段两层映射都查不到 | 值合法且选择器可定位 → **当场生成作用域内自定义规则落设计层文件并申报**;只有「值非法 / 无法定位」才进缺口清单 |
171
-
172
- **零缺口交付(禁止中途停顿)**:落地一次跑完,**不得因「词典没建这个 ID / 这个字段没枚举 / 这个值要不要确认」而停下来问用户**。缺口只有两类,去向各不相同:
173
-
174
- | 缺口类型 | 判据 | 处理 |
175
- |---|---|---|
176
- | **能力缺口**(词典缺 ID / 缺字段枚举 / 缺 form) | 设计侧意图完整、值合法 | **项目侧当场落地**:按 L3 定制布局施工并写 mapping 临时映射;出厂文件仅在「补通道」时可动,交付说明单列申报。**进清单 = 把可落地项搁置 = 交付失败** |
177
- | **意图缺口**(设计侧没给值 / 值非法) | 变更集里本就没有这个值 | 才可进「缺口清单」,交付说明写明「回流设计侧补齐」——**不是问用户要不要做** |
178
-
179
- `缺口清单` 只承载第二类,且必须给出点位 ID + 缺失字段名。
180
-
181
- **转换计划新增四类输出()**:每条 L1/L2 点位除样式指令外,还会输出——
182
-
183
- | 输出 | 含义 | 施工含义 |
184
- |---|---|---|
185
- | `▸ 承载通道 anchors` | 该点位可落地的宿主盒 / 内层文本盒 / CSS 变量锚点 | 落点以这里为准,不要自己猜选择器 |
186
- | `▸ 承载通道来源 apply_via` | 本声明引用的锚点来源条目 | 落到该条目的锚点上(而非 change.id 自身的) |
187
- | `▸ 结构施工 structure_ops` | 需要改数据 / 模板结构的事项 | **必须改动数据或模板分支**,禁止只写 CSS |
188
- | `▸ 前置条件 preconditions` | 值成立依赖的宿主前提 | 施工前必须满足,否则「值对了也不生效」 |
189
- | `▸ 覆写优先级 priority` | 该点位的提权策略 | 按策略取胜,禁止逐点硬堆 `!important` |
190
-
191
- **词典硬闸(match 期机检,违规 = 拒绝执行)**:
192
-
193
- | 闸 | 触发条件 | 判据来源 | 违规输出 |
194
- |---|---|---|---|
195
- | **G8 模式闸** | 变更集顶层 `mode: "restore"`(场景还原)但基线不全:缺 `scheme` / `oracle` / `coverage`,**或 `oracle.mockup` / `coverage.registry` 为空**(有壳无芯的伪基线)——伪还原变更集(只换主题色却以还原之名交付)拒绝执行;`mode` 非法值同样阻断 | 变更集顶层 `scheme` / `mode` / `oracle.mockup` / `coverage.registry` | `G8 模式闸:mode=restore 但缺少 … → 拒绝执行` |
196
- | **G9 登记表身份闸** | `mode=restore` 但登记表**身份对不上**:`coverage.registry` 实物解析失败,或登记表 `design_scheme`/`scene` 与变更集 `scheme`/`scene` 不一致(或缺身份字段)——凡身份对不上的表视同没有表,防止覆盖率分母被偷换(面包屑/顶栏图标/表头 nowrap 等点位从分母消失,欠声明不可数) | 登记表顶层 `design_scheme` / `scene` ↔ 变更集顶层 `scheme` / `scene` | `G9 登记表身份闸:登记表 … 属于 scheme="…"/scene="…",与变更集 … 不一致 → 拒绝执行` |
197
- | **G10 dims 兑现闸** | `mode=restore` 下登记项的 ID 已在 `changes[]` 声明,但登记 `dims` 维度未全部给全(`form` 看 `change.form`,其余看 `style ∪ layer` 的键;`source:none`、global 伪点位、`visible:false` 豁免)——「点位在、细节丢」(表头竖排 = nowrap 丢失)正是样式细节不还原的机制成因,dims 缺口与欠声明同级阻断 | 登记表条目 `dims` ↔ 变更集条目 `form` / `style` / `layer` | `dims 兑现缺口(G10 · … 条 → exit 1):… 缺 dims=[…]` |
198
- | **G11 oracle 基线闸** | `mode=restore` 下 oracle 校验发现问题(主题错配 / `oracle.sids` 欠声明或无基线 / 实物缺口):restore 下从「⚠ 软提示继续」升格为「拒绝执行」——基线断了仍绿灯交付,verify 无从做 1:1 证明。同构异色复用须在 oracle 显式声明 `theme_mapping: { from, to }` | oracle 主题词 ↔ `global.brand_primary` 主题词;`oracle.sids` ↔ `changes[].id` 双向 | `oracle 基线问题(G11 · … 类 → 拒绝执行):主题错配 …` |
199
- | **G1 suppress 收口** | 条目声明某 `form`,词典 `suppress_rules[form]`(或 forms 描述「suppress 必含 x」内联标记)要求收口的出厂互斥通道未全部出现在该条目 `suppress[]` | 词典条目 `suppress_rules` | `suppress 缺口:…必须收口出厂互斥通道 [x],缺 [x]` |
200
- | **G5 几何语境** | 词典 preconditions 含「几何语境随值迁移」标记 ∧ `style` 含 padding/margin 族几何字段落宿主 ∧ 未声明 `suppress_inner` | 词典条目 preconditions 标记句 | `suppress_inner 缺口:…两层之和 ≠ 设计值` |
201
-
202
- 三闸与禁词校验同级阻断(`exit 1`)——「新旧形态叠加」「两层 padding 相加」「伪还原只换主题」都是历史事故源(双竖条、28px 列挤压、「还原后布局细节零变化」),不允许靠观感兜底。G8 判据一句话:**「把系统 / 页面改成 X」默认是还原(restore),必须带齐 `scheme` + `oracle.mockup` + `coverage.registry`;只有「显式声明只改主题色、其它不动」才用 `design`**(2026-09-20 事故机制化:还原项目后重跑,无登记表无基线的轻量变更集一路绿灯,落地后「只变了主题、布局细节零变化」;二轮强化再堵住 `oracle`/`coverage` 只给空壳、无 `mockup`/`registry` 芯的写法)。**降级不许静默发生**:变更集 `notes` 与交付说明都须显式写出本次 `mode` 与范围。restore 模式下 G9/G10/G11 同时生效(登记表身份、dims 维度兑现、oracle 基线三道复闸),三者判据细节见上表与「登记表覆盖率」小节。
203
-
204
- **验收基线输出**:转换计划末尾另打印 `=== 验收基线 oracle ===`(效果图路径 + 待比对点位)与 `=== 覆盖率 coverage ===`(登记项 R / 适用 A / 已兑现 C)。有 `oracle` → 落地后必须跑第 6 步 `verify`;缺 `oracle` / `coverage` → 输出提示,把「补基线 / 补登记覆盖率」回流设计侧(场景还原应给)。
205
- **覆盖率校验**:`coverage.covered` 必须等于 `coverage.applicable`、`gaps` 为空,否则打印缺口清单——`C < A` 即**欠声明**(有规范子项未落进 `changes[]`/`visible`/`pending`),属设计侧交付不完整,必须回流,不得在项目侧"猜着补"。
206
-
207
- ### 第 1 步附加 · 挂载点审计(,静态查三类隐性缺口)
208
-
209
- ```bash
210
- node parser/index.js audit --project <目标项目根目录> [<changeset.json…>]
211
- ```
212
-
213
- 不开浏览器即可查出的三类历史高发缺口:
214
-
215
- | 检查 | 抓什么 | 对应历史缺口 |
216
- |---|---|---|
217
- | **挂载点缺失 / 可疑** | `selector` / `anchors.target` 里的类名在项目里**只在样式文件出现、模板没挂**,或**完全找不到** | 列未绑 `class-name` → 金额列右对齐 / 缩略图尺寸永不生效;操作栏规则有定义无引用 |
218
- | **死通道** | `anchors` 里的 CSS 变量在项目中**无 `var()` 消费者**(两类豁免:`--el-*` 组件库变量由 EP 运行时消费;设计层已显式接管定义的变量属故意 suppress) | 变量有定义无引用,翻译再准也不生效 |
219
- | **词典无此条目** | 变更集引用了词典未建的 ID | L3 新增点位须当场落地并回写临时映射 |
220
- | **G2 structure_ops 施工证据** | 变更集声明 `structure_ops` 的点位,按词典 anchors/selector 语义类名 + `op.node` 提取探针,在**非设计层结构源码**中查证施工痕迹;零命中 = 纯 CSS 冒充结构施工 | 操作列分割线 `add_node` 声明多轮从未施工 |
221
- | **G4 T 通道对账** | `global.brand_primary`(语义值解析 hex)↔ `platform-config.EpThemeColor`;页签 `form` ↔ `ShowModel`;`visible:false` 点位的 `visible_prop` 开关 ↔ platform-config 实值 | 变更集孔雀绿、platform-config 残留旧主题;flat 页签叠加 chrome 结构 |
222
-
223
- 挂载点疑似但**设计层文件已承载该类名** → 降级不阻断(C 通道由 design-shell 兜底是合法落点)。G2 / G4 违规与挂载点问题同置 `exitCode 1`。审计报错 = **能力缺口**:当场按 `structure_ops` 补挂载 / 补消费者,交付说明单列申报;不得以「词典没建」为由跳过。审计通过 ≠ 还原达标——**静态审计查不出「值对了、位置不对」**,那要靠第 6 步渲染态验收。
224
-
225
- ### 第 1 步附加(之二)· 登记表覆盖率(子项级细闸 · )
226
-
227
- 组级台账(`restore-checklist`)只能防「整组忘光」;**组内子项**是否被静默丢失,用登记表计数。
228
-
229
- ```bash
230
- node parser/index.js match <cs.json> --registry <restore-registry.json> # 匹配 + 覆盖率当场重算
231
- node parser/index.js registry <restore-registry.json> [--verbose] # 只核验登记表对词典的通道就绪度
232
- ```
233
-
234
- | 量 | 定义 | 谁重算 |
235
- |---|---|---|
236
- | **R 登记项** | 登记表条数(= 规范里带样式结论的子项数) | 读表 |
237
- | **A 适用** | `always:true` 的子项 ∪ 效果图已标注同名 `data-sid` 的子项 | parser 当场算 |
238
- | **C 兑现** | A 中在 `changes[]` / `visible:false` / `pending[].proposed_id` 出现者 | parser 当场算 |
239
- | **缺口** | `A − C`,逐条列出 `rule + sid + dims`(同组超过 6 条需加 `--verbose` 展开) | parser 当场算 |
240
-
241
- **关键口径**:A/C **由 parser 以登记表为权威当场重算,设计侧自报的 `coverage` 数字不参与**——所以「把 applicable 写小」蒙混不过去。有缺口 → `exit 1`,属**交付不完整**,回流设计侧补齐后重跑。
242
-
243
- 另有一项**效果图标注缺口**告警:`always:true` 的子项若在效果图里找不到同名 `data-sid`,基线根本抽不出来(效果图标注粒度必须与登记表同分辨率,否则第 6 步的 oracle 必然残缺)。
244
-
245
- `registry` 子命令单独回答「这张登记表里有多少必登项在项目侧真有承载字段」:
246
- - **硬缺口**(引用了词典不存在的点位且未标 `pending`)→ `exit 1`;
247
- - **通道缺口**(设计侧维度在词典无对应字段)→ 列出,属**项目侧补词典**事项,补齐后还原度才可达 100%。
248
-
249
- ### 第 2 步 · 结构先行(visible / position / form)
250
-
251
- **先改结构,后改样式**——结构变了选择器才稳定,样式才有处可落。
252
-
253
- - `visible: false` → 按条目 `visible_prop`(如 `platform-config.json` 的 `HideTabs`)或组件 `v-if` 隐藏;无现成通道时 `display: none`,作用域限定在条目 `style_scope` 内。**不删除任何代码行。**
254
- - `position` → 优先用 flex 顺序(`order` / DOM 位置调整),禁止绝对定位像素坐标。
255
- - `form` → 按条目 `forms` 枚举切换(如 tabs 的 `chrome`/`card` 走 `platform-config.json ShowModel`;内容区滚动模式走 `admin.content.container` 的 form(`fixed`/`scroll`/`auto` → 路由组件根节点 `data-content-mode` 属性,`auto` 为省略即钩子类探测)。枚举外的形态 → 报告,不猜。
256
- - **结构维度缺失即申报,禁止「只改令牌冒充落地」**:变更集把结构/方位/有无类意图写进 `style`(如指示条只在 `style.menu_active_indicator` 出现、无对应 `form`)时,按「结构意图缺失」处理——交付说明申报「设计侧需补 form + 几何 + 色值」,不得只覆盖颜色令牌交差(历史事故:竖条只换令牌 → 图上有、页面上没有)。
257
- - `form` 的落点按上文「落地三落点判据」执行:**有 DOM/配置通道走通道,无通道需新节点走结构增量,纯视觉形态走设计层样式文件**。当某形态在本项目只有样式表达(如菜单指示条方位)时,该 form 允许落到样式层——这与「禁止把内容区高度模式降级成 SCSS」不冲突,判据是**该形态有没有非样式通道**。
258
- - `layout_type` → 改 `platform-config.json Layout` 字段,值域 `vertical/horizontal/mix`。**大屏全屏沉浸式等独立页不走此通道**(设计侧不填 `layout_type`,点位走 L3 落地)。
259
-
260
- **存在性收口(通用机制,第 2 步随结构处理)**:变更集未声明的**出厂多余元素**(设计效果图上不存在的按钮/图标/入口,如顶栏设置按钮)→ 按各条目口径处理:有条目者在对应点位上以 `visible:false` 收口(代码保留,`v-if`/`display:none`);无条目者列入缺口清单申报「设计侧未声明,按无此元素收口」,同样以隐藏通道落地。禁止既不声明也不收口、让出厂元素顶替设计效果(顶栏设置按钮漏收口已实证:效果图无此按钮,落地后仍显示)。反向同理:**设计声明了而出厂没有的元素**(如欢迎区问候语)必须按条目 `$note`/设计规范补齐结构(结构通道豁免底线二),缺失 = 未交付。
261
-
262
- **结构/样式图层分工**:`form`(高度模式、形态枚举)是**结构意图**,必须落到 DOM 属性/组件开关/配置字段(如 `data-content-mode`、`ShowModel`);**禁止把结构意图降级翻译成 SCSS 变量写进样式文件**(form=scroll 只写 `--vts-margin` = 未施工,已实证)。样式文件(如 design-shell.scss)只承载 css_vars/custom_style_map 翻译产物;壳层通用文件禁止代打页面级结构属性(lay-content 硬编码 `data-content-mode="scroll"` 曾压掉 `:has()` 自动定高探测,useTableSearch 高度链断裂致列表区整体崩坏——已回退,禁止复活)。
263
-
264
- **结构链不可侵(高度链保命红线)**:内容区高度链是**结构层**,已与视觉解耦,两侧各有边界——
265
-
266
- | 结构层(禁止改写) | 视觉层(设计自由落点) |
267
- |---|---|
268
- | `data-content-mode`(滚动归属,**页面根节点属性**) | 页面容器形态(卡 / 通栏 / 自绘)、底色、圆角、边框、内边距、阴影 |
269
- | `data-fill`(填满剩余高度,**逐层节点属性**) | 容器内部排布(标题区 / 筛选区 / 表格区的位置与间距) |
270
-
271
- - 设计要求换掉出厂卡片容器(去卡片、改通栏、改内部排布)→ **照做,不打折**:页面根声明 `data-content-mode`,把 `data-fill` **平移**到新容器及其「体」层,视觉全落设计层文件。此路径下 `tableHeight` 几何实测照常成立。
272
- - **双向禁止**:① 以「保高度」为由拒绝改容器/内边距/去卡片(= 放弃设计还原);② 为凑还原效果改写壳层结构层规则、或在视觉层重写/压掉 `[data-fill]` / `.main-content[data-content-mode]`(= 高度链断裂,返工项)。
273
-
274
- #### 第 2 步附加 · 结构施工(structure_ops)与优先级策略()
275
-
276
- **A. 结构施工 `structure_ops`(数据 / 结构驱动点位)**——有些点位**换不掉也写不出来**,因为呈现由数据源或模板结构决定。变更集给出 `structure_ops` 时必须照做,**只写 CSS = 无效声明**:
277
-
278
- | `op` | 含义 | 施工动作 |
279
- |---|---|---|
280
- | `add_node` | 新增语义节点 | 在模板按 `form` 保形插入(不删原代码),落点见「落地三落点判据」第 2 条 |
281
- | `remove_node` | 移除语义节点 | 按 `visible:false` 收口(隐藏不删);确需物理移除时先确认无业务耦合 |
282
- | `move_node` | 调整节点位置 | 优先 flex `order` / DOM 位置调整,禁止绝对定位像素坐标 |
283
- | `render_branch` | 补渲染分支 | 例:状态列 `formatter` 返回纯文本 → 改为 `el-tag` 分支(`source` 指出数据来源) |
284
- | `bind_source` | 绑定数据源 | 例:金额列补 `class-name` / `align`、缩略图列补 `class-name` —— 属数据侧结论,**改 CSS 不算** |
285
-
286
- **判据一句话**:**这个点位的呈现,改 CSS 能改吗?** 改不了(图标在数据里、Tag 在模板分支里、类名没绑)→ 必须走 `structure_ops`;能改(颜色 / 圆角 / 间距)→ 走第 3 步样式落地。
287
-
288
- **B. 落点层级 `layer`(专治「值对了、位置不对」)**——同一点位的样式可能落在**宿主盒**或**内层文本盒**,两者不通用:
289
-
290
- - 变更集给了 `layer` → 严格按 `layer` 从条目 `anchors` 取对应选择器(parser 已在转换计划里给出 `@ … · host/inner 层`)。
291
- - 变更集**没给** `layer`、但条目 `preconditions` 指出必须落内层(如 EP 表头 `white-space`)→ 按 `preconditions` 落 inner 层,并在交付说明注明「设计侧未给 layer,按条目前置条件处理」。
292
- - **内层盒属性族强制校验**:`white-space` / `text-overflow` / `overflow` / `word-break` / `text-align` / `line-height` / `vertical-align` 这组属性**只在内层文本盒生效**——逐字段核对 `layer`;未指认且条目前置条件也没说 → **退回设计侧补声明**,禁止默认落 host(历史缺口:表头「禁止换行」落 host 被内层默认 `normal` 吃掉 → 表头竖排、行高撑大、列内容被压)。
293
- - 常规分工:高度 / 背景 / padding 落 host;文本换行、省略、对齐落 inner。
294
- - **几何语境必须随值迁移(双重内边距,历史缺口:表头标题截断成 类…/包…/操…)**:出厂内层文本盒自带 padding 时(EP `.el-table .cell` 出厂 `padding: 0 12px`),把设计的 16px 落到 host 后**必须同步清零内层自带 padding**——否则实际内边距 = 16+12 = 28px/侧,列宽被挤、表头标题被省略号截断、视觉不适配常规。判据:**效果图的距离语义是「列缘到文字」的总距离;宿主/内层两层结构下必须拆成两段落地,两段之和等于设计值**。凡向 host 落 padding/border 类几何值,先查出厂内层盒的自带同族值再决定是否归零。
295
-
296
- **B2. 出厂形态互斥收口 `suppress`(治「新形态上了、旧形态残留」)**——条目带 `suppress` 时,逐通道执行收口,**收口优先走令牌重映射**(在令牌宿主作用域重声明令牌,零权重战争),令牌不存在才写属性:
297
-
298
- - 每条通道收口后必须在交付说明列出「通道名 → 收口方式 → 落点」,漏一条 = 出厂旧装饰残留。
299
- - 实例:侧栏 `form=pill` → `suppress: ["右指示条通道"]` → 在侧栏作用域把出厂右竖条令牌重映射为 `none`(出厂 `.el-menu-item.is-active { border-right: var(--…) }` 与 `design-tokens` 的 `3px solid` 令牌都无需改动)。
300
- - 页签 `form=flat` 属**多通道收口**:透明化激活底色块 + 去圆角间距 + 关闭钮常显 + 贯穿分割线 + 首页页签仅图标——必须逐通道列出并收口,漏任何一条 = 「整个样式和设计不一样」。
301
-
302
- **C. 覆写优先级 `priority`(禁止逐点硬堆 `!important`)**——条目 `priority.strategy` 给出本点位该怎么赢:
113
+ 各步骤**子文件按需加载**(上下文预算纪律:做到哪一步读哪一份,禁止一次全部通读):
303
114
 
304
- | 策略 | 施工口径 |
305
- |---|---|
306
- | `scope_qualified` | 用条目 `style_scope` 作用域限定即可覆盖 |
307
- | `self_plus_important` | 目标处于**行内 style**(`:header-cell-style` 等)竞争下 → 先移除页面行内样式;无法移除时,作用域内提权并在交付说明申报 |
308
- | `deep_qualified` | 目标与**组件 scoped 规则同权重** → 提高选择器权重或走深度选择器显式取胜(**不能只靠「后置加载」**) |
309
-
310
- > **为什么必须显式处理**:同权重时胜负由样式注入顺序决定、不可控;靠「加 `!important` / 加宽选择器」逐点硬压,会把互不相干的点位耦合起来、副作用无人发现 → **累积成漂移而不是收敛**(这正是「越改越乱」的机理)。
311
-
312
- ### 第 3 步 · 样式落地(两层转换 + 语义值译表)
313
-
314
- 对每个 `style` 字段,按 parser 转换指令执行(parser 已把语义值解析为精确值,如 `钴蓝-5` → `#245BFF`)。**冲突裁决规则(免问):凡变更集声明与项目出厂现状/模板既有口径冲突,一律按变更集执行——变更集是唯一施工依据,不反问、不逐次确认。**
315
-
316
- 1. **css_vars 层(优先)**:在条目 `style_scope` 作用域内覆盖该 CSS 变量。
317
- ```scss
318
- // 例:admin.layout.sidebar.menu 的 menu_bg = 钴蓝-9(#0D2A7F)
319
- .sidebar-container {
320
- --vts-theme-menu-bg: #0D2A7F;
321
- }
322
- ```
323
- 2. **custom_style_map 层(兜底)**:无官方变量可用时,生成 `:deep()` 隔离样式。
324
- ```scss
325
- // 例:admin.layout.header.user_profile 的 avatar_width
326
- .navbar :deep(.el-dropdown-link img) { width: 36px; height: 36px; }
327
- ```
328
- `sub_selectors` 有定义的字段(如 `avatar_*` → img、`name_*` → p)按对应选择器路由。
329
- 3. **两层都未命中** → 值合法且选择器可定位时,当场生成作用域内自定义规则落设计层文件并在交付说明申报;仅「值非法 / 无法定位」才进缺口清单。
330
- 4. **值未命中译表且非 hex**(parser 会提示)→ 能按数值字面量 / hex / 上下文判定的当场落地并申报;仅完全无法判定时进缺口清单、回流设计侧补齐(**不向用户反问**)。
331
-
332
- 全局令牌(`global` 字段,**整套主题切换优先通道**)→ `design-tokens.scss` 对应变量(`basic/` 词典翻译,语义值走 `mapping/basic/semantic-values.json` 译表),主色走 `setEpThemeColor()` 链路。**壳层模块底色注意**:顶栏底色不走 global(无独立令牌),须以 `{"id": "admin.layout.header", "style": {"bg": "<值>"}}` 场景条目声明(scoped 覆盖 .navbar 底色);侧栏底色两者皆可——global 走 `sidebar_bg`(--sidebar-bg 令牌链),场景条目走 `admin.layout.sidebar` 的 `bg`(--vts-theme-menu-bg)。
333
-
334
- ### 第 3 步附加 · 设计层落点文件(强制)
335
-
336
- 所有「新增的 CSS 规则」一律写入 **`src/styles/design-shell.scss`**(出厂空文件,经 `index.scss` 末位 `@use` 加载),或写入页面级 `<style scoped>`;**不得**写进 `sidebar.scss` / `element-plus.scss` / `theme.scss` / `lay-*.vue` 等出厂文件去表达某张效果图的结论。
337
-
338
- ⚠ **「末位加载」只决定「同源、同特异度」时的先后,压不过两类对手**——这是「规则明明写了却不生效」的头号成因:
339
-
340
- | 对手 | 为什么本文件会输 | 取胜方式 |
341
- |---|---|---|
342
- | **组件 `<style scoped>`** | Vite 下组件样式在全局样式**之后**动态注入;scoped 选择器末元素带 `[data-v-x]`(按一个类计权)。同特异度时后注入者胜 → 本文件出局 | 提权(≥3 层作用域限定 / 叠加属性伪类)——**不是靠文件顺序** |
343
- | **出厂规则里的 `!important`** | `!important` 高于任何特异度,提权无效 | 本点位也必须 `!important`,或改走通道变量 |
344
-
345
- 每写一条新规则前,先按第 1 步输出的 `▸ 覆写优先级 priority` 判定对手类型与取胜方式(见下节)。
346
-
347
- #### 特异度必须**逐位比较**(`html` / `body` 抬不动「类位」)
348
-
349
- 特异度写成三元组 `(a, b, c)`:`a` = id,`b` = **类 / 属性选择器 / 伪类**,`c` = 类型选择器 / 伪元素。比较顺序是**先比 `a` → 再比 `b` → 最后比 `c`**,`b` 位为 0 时 `c` 再大也没用。
350
-
351
- - `html` / `body` 是**类型选择器**,只加 `c` 位。对手 `b` 位更高时,加 `html body` **完全无效**。
352
- - 对手是组件 scoped(末元素 `[data-v-x]` 只加一个类,`b` 通常 ≤2)时,「抬一级作用域」有效;对手是 `body[layout='vertical'] .sidebar-container .el-menu-item`(属性 + 2 类 = `b=3`)时,`html body .sidebar-container .el-menu-item`(`b=2`)无论再加多少 `html`/`body` 都赢不了。
353
- - 正确的抬法是**加类**:在祖先链上补稳定的语义类(如 `.el-menu`)把 `b` 抬到与对手相等,再靠 `c`(`html body`)胜出。
354
-
355
- > **实例(已发生的回归)**:`sidebar.scss` 的 `body[layout='vertical'] .sidebar-container .el-menu-item { color: var(--vts-theme-menu-text) !important }`(`b=3`)压掉了设计层的 `html body .sidebar-container .el-menu-item { color: rgb(255 255 255 / 65%) !important }`(`b=2`)→ 菜单文字改用出厂令牌的**浅色主题值(黑)**落在设计强制的深色侧栏上 → **整栏菜单字全部消失**。规则没写错,是权重没算对。
356
-
357
- #### 改通道(令牌)优先于抢属性
358
-
359
- 出厂用**语义令牌间接**设置属性时(`color: var(--vts-theme-menu-text)`、`background: var(--vts-theme-menu-bg)`…),**不要写同名属性去抢**,而是**在令牌宿主作用域重映射令牌**:
360
-
361
- ```scss
362
- html body .sidebar-container { /* 令牌宿主 = 该令牌被消费的元素所在作用域 */
363
- --vts-theme-menu-text: rgb(255 255 255 / 65%);
364
- }
365
- ```
366
-
367
- 判据:**令牌在哪个元素上被声明,就在那个作用域重映射**。自定义属性按继承解析,出厂规则自己会消费新值 ⇒ **零权重战争**,也不受对手 `!important` 影响。适用范围:`--vts-theme-*` 全族。
368
-
369
- 只有在「出厂没有该令牌」或「令牌语义与设计不符(如胶囊几何 `inset`/`radius`)」时才回到抢属性,并按上一条逐位比较。
370
-
371
- **统一顺序:① 先找令牌通道 → ② 无通道才抢属性(逐位比特异度)→ ③ 都不行才 `!important` + 注释对手。**
372
-
373
- > 上例的正解就是①:在设计层把 `--vts-theme-menu-text/bg/hover/active-bg` 在 `.sidebar-container` 上重映射,出厂规则自己就画出白色的字与蓝色胶囊。
374
-
375
- 写入纪律:
376
-
377
- - **本文件是产物,不是手改对象(流程红线)**:`design-shell.scss` 的每一行都必须由「变更集 + 词典」经本协议产出——发现缺规则时,正确动作是**补词典字段 / 前置条件 / 登记项**让下一次 design-apply 自动生成,**禁止绕过流程直接手写项目文件**。历史规则已落词典的(侧栏令牌 / suppress / 表头内层 nowrap / 双重内边距归零 / 分割线通道),重生成后会自动带出;仅「补通道」(变量消费者 / form 枚举 / 组件中性默认)允许动出厂源码并单列申报。
378
-
379
- - 每条规则带来源标注(`/* <语义 ID> · <变更条目> */`),换设计时整段可替换;
380
- - 本文件内新增的 CSS 变量必须**定义 + 引用成对出现**(出厂已有消费者也算),避免死通道;
381
- - 出厂元素需关闭时(存在性收口)也在这里做:令牌置 `transparent` 或 `display:none`,**绝不删出厂代码行**;
382
- - 出厂 `--vts-theme-menu-active-before` 默认 `transparent` 且无消费者 → 声明 `form=indicator_*` 时必须在此文件内**同时**落地「关胶囊令牌 `menu_active_bg: transparent`」与「新建 `::after` 消费者」,缺一即未施工成功。
383
- - **自举(项目被还原到出厂时必做,幂等)**:文件不存在 → 新建(仅保留文件头纪律注释,无任何设计结论)+ 在 `src/styles/index.scss` **末位**补 `@use 'design-shell';`(必须末位,靠后置压出厂)。此动作属「补通道」,交付说明单列申报。**文件缺失时径直把设计规则写进 `element-plus.scss` / `sidebar.scss` / `theme.scss` = 污染出厂文件,禁止**(这也是「设计还原度为零」的常见成因:规则无处可落)。
384
-
385
- ### 第 3 步附加(之二)· 覆写优先级消费( 硬步骤)
386
-
387
- 第 1 步输出的 `▸ 覆写优先级 priority` **不是提示,是落地写法的硬要求**。每落一条规则前先按策略决定写法;写法错了,规则就是「写了不生效」。历史缺口「面包屑 `visible:false` 写了 `display:none` 却照旧显示」「页签关闭钮 `opacity` 写了却仍要 hover 才显」全部源于此——两条规则本身都没写错,是**赢了才是硬道理**这一步没人做。
388
-
389
- | `priority.strategy` | 对手 | 必须的写法 | 自检判据 |
115
+ | 步骤 | 子文件 | 内容 | 加载时机 |
390
116
  |---|---|---|---|
391
- | `scope_qualified` | 无,或出厂**全局样式**(`sidebar.scss` / `element-plus.scss` / `theme.scss`,注意它们也在 `index.scss` 的 `@use` 链里、可能带 `!important` 且 `b` 位更高) | 按词典 selector 原样落;**逐位比过对手**(先 b 后 c);出厂用 `var(--vts-theme-*)` 时优先重映射令牌 | 若实测仍被覆盖 → 升格按 `deep_qualified` 处理 |
392
- | `deep_qualified` | 组件 `<style scoped>`(平手 + 后注入) | **禁止裸类名**。≥3 层作用域限定(如 `html .a .b`)或叠加属性/伪类;仍平手才对本条补 `!important` | 写前自问:这条与组件 scoped 谁特异度高?**平手即错** |
393
- | `self_plus_important` | 出厂规则带 `!important` | 本条必须 `!important` + 注释写明「对手带 `!important`」;能改走通道变量时优先改通道 | 只抬特异度无效,别白费 |
394
-
395
- 落地写法模板(每条规则标注来源 + 取胜依据):
396
-
397
- ```scss
398
- /* <语义 ID> · <变更条目> · 取胜依据:deep_qualified(对手 lay-*.vue scoped) */
399
- html .navbar .navbar-breadcrumb-wrap {
400
- display: none; /* visible:false · 存在性收口,不删出厂代码行 */
401
- }
402
- ```
403
-
404
- **`!important` 只允许出现在两种情形**:① `strategy = self_plus_important`(对手带 `!important`);② 对手是组件 scoped 且提权后**实测**仍平手。其余一律靠作用域限定解决——逐点堆 `!important` 会让点位互相耦合、副作用累积成漂移,也就是「越改越乱」的机理。
405
-
406
- ### 第 4 步 · L3 新模块处理(分级布局)
407
-
408
- - **验收对象闸(角色集合必须齐)**:验收页面的**角色集合**必须覆盖变更集声明的角色。缺角色的,按第 0.2 步「对接匹配 → 需适配」处置——**项目侧补齐该角色的骨架 / 结构**(走 `crud-pages` 样板 + L3 落地并申报),**不是要求设计侧换页面**。不得用出厂 demo 页充数:demo 页**结构上就没有**标题区 / 批量按钮 / 状态 Tag 这些角色 → 这类差异**无论怎么调 CSS 都消不掉**(不是样式问题,是角色集合不匹配)。
409
- - **列宽口径(业务层 / 设计层边界)**:表格**业务列宽度属业务层**,设计侧不声明、项目侧不按效果图硬套——效果图里的列宽只是其示例数据下的参考值。**唯一例外是操作列**:宽度由组件公式推算(`resolveOperateColumnWidth`,已含分割线占位),业务页禁止写死。**固定列自查(落完后必做,防「符合规范但不合常规」)**:操作列按钮不被裁、不换行、分割线居中可见;状态列标签完整;表头/单元格标题不被省略号截断——任何一项不满足即返工,禁止用「设计值就是对的」搪塞。
410
-
411
- - **L3 是施工指令,不是待办**:词典未命中的点位一律当场落地、交付说明申报「补映射」,不留待确认。新模块按「定制布局」三步走:① 基于全局规范生成结构(继承命名/作用域/组件规范)② 原子层字段(色彩/圆角/组件级)从 `basic/` + `component/` 词典借力 ③ 场景专属点位生成后**立即写入 mapping/ 对应场景域**(临时映射),累计复用 ≥3 次建议升级标准(由人工评审)。
412
- - 生成的新页面必须带构图钩子(`vts-page-card` / `vts-filter-area` / `vts-table-area` 等),保证后续变更集可命中。
413
-
414
- ### 第 5 步 · 合规闸门(变更集专属检查)
415
-
416
- 跑 `code-quality` 全量清单之外,追加:
417
-
418
- - [ ] 变更集外的任何点位**零改动**(diff 只含变更集提到的文件/选择器)
419
- - [ ] `visible: false` 的模块代码仍存在(只是隐藏)
420
- - [ ] **`!important` 使用合规**:新增 `!important` 仅允许两种情形——① 词典 `priority.strategy = self_plus_important`(对手带 `!important`);② 对手为组件 scoped 且提权后**实测**仍平手;且每条带理由注释。其余一律靠作用域限定解决。无内联 style 硬编码色值(全部走变量)
421
- - [ ] 未修改 `src/components/`(Re* 组件库源码——**底线一**)
422
- - [ ] 未改动业务逻辑层(API/状态/事件——**底线二**;样式与结构通道内的 DOM 调整除外)
423
- - [ ] 两层样式全部落在 `style_scope` 作用域内,无全局泄漏
424
- - [ ] **类名冲突检查(AI 施工硬性步骤)**:新增 class 之前先在目标文件与同作用域全局样式中检索同名类——已存在时禁止直接追加重复定义,按三选一处理并在交付说明申报:① 语义相同 → **合并**进既有规则;② 语义不同 → 改用带点位前缀的新类名(如 `vts-<语义id末段>`);③ 确需覆盖 → 走作用域内更高优先级(不写 `!important`)。重复类名(尤其跨 `<style>` 块的 scoped 样式重复定义)会触发编辑器/构建报错,**本项不通过不得交付**
425
- - [ ] **出厂中性检查(架构红线,不通过必须回退重做)**:diff 中不得出现「为表达本次设计而改写出厂文件」的产物——典型症状:把指示条方位/问候语 DOM/某个具体尺寸直接写进 `sidebar.scss`、`element-plus.scss`、`lay-navbar/index.vue`、`lay-content/index.vue` 等出厂载体;在出厂 `<component>` 上硬编码 `data-content-mode`/样式钩子。出厂文件若被改动,只能是「补通道」(补变量消费者 / 补 form 枚举 / 修层叠优先级,如已修的 `:has()` 与显式模式优先级反转),且必须在交付说明单列「补通道」条目写明缺失点;非此情形一律回退,改由 `design-shell.scss` + 变更集驱动。**模板源码注释保持中性**:diff 中不得出现「语义 ID / 本协议步骤号 / 面向 AI 的纪律条款」写进模板源码注释(如 `lay-content/index.vue`、`element-plus.scss`、`design-shell.scss` 的文件头与段落注释);这类内容只允许存在于技能侧文档
426
- - [ ] **文本溢出回归检查**:改动侧栏菜单/顶栏/页签等含文字的模块后,必须确认「长文本显示」未被破坏(菜单项名称完整可见,必要时保留 ellipsis 溢出策略而不是隐藏/截断);宽度相关字段(width/min-width/padding)改动后逐项目视验证
427
- - [ ] **形态与存在性目视验证(历史漏还原高发区,声明即必须验证,没做视同未交付)**:变更集声明了以下意图时,逐项在页面上确认真实生效——
428
- - 语言切换 form=inline_switch → 顶栏出现「中|EN」并排文字(不再是纯图标)
429
- - 折叠按钮 form=header_inline → 顶栏最左出现 40×40 折叠按钮且与首页页签左对齐;**同时侧栏底部出厂折叠条按设计隐藏(visible:false 声明时)**,避免双折叠按钮并存
430
- - 侧栏 `menu_active_*` / `form=indicator_*` → **按变更集声明的 form 逐项核对**(indicator_left → 左侧竖条;indicator_right → 右侧竖条;indicator_underline → 底部横线;pill → 胶囊底色;none → 无指示):方位/粗细/长度/圆角与变更集 style 字段一致,且出厂胶囊已关闭(`--vts-theme-menu-active-bg: transparent`)、`--vts-theme-menu-active-before` 消费者真实建成。**禁止用「左侧 3px」这类历史/词典结论替代当次声明**——设计换了就必须是新的方位与数值
431
- - 顶栏未声明点位(设置按钮等)→ 已收口不显示;用户区 → 按 `form` 核对组合形态(`avatar_name` / `greeting_avatar_name` / `greeting_name` / `avatar_only` / `name_only`),其中 greeting 为结构增量节点(出厂无此 DOM,需 AI 按 form 插入后再验)
432
- - 页签图标 → 按 `form` 核对(item 的 `text_only`/`with_icon`,home_tab 的 `icon_only`/`text`),出处是路由 `meta.icon` 数据或本次隐藏规则,不是源码常量
433
- - 内容区 form=scroll/fixed → `data-content-mode` 属性落在**页面根节点**(不是样式文件、不是壳层组件),列表页自动定高未被压掉;填满链逐层带 `data-fill`(详见下方「高度链存活检查」)
434
- - 操作栏 form=with_tools/left_batch → 刷新/密度/列设置三件套齐全;批量删除红底/导出白底/未选中置灰
435
- - 操作列 form=text_link → **业务列定义的 icon 字段已移除**(纯文字无图标,只改 CSS 保留图标 = 未还原);按钮单行不换行(列宽 ≥160px + nowrap);删除项红色;≥3 个折叠「更多」带箭头
436
- - tabs form → 页签形态切换生效(chrome/card);激活态表现(有无下划线 / 是否仅文字变色 / 字重)按当次变更集 style 字段核对,**不以历史设计稿口径为准**
437
- - [ ] **高度链存活检查(结构层不被设计改动压垮,也不被"保高度"绑架)**:定高页(`form=fixed` 或列表页自动定高)还原后逐项确认——
438
- - `data-content-mode` 落在**页面根节点**;从页面根到表格/画布容器**每层需填满的节点都带 `data-fill`**(换了视觉容器时属性已平移;横向分栏用 `data-fill="row"`);
439
- - `content` ref 仍绑在定高容器上(换容器后未丢),`otherRef` 仍在表格上方、分页仍在表格正下方;
440
- - 表头 / 行 / 分页都在视口内,仅表格体内滚动,无外层滚动条、无拉伸 / 塌陷 / 双滚动条,`tableHeight > 0`;
441
- - **结构层 diff 为空**:`lay-content/index.vue` 的 `.main-content[data-content-mode]` 与 `element-plus.scss` 的 `[data-fill]` 未被改动;同时确认没有「为保高度而放弃设计还原」(出厂卡片 / 内边距 / 内部排布原样未动而变更集声明了改动)——两个方向任一命中即返工
442
- - [ ] **映射通道活性检查(杂必查)**:样式落地引用的每个 CSS 变量必须在项目样式中**存在消费者**(`变量名` 有 `var(--xxx)` 引用点);只定义不消费的变量 = 通道死路,翻译再准也不生效(menu_active_indicator 曾因 --vts-theme-menu-active-before 无消费者而「映射了却没效果」)。施工时 grep 核对,无消费者时改走消费者存在的作用域或补挂载点并申报。
443
- - [ ] **结构施工兑现检查(structure_ops 逐条对账,与红线同级)**:变更集 `structure_ops[]` 的**每一条 op** 都必须在交付说明给出「op → 落在哪个文件 / 哪个节点 / 怎么落的」;`add_node` 必须真的新增了元素或渲染分支(模板 diff 可验),`bind_source` 必须真的改了绑定(`class-name` / `align` / `formatter`)。出现「声明了 op、代码里找不到对应改动」= 交付不完整,禁止只改 CSS 冒充结构施工(历史缺口:操作列分割线 `add_node` 声明了但从未施工 → 按钮间竖线一直缺失)
444
- - [ ] **同权重失效检查( · 专查「写了不生效」)**:逐条核对设计层新增规则是否真能取胜——① 对手是组件 `<style scoped>` 时,本条特异度必须**严格高于**它(**平手即错**,因为组件样式在全局之后注入);② 对手带 `!important` 时本条必须同样 `!important`,或改走通道变量。**判定方法(必须真数,不许目测)**:对每条新规则与其对手分别写出特异度三元组 `(a,b,c)` 并**逐位比较(先 b 后 c)**,本条的 `b` 不大于对手即判为「失效」;`html` / `body` 只加 `c` 位,**对手 `b` 更高时加 `html body` 无效**,必须靠**加类**(祖先链补稳定语义类,如 `.el-menu`)把 `b` 抬到相等。同 `b` 时,`c` 更高者胜。③ **出厂用语义令牌间接设置该属性时(`var(--vts-theme-*)`),必须先走「令牌重映射」而不是抢属性**——在令牌宿主作用域重声明令牌即生效、零权重战争;只有无令牌或令牌语义不符时才抢属性。历史缺口全部命中本项:面包屑 `display:none`(与组件 scoped 同为 0,2,0)→ 照旧显示;页签关闭钮 `opacity`(同为 0,5,0)→ 仍要 hover 才显;页签项 `padding`(对手带 `!important`)→ 无论怎么抬特异度都改不动;**侧栏菜单 `color`(`b=2` 输给出厂 `b=3` + `!important`)→ 整栏菜单文字用浅色主题的黑色落在深色侧栏上、字全部消失**
445
- - [ ] **oracle 基线可用性检查**:变更集带 `oracle` 时——① `oracle.mockup` 必须与**本次主题、本次页面**一致;**同构异色复用除外**:变更集声明 `oracle.theme_mapping: { "from": "<效果图主题>", "to": "<本次主题>" }`(同场景 / 同页面 / 同角色集合、仅主题色板不同)时,允许复用 from 主题效果图,verify 必须带 `--from-theme/--to-theme` 做色值归一,**不得因换主题色就判死闭环**;结构 / 形态有差异时禁止复用;② `oracle.sids` 与 `changes[]` **双向闭合**:效果图里有、changes[] 未声明 = **欠声明**(该点位永远不可能被还原);changes[] 已声明、效果图无 sid = **无基线**——**仅 `visible:false` 的隐藏点位豁免**(效果图上无可见元素可标 `data-sid`,parser 已自动豁免并打印清单)。其余两类出现即回流设计侧补齐,**不得直接开工**(`parser match` 已自动报出)
446
- - [ ] **dark.scss 暗色同步**:新增视觉规则在 `html.dark` 有对应覆盖
447
- - [ ] **缺口清单只含意图缺口**:清单每一项都必须是「设计侧未给值 / 值非法」且已注明「回流设计侧补齐」;能力缺口(词典缺 ID / 缺字段枚举 / 缺 form)不得出现在清单里——出现即把可落地项搁置
448
- - [ ] **台账逐行兑现对账(对账闸门)**:把设计侧交付的提取台账逐行过一遍,每行必须有落地结论——已落地(写明落在哪个文件/选择器)或已入缺口清单(写明缺失字段)。存在「台账有行、落地无结论」的行 = 交付不完整,与红线同级
449
- - [ ] **登记表覆盖率对账(子项级细闸,)**:带登记表交付时必须跑 `match --registry`——`C = A` 且无缺口才可交付;同时确认无「效果图标注缺口」(`always:true` 子项在效果图上都有同名 `data-sid`)。**禁止采信设计侧自报的 `coverage` 数字**(parser 会当场重算,自报数不参与);缺口逐条点名回流设计侧
450
- - [ ] **零搁置交付**:最终回复不含「待确认」类停顿项;交付说明的「补映射 / 补通道 / 缺口回流」三段齐全(无内容写「无」)
451
- - [ ] `node parser/index.js build --dry` 通过(mapping 若有临时新增)
452
-
453
- ### 第 6 步 · 渲染态验收(变更集含 `oracle` 时强制 · 闭环回路)
454
-
455
- 第 5 步是静态自查,查不出「值对了、位置不对 / 写了没生效」。**只要变更集带 `oracle`(效果图基线),落地后必须做机器逐点比对**——这是「1:1 还原」能被证明、且不再漂移的唯一手段。
456
-
457
- **链路(抽取由浏览器完成,diff 由 parser 完成)**:
458
-
459
- 1. **抽取期望值**:在浏览器打开效果图(`oracle.mockup`,元素已带 `data-sid`),对 `oracle.sids` 中每个 sid 取其代表性元素的 computed style,导出为 `{ "<sid>": { "<css属性>": "<值>" } }` → `oracle.json`。
460
- 2. **抽取实测值**:在浏览器打开已落地页面,**按词典 `selector` / `anchors.target` 定位元素**(**项目页不要求打 `data-sid`**)做抽取 → `actual.json`。
461
- - 先跑 `node parser/index.js verify --oracle oracle.json --resolve` 得到「sid → 词典 selector」定位计划;
462
- - 抽取脚本(Playwright / 浏览器控制台)按计划 selector 取 `getComputedStyle(el)` 的白名单属性(padding / font-size / font-weight / text-align / color / background-color / border-radius / gap 等);
463
- - **期望端(效果图)用 `data-sid`、实测端(项目页)用词典 selector——两侧定位方式不必对称**:效果图是设计侧自控产物,项目页是消费方、不感知设计坐标。selector 挂载点错位由 `audit` 先于 `verify` 报出,责任链回到词典;
464
- - 期望值**优先直接消费设计侧交付的 `oracle.json` 抽取产物**(期望 / 实测同源同口径);无产物时再从 `oracle.mockup` 现场抽取;
465
- - 两个页面的属性白名单必须一致,否则出现假缺口。
466
- 3. **逐点 diff**:
467
- ```bash
468
- node parser/index.js verify --oracle oracle.json --actual actual.json
469
- # 可选 --sids admin.content.table.header_cell,admin.layout.tabs.item 只验部分点位
470
- # 同构异色复用(oracle.theme_mapping 已声明时必带)——效果图色值按语义槽位归一为本主题色值再比:
471
- node parser/index.js verify --oracle oracle.json --actual actual.json --from-theme 钴蓝 --to-theme 橘橙
472
- ```
473
- 退出码:存在缺口(含存在性缺口 / 基线漂移)→ `1`。
474
-
475
- **归因与处置(四类,禁止用 `!important` 掩盖)**:
476
-
477
- | 归因 | 触发 | 处置 |
478
- |---|---|---|
479
- | **选择器落空** | oracle 有点位、actual 无(或某属性取不到) | 补挂载点:按 `structure_ops` 挂类 / 补 `data-sid` / 确认元素已渲染(属能力缺口,交付说明申报) |
480
- | **权重被压** | 颜色 / 字重 / 透明度 / 阴影类属性值不符 | 按词典 `priority` 声明的策略提权(`scope_qualified` / `self_plus_important` / `deep_qualified`) |
481
- | **语境错位** | 几何 / 盒模型属性(padding / 尺寸 / 对齐 / 行高)值不符 | 校准 `layer`(`host` vs `inner`)——值对了落错层 |
482
- | **存在性缺口(G12)** | `oracle.absent` 点位在页面仍渲染可见(`display` 非 `none`) | 补 `visible:false` 收口并按词典 `priority` 提权(历史缺口:面包屑 `display:none` 被同权重 scoped 规则反压——写了不生效也是它) |
483
-
484
- **存在性闸(`oracle.absent`)**:效果图上不存在的出厂点位(面包屑 / 设置铃铛等)逐条列入变更集 `oracle.absent`,verify 逐个断言「actual 不存在或 `display:none` / `visibility:hidden`」。**这类缺口无期望值,逐点 diff 永远验不到——不进 absent 就不在验收范围内**(2026-09-21 面包屑事故机制化)。
485
-
486
- **残差豁免(`oracle.residual_accepted`)**:`[{ "sid": …, "reason": … }]`(reason 必填)。命中豁免的属性差异降级为「已申报固有残差」提示行,不进缺口计数;验收报告单列豁免明细,逐条可审计。**机制推算值(等宽槽宽)、业务资产(logo 图形)必须申报**——不申报 = 每轮验收重新报缺口 = 「改了很多版始终不行」的体感来源。
487
-
488
- **快照回归(`--snapshot` / `--baseline`,治「上一轮改对的这一轮漂回」)**:
489
-
490
- ```bash
491
- # 每轮动工前:先对当前页面跑一次 verify 并导出快照
492
- node parser/index.js verify --oracle oracle.json --actual actual.json --snapshot snapshot-r1.json
493
- # 本轮交付前:带 --baseline 与上轮快照比对
494
- node parser/index.js verify --oracle oracle.json --actual actual.json --baseline snapshot-r1.json
495
- ```
496
-
497
- - 上轮 `hit` / `absent-hit`、本轮退步的点位 / 属性 = **基线漂移**,逐条列出且 `exit 1`——先回归上轮修法,再谈新缺口。
498
- - 项目还原到出厂(design-shell 回空壳)后第一轮验证**不带** `--baseline`(基线已失真),改以 clean 夹具重新起拍。
499
-
500
- **夹具与设计资产的边界(职责单侧沉淀红线)**:`「页面名-主题」`命名法(如 `运单管理-钴蓝.html`)是设计侧效果图库的专属资产命名——**项目侧(含 parser/fixtures 回归夹具)禁止出现与设计侧资产同名的文件**。回归需要 mockup 实物时,一律用「回归夹具-」前缀合成名(如 `回归夹具-列表页-钴蓝.html`),点集为回归机制定制、与真基线**不同且不可互替**;真实效果图基线唯一沉淀在设计侧 `page-specs/styles/<方案>/scenes/<场景>/mockups/`,项目侧 `oracle.mockup` 指向它靠 `resolveFirstExisting` 跨库解析(变更集同目录 → cwd → 技能根 → 设计侧兄弟目录),不做本地拷贝。
501
-
502
- - 验收结果写入最终回复(命中 N / 缺口 M / 归因分布 / 修正)与 `code-quality` 结果块;**不得只报「已完成」**。
503
- - 变更集无 `oracle` 时输出 `N/A`(无基线),并在交付说明注明「无验收基线」——这是设计侧应补的项,回流设计侧。
504
- - 静态审计(audit)与渲染态验收(verify)**互补**:audit 查「通道是否存在」,verify 查「渲染结果是否一致」,两者都过才算闭环。
505
-
506
- ## 词典维护纪律
507
-
508
- ### 出厂状态漂移(词典假前提 = 事故源,落地前必查)
509
-
510
- **项目可能随时被还原到出厂**(design-shell 回空壳、`.changeset/*` 消失、本体系此前补的通道全部消失)。因此词典里凡「出厂已具备 X」类表述必须满足:① X 是**真出厂能力**(对照出厂源码可验证);② 由本体系补建的通道一律写成**条件式**——「若缺失,按 structure_ops / 补通道流程补建并申报」,不写「已存在」。**落地前必须跑 `node parser/index.js audit --project <dir>`**:锚点/选择器/变量消费者存在性静态校验,会当场暴露词典假前提(曾发生:词典写「出厂已渲染分割线 / 工具栏行已挂语义类」,项目还原后全部失真 → 规则落空)。
511
-
512
- - mapping/ 是唯一事实源:施工前 `parser query <id>` 精读条目,**不凭记忆施工**。
513
- - **禁止编造的是「既有条目的映射」**(改既有 selector / css_vars / 变量指向 = 静默篡改,绝对禁止)。**词典缺 ID / 缺字段枚举不属编造**——那是新点位,按 L3 当场落地并写**新增的**临时映射条目,交付说明申报,等人工评审转正。
514
- - 「宁可不做,不做错」只适用于**设计侧未给值 / 值非法**的意图缺口;用它搁置能力缺口 = 交付失败。
515
- - 临时映射转正须人工评审;禁止静默修改既有映射条目的 selector/css_vars。
516
-
517
- ## 环境备注
518
-
519
- - parser 运行时在无 Node 环境不可用时:以本协议 + mapping/ JSON 直读方式人工执行三级匹配(词典即 JSON,逻辑同 parser),并在交付说明中注明「parser 未运行,人工匹配」。
520
-
521
- ## 端到端回归(改 parser/mapping 后必跑)
522
-
523
- ```bash
524
- node parser/regression.js # 一键跑完 A-V 二十二步(自动断言退出码与关键输出,任一失败 exit 1 并回显详情)
525
- npm run regression # 等价写法
526
- ```
527
-
528
- 分步展开(等价于 regression.js 内部步骤,排障时可单跑某一步):
529
-
530
- ```bash
531
- node parser/validator.js # A. 映射词典全量校验(含 semantic-values.json)
532
- node parser/index.js list --scene admin --verbose # B. 头部应输出映射集版本;ID/字段/形态清单
533
- node parser/index.js match parser/fixtures/changeset-pos.json # C. 正例:exit 0;钴蓝-5→#245BFF 译表解析;pending 功能描述输出
534
- node parser/index.js match parser/fixtures/changeset-neg1.json # D. 负例1:exit 1(缺 schema)
535
- node parser/index.js match parser/fixtures/changeset-neg2.json # E. 负例2:exit 1(mapping_version 不匹配)
536
- node parser/index.js match parser/fixtures/changeset-neg3.json # F. 负例3:exit 1(禁词/非法 ID/位置违规,逐条列出)
537
- node parser/index.js match parser/fixtures/changeset-legacy.json # G. 旧协议:exit 0 + layout 键/schema 历史值两条告警
538
- node parser/index.js match parser/fixtures/changeset-fullpage-restore.json # H. 整页场景还原样例:exit 0;壳层+内容区全模块 L1 命中;数值字面量(40px 等)透传无 ⚠
539
- node parser/index.js build --dry # I. 产物链自检
540
- node parser/index.js match parser/fixtures/changeset-v32-fields.json # J. 声明维:exit 0;输出「结构施工 structure_ops」与 layer / apply_via
541
- node parser/index.js audit --project parser/fixtures/fake-project parser/fixtures/changeset-v32-fields.json # K. 静态审计:夹具项目存在挂载点缺失/死通道 → exit 1
542
- node parser/index.js verify --oracle parser/fixtures/verify/oracle.json --actual parser/fixtures/verify/actual.json # L. 渲染态验收:夹具含三类故意缺口 → exit 1;归因计数 选择器落空1/权重被压1/语境错位2
543
- node parser/index.js match --registry parser/fixtures/registry-sample.json parser/fixtures/changeset-registry-gap.json # M. 登记表覆盖率细闸:夹具欠声明 2 条恒存在子项 → exit 1
544
- node parser/index.js registry parser/fixtures/registry-sample.json # N. 登记表通道核验:点位全部命中 → exit 0;输出含「登记表通道核验」
545
- node parser/index.js registry parser/fixtures/registry-bad.json # O. 登记表硬缺口:引用不存在且未标 pending 的点位 → exit 1
546
- node parser/index.js match parser/fixtures/changeset-neg4-g8.json # P. G8 模式闸负例:mode=restore 缺 oracle/coverage(伪还原变更集)→ exit 1
547
- node parser/index.js match parser/fixtures/changeset-neg5-g8-stub.json # Q. G8 强化负例:mode=restore 但 mockup/registry 空壳(有壳无芯伪基线)→ exit 1
548
- node parser/index.js match parser/fixtures/changeset-neg6-g9-identity.json # R. G9 身份闸负例:scheme=tangerine 却引 default 方案登记表(分母偷换)→ exit 1
549
- node parser/index.js match parser/fixtures/changeset-neg7-g10-dims.json # S. G10 dims 闸负例:header_cell 缺 text_align/nowrap(点位在细节丢)→ exit 1
550
- node parser/index.js match parser/fixtures/changeset-neg8-g11-oracle.json # T. G11 oracle 闸负例:橘橙主色配钴蓝效果图且无 theme_mapping(主题错配)→ exit 1
551
- node parser/index.js verify --oracle parser/fixtures/verify/oracle.json --actual parser/fixtures/verify/actual-clean.json # U. 残差豁免 + G12 收口正例:申报点位不计缺口、absent 已收口 → exit 0
552
- # V. 快照回归(两段式,regression.js 内部自动展开):clean 夹具导快照 → 缺口夹具比对 → 基线漂移 → exit 1
553
- ```
554
-
555
- 通过标准:regression.js 输出 `A✔ B✔ … V✔` 且 exit 0;分步跑时各步符合注释预期。夹具含义见各文件 `$comment`。
556
-
557
- ## 配套工具(作者/维护侧)
558
-
559
- - **watch 模式**:`node parser/watch.js` 或 `npm run mapping:watch`——监听 mapping/ 下 JSON 变更,自动「校验 + 重编 dist/」;校验失败不杀进程,修正后自动重试。
560
- - **业务级覆写 API**:`import { themeVars, overrideMapping } from '<skill>/dist/theme-vars.js'`——仅覆写指定字段,不改动基础映射;strict 模式下覆写词典外字段直接报错(防拼错静默失效)。当前 vue3-web-temp 不引入,服务于未来空白项目。
561
- - **mapping 版本流程**:所有 mapping/*.json 的 `meta.version` 恒为 `1.0.0`(由 SKILL.md 体系版本统一管理);`release.js` 发版前自动执行 `parser build` 刷新 dist/,产物随 NPM 包发布。
117
+ | 第 0 步 | [`step0-preflight.md`](steps/step0-preflight.md) | 第 0 步 · 版本与场景检查 · 对接匹配(适配前置)· 运行时清场 | 每次落地开工前(版本/场景/对接匹配/运行时清场三件套) |
118
+ | 第 1 步 | [`step1-match.md`](steps/step1-match.md) | 第 1 步 · parser 确定性匹配(含词典硬闸 G8-G11/G1/G5) | match 执行与闸门判读 |
119
+ | 第 1 步附加 | [`step1b-audit.md`](steps/step1b-audit.md) | 第 1 步附加 · 挂载点审计(audit · 静态查三类隐性缺口) | match 通过后、施工前 |
120
+ | 第 1 步附加(之二) | [`step1c-registry.md`](steps/step1c-registry.md) | 登记表覆盖率(子项级细闸) | 变更集带 coverage.registry / --registry 时 |
121
+ | 第 2 步 | [`step2-structure.md`](steps/step2-structure.md) | 第 2 步 · 结构先行(visible / position / form · structure_ops · layer · suppress · priority 消费) | 进入施工时(先于一切样式) |
122
+ | 第 3 步 | [`step3-style.md`](steps/step3-style.md) | 第 3 步 · 样式落地(两层转换 + 语义值译表) | 结构完成后 |
123
+ | 第 3 步附加 | [`step3b-shell.md`](steps/step3b-shell.md) | 第 3 步附加 · 设计层落点文件 design-shell.scss(强制 · 覆写定律 · 自举) | 写任何新 CSS 规则前 |
124
+ | 第 3 步附加(之二) | [`step3c-priority.md`](steps/step3c-priority.md) | 覆写优先级消费(硬步骤) | 与 step3b 配套,落规则前逐条判定 |
125
+ | 第 4 步 | [`step4-l3.md`](steps/step4-l3.md) | 第 4 步 · L3 新模块处理(分级布局) | 存在未命中点位 / 新页面生成时 |
126
+ | 第 5 步 | [`step5-gates.md`](steps/step5-gates.md) | 第 5 步 · 合规闸门(变更集专属检查清单) | 施工完成后、验收前 |
127
+ | 第 6 步 | [`step6-verify.md`](steps/step6-verify.md) | 第 6 步 · 渲染态验收(oracle 逐点 diff · 快照回归 · 残差豁免) | 变更集含 oracle 时强制 |
128
+ | 维护 | [`maintenance.md`](steps/maintenance.md) | 词典维护纪律 · 出厂状态漂移排查 | 改 mapping / 排查词典假前提时 |
129
+ | 回归 | [`regression.md`](steps/regression.md) | 端到端回归 A-V · 配套工具 | 改 parser/mapping 后必跑 |
130
+
131
+ **红线摘要(全文适用,细节在各步子文件)**:出厂中性 · 变更集驱动(上文);先结构后样式(第 2 步先于第 3 步);缺口只分「能力缺口(当场落地)」与「意图缺口(回流设计侧)」两类;**效果图/大文件只读一次**——期望值落盘 `oracle.json` 后,后续环节一律消费落盘产物,禁止反复重读。环境无 Node 时按「环境备注」(见 maintenance.md)人工执行。
@@ -0,0 +1,16 @@
1
+ # design-apply · 词典维护纪律与出厂状态漂移
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:改 mapping / 出厂状态存疑 / 排查词典假前提时。
4
+
5
+ ---
6
+
7
+ ## 词典维护纪律
8
+
9
+ ### 出厂状态漂移(词典假前提 = 事故源,落地前必查)
10
+
11
+ **项目可能随时被还原到出厂**(design-shell 回空壳、`.changeset/*` 消失、本体系此前补的通道全部消失)。因此词典里凡「出厂已具备 X」类表述必须满足:① X 是**真出厂能力**(对照出厂源码可验证);② 由本体系补建的通道一律写成**条件式**——「若缺失,按 structure_ops / 补通道流程补建并申报」,不写「已存在」。**落地前必须跑 `node parser/index.js audit --project <dir>`**:锚点/选择器/变量消费者存在性静态校验,会当场暴露词典假前提(曾发生:词典写「出厂已渲染分割线 / 工具栏行已挂语义类」,项目还原后全部失真 → 规则落空)。
12
+
13
+ - mapping/ 是唯一事实源:施工前 `parser query <id>` 精读条目,**不凭记忆施工**。
14
+ - **禁止编造的是「既有条目的映射」**(改既有 selector / css_vars / 变量指向 = 静默篡改,绝对禁止)。**词典缺 ID / 缺字段枚举不属编造**——那是新点位,按 L3 当场落地并写**新增的**临时映射条目,交付说明申报,等人工评审转正。
15
+ - 「宁可不做,不做错」只适用于**设计侧未给值 / 值非法**的意图缺口;用它搁置能力缺口 = 交付失败。
16
+ - 临时映射转正须人工评审;禁止静默修改既有映射条目的 selector/css_vars。
@@ -0,0 +1,47 @@
1
+ # design-apply · 端到端回归与配套工具(作者/维护侧)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:改 parser/mapping 后必跑;日常落地不需要加载。
4
+
5
+ ---
6
+
7
+ ## 端到端回归(改 parser/mapping 后必跑)
8
+
9
+ ```bash
10
+ node parser/regression.js # 一键跑完 A-V 二十二步(自动断言退出码与关键输出,任一失败 exit 1 并回显详情)
11
+ npm run regression # 等价写法
12
+ ```
13
+
14
+ 分步展开(等价于 regression.js 内部步骤,排障时可单跑某一步):
15
+
16
+ ```bash
17
+ node parser/validator.js # A. 映射词典全量校验(含 semantic-values.json)
18
+ node parser/index.js list --scene admin --verbose # B. 头部应输出映射集版本;ID/字段/形态清单
19
+ node parser/index.js match parser/fixtures/changeset-pos.json # C. 正例:exit 0;钴蓝-5→#245BFF 译表解析;pending 功能描述输出
20
+ node parser/index.js match parser/fixtures/changeset-neg1.json # D. 负例1:exit 1(缺 schema)
21
+ node parser/index.js match parser/fixtures/changeset-neg2.json # E. 负例2:exit 1(mapping_version 不匹配)
22
+ node parser/index.js match parser/fixtures/changeset-neg3.json # F. 负例3:exit 1(禁词/非法 ID/位置违规,逐条列出)
23
+ node parser/index.js match parser/fixtures/changeset-legacy.json # G. 旧协议:exit 0 + layout 键/schema 历史值两条告警
24
+ node parser/index.js match parser/fixtures/changeset-fullpage-restore.json # H. 整页场景还原样例:exit 0;壳层+内容区全模块 L1 命中;数值字面量(40px 等)透传无 ⚠
25
+ node parser/index.js build --dry # I. 产物链自检
26
+ node parser/index.js match parser/fixtures/changeset-v32-fields.json # J. 声明维:exit 0;输出「结构施工 structure_ops」与 layer / apply_via
27
+ node parser/index.js audit --project parser/fixtures/fake-project parser/fixtures/changeset-v32-fields.json # K. 静态审计:夹具项目存在挂载点缺失/死通道 → exit 1
28
+ node parser/index.js verify --oracle parser/fixtures/verify/oracle.json --actual parser/fixtures/verify/actual.json # L. 渲染态验收:夹具含三类故意缺口 → exit 1;归因计数 选择器落空1/权重被压1/语境错位2
29
+ node parser/index.js match --registry parser/fixtures/registry-sample.json parser/fixtures/changeset-registry-gap.json # M. 登记表覆盖率细闸:夹具欠声明 2 条恒存在子项 → exit 1
30
+ node parser/index.js registry parser/fixtures/registry-sample.json # N. 登记表通道核验:点位全部命中 → exit 0;输出含「登记表通道核验」
31
+ node parser/index.js registry parser/fixtures/registry-bad.json # O. 登记表硬缺口:引用不存在且未标 pending 的点位 → exit 1
32
+ node parser/index.js match parser/fixtures/changeset-neg4-g8.json # P. G8 模式闸负例:mode=restore 缺 oracle/coverage(伪还原变更集)→ exit 1
33
+ node parser/index.js match parser/fixtures/changeset-neg5-g8-stub.json # Q. G8 强化负例:mode=restore 但 mockup/registry 空壳(有壳无芯伪基线)→ exit 1
34
+ node parser/index.js match parser/fixtures/changeset-neg6-g9-identity.json # R. G9 身份闸负例:scheme=tangerine 却引 default 方案登记表(分母偷换)→ exit 1
35
+ node parser/index.js match parser/fixtures/changeset-neg7-g10-dims.json # S. G10 dims 闸负例:header_cell 缺 text_align/nowrap(点位在细节丢)→ exit 1
36
+ node parser/index.js match parser/fixtures/changeset-neg8-g11-oracle.json # T. G11 oracle 闸负例:橘橙主色配钴蓝效果图且无 theme_mapping(主题错配)→ exit 1
37
+ node parser/index.js verify --oracle parser/fixtures/verify/oracle.json --actual parser/fixtures/verify/actual-clean.json # U. 残差豁免 + G12 收口正例:申报点位不计缺口、absent 已收口 → exit 0
38
+ # V. 快照回归(两段式,regression.js 内部自动展开):clean 夹具导快照 → 缺口夹具比对 → 基线漂移 → exit 1
39
+ ```
40
+
41
+ 通过标准:regression.js 输出 `A✔ B✔ … V✔` 且 exit 0;分步跑时各步符合注释预期。夹具含义见各文件 `$comment`。
42
+
43
+ ## 配套工具(作者/维护侧)
44
+
45
+ - **watch 模式**:`node parser/watch.js` 或 `npm run mapping:watch`——监听 mapping/ 下 JSON 变更,自动「校验 + 重编 dist/」;校验失败不杀进程,修正后自动重试。
46
+ - **业务级覆写 API**:`import { themeVars, overrideMapping } from '<skill>/dist/theme-vars.js'`——仅覆写指定字段,不改动基础映射;strict 模式下覆写词典外字段直接报错(防拼错静默失效)。当前 vue3-web-temp 不引入,服务于未来空白项目。
47
+ - **mapping 版本流程**:所有 mapping/*.json 的 `meta.version` 恒为 `1.0.0`(由 SKILL.md 体系版本统一管理);`release.js` 发版前自动执行 `parser build` 刷新 dist/,产物随 NPM 包发布。
@@ -0,0 +1,51 @@
1
+ # design-apply · 第 0 步 · 版本与场景检查 · 对接匹配(适配前置)· 运行时清场
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:每次落地开工前(版本/场景/对接匹配/运行时清场三件套)。
4
+
5
+ ---
6
+
7
+ ### 第 0 步 · 版本与场景检查 · 对接匹配(适配前置)· 运行时清场
8
+
9
+ **0.1 版本与场景检查**
10
+
11
+ - 变更集 `schema` 版本不在支持范围 → 停止,向上游(用户/设计侧)报告版本不匹配,不降级猜测。
12
+ - `scene` 在 `parser list` 场景清单中无对应域 → 报告并列出支持的场景,等待确认。
13
+
14
+ **0.2 对接匹配(适配前置)——把散落的匹配收拢为一个前置阶段**
15
+
16
+ 在施工前,把「设计意图 ⇄ 模板能力」整体对一遍,输出匹配结论,供**生成前**决策(而不是落地时才发现对不上)。三步判定:
17
+
18
+ | 级 | 判定 | 依据 |
19
+ |---|---|---|
20
+ | **布局级** | `layout_type` 命中标准枚举? | 命中 → 切布局模板池(§5.2);未命中 → 变体派生 / 定制生成骨架(§5.3 / §5.4) |
21
+ | **点位级** | 逐 id 三级匹配 | 一级完整命中 / 二级父级命中 / 三级未命中(§4.1) |
22
+ | **形态级** | `form` 在条目 `forms` 枚举内?`structure_ops` 所需 DOM 钩子是否存在? | 词典 `forms` / 模板源码 / `audit` |
23
+
24
+ **输出三类结论,处置全在项目侧**:
25
+
26
+ | 结论 | 判据 | 处置 |
27
+ |---|---|---|
28
+ | 完全匹配 | L1 ∧ form 在枚举 ∧ 无需结构 | 直接施工 |
29
+ | 可派生 | L2 / 变体布局 / form 可映射 | 派生骨架或继承父级后施工 |
30
+ | 需适配 | L3 / 定制布局 / 缺通道 / 需新 DOM | **先补通道 / 结构增量 / 生成骨架,再生成**;交付说明单列申报 |
31
+
32
+ > **总原则(红线):设计为主,项目侧适配。** 设计效果是目标态,模板是待适配的一方。"设计 ↔ 模板对不上"的出口**永远在项目侧**——**不回流设计侧改设计**。只有「设计侧未给值 / 值非法」(**意图缺口**)才回流设计侧。严禁以「模板不支持」为由要求设计改图。
33
+
34
+ **0.3 运行时主题清场(T 通道先于 D/S/C)**
35
+
36
+ 主色 / 主题走的是**运行时通道**:`setEpThemeColor()` 把 `--el-color-primary` 写成 `documentElement` 的**内联样式**并持久化到 localStorage(读取优先级 = 浏览器持久化 ?? `platform-config.json`)。**内联样式 + 运行时持久化 ⇒ 设计层 CSS 与词典 selector 都赢不了。**
37
+
38
+ - 落地前先读 localStorage(键 `responsive-layout`)的 `theme` / `epThemeColor`,与本变更集主题**不一致时清 key 或显式重设**;
39
+ - 清场动作与结果写入交付说明(可回溯);
40
+ - **不清场则颜色类差异全部失真**——归因前必须先确认起点已对齐,否则会把「环境残留」误判成「落地失败」。
41
+ - **机检对账(G4)**:`parser audit` 会自动比对 `global.brand_primary` ↔ `platform-config.EpThemeColor`、页签 form ↔ `ShowModel`、`visible:false` ↔ 显隐开关,不一致即 `exit 1`——人工清场 + 机检对账双保险。
42
+
43
+ **0.3b T 通道持久化三件套(页签形态 / 主题类字段施工必做)**
44
+
45
+ 运行时配置读 localStorage,而 localStorage 只在 `platform-config.Version` 变化时经 `responsive.ts invalidateStorageIfConfigVersionChanged` 重灌。凡施工涉及 `ShowModel` / `Theme` / `EpThemeColor` 等 T 通道字段,**三件套缺一不可**:
46
+
47
+ 1. 改 `platform-config.json` 实值(如 `ShowModel: "card"`);
48
+ 2. **`Version` 自增一位**(如 0.0.6 → 0.0.7)——漏此步 = 代码对但运行时仍旧形态(历史事故:只改 ShowModel 未动 Version,页签零变化);
49
+ 3. **渲染取证**:断言新形态类实际挂载(如 `.scroll-item.card-item` 出现在 DOM)——不许只看代码改没改。
50
+
51
+ 词典 `admin.layout.tabs.preconditions` 有同款硬闸描述;本三件套对任意 T 通道字段通用。
@@ -0,0 +1,58 @@
1
+ # design-apply · 第 1 步 · parser 确定性匹配(含词典硬闸 G8-G11/G1/G5)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:match 执行与闸门判读。
4
+
5
+ ---
6
+
7
+ ### 第 1 步 · parser 确定性匹配
8
+
9
+ ```bash
10
+ # 单份变更集
11
+ node parser/index.js match <changeset.json>
12
+ # 项目级批量(设计侧项目级模式产出:全局变更集 + 各页面变更集目录)
13
+ node parser/index.js match --batch <changesets-dir>
14
+ ```
15
+
16
+ 读取输出的**转换计划**,它包含:
17
+
18
+ | 分级 | 含义 | 处理 |
19
+ |------|------|------|
20
+ | **L1 完整命中** | ID 在词典中直接命中 | 按条目施工坐标直接落地(预期 100% 还原) |
21
+ | **L2 父级命中** | ID 的父模块命中 | 继承父模块样式约定,按子级定位施工(85-90% 还原) |
22
+ | **L3 未命中** | 词典无此 ID(新增点位) | **当场按第 4 步定制布局落地**并写入 mapping 临时映射;只有设计侧未给完整意图(无值 / 值非法)才进缺口清单 |
23
+ | **字段级未命中** | ID 命中但 `style` 某字段两层映射都查不到 | 值合法且选择器可定位 → **当场生成作用域内自定义规则落设计层文件并申报**;只有「值非法 / 无法定位」才进缺口清单 |
24
+
25
+ **零缺口交付(禁止中途停顿)**:落地一次跑完,**不得因「词典没建这个 ID / 这个字段没枚举 / 这个值要不要确认」而停下来问用户**。缺口只有两类,去向各不相同:
26
+
27
+ | 缺口类型 | 判据 | 处理 |
28
+ |---|---|---|
29
+ | **能力缺口**(词典缺 ID / 缺字段枚举 / 缺 form) | 设计侧意图完整、值合法 | **项目侧当场落地**:按 L3 定制布局施工并写 mapping 临时映射;出厂文件仅在「补通道」时可动,交付说明单列申报。**进清单 = 把可落地项搁置 = 交付失败** |
30
+ | **意图缺口**(设计侧没给值 / 值非法) | 变更集里本就没有这个值 | 才可进「缺口清单」,交付说明写明「回流设计侧补齐」——**不是问用户要不要做** |
31
+
32
+ `缺口清单` 只承载第二类,且必须给出点位 ID + 缺失字段名。
33
+
34
+ **转换计划新增四类输出()**:每条 L1/L2 点位除样式指令外,还会输出——
35
+
36
+ | 输出 | 含义 | 施工含义 |
37
+ |---|---|---|
38
+ | `▸ 承载通道 anchors` | 该点位可落地的宿主盒 / 内层文本盒 / CSS 变量锚点 | 落点以这里为准,不要自己猜选择器 |
39
+ | `▸ 承载通道来源 apply_via` | 本声明引用的锚点来源条目 | 落到该条目的锚点上(而非 change.id 自身的) |
40
+ | `▸ 结构施工 structure_ops` | 需要改数据 / 模板结构的事项 | **必须改动数据或模板分支**,禁止只写 CSS |
41
+ | `▸ 前置条件 preconditions` | 值成立依赖的宿主前提 | 施工前必须满足,否则「值对了也不生效」 |
42
+ | `▸ 覆写优先级 priority` | 该点位的提权策略 | 按策略取胜,禁止逐点硬堆 `!important` |
43
+
44
+ **词典硬闸(match 期机检,违规 = 拒绝执行)**:
45
+
46
+ | 闸 | 触发条件 | 判据来源 | 违规输出 |
47
+ |---|---|---|---|
48
+ | **G8 模式闸** | 变更集顶层 `mode: "restore"`(场景还原)但基线不全:缺 `scheme` / `oracle` / `coverage`,**或 `oracle.mockup` / `coverage.registry` 为空**(有壳无芯的伪基线)——伪还原变更集(只换主题色却以还原之名交付)拒绝执行;`mode` 非法值同样阻断 | 变更集顶层 `scheme` / `mode` / `oracle.mockup` / `coverage.registry` | `G8 模式闸:mode=restore 但缺少 … → 拒绝执行` |
49
+ | **G9 登记表身份闸** | `mode=restore` 但登记表**身份对不上**:`coverage.registry` 实物解析失败,或登记表 `design_scheme`/`scene` 与变更集 `scheme`/`scene` 不一致(或缺身份字段)——凡身份对不上的表视同没有表,防止覆盖率分母被偷换(面包屑/顶栏图标/表头 nowrap 等点位从分母消失,欠声明不可数) | 登记表顶层 `design_scheme` / `scene` ↔ 变更集顶层 `scheme` / `scene` | `G9 登记表身份闸:登记表 … 属于 scheme="…"/scene="…",与变更集 … 不一致 → 拒绝执行` |
50
+ | **G10 dims 兑现闸** | `mode=restore` 下登记项的 ID 已在 `changes[]` 声明,但登记 `dims` 维度未全部给全(`form` 看 `change.form`,其余看 `style ∪ layer` 的键;`source:none`、global 伪点位、`visible:false` 豁免)——「点位在、细节丢」(表头竖排 = nowrap 丢失)正是样式细节不还原的机制成因,dims 缺口与欠声明同级阻断 | 登记表条目 `dims` ↔ 变更集条目 `form` / `style` / `layer` | `dims 兑现缺口(G10 · … 条 → exit 1):… 缺 dims=[…]` |
51
+ | **G11 oracle 基线闸** | `mode=restore` 下 oracle 校验发现问题(主题错配 / `oracle.sids` 欠声明或无基线 / 实物缺口):restore 下从「⚠ 软提示继续」升格为「拒绝执行」——基线断了仍绿灯交付,verify 无从做 1:1 证明。同构异色复用须在 oracle 显式声明 `theme_mapping: { from, to }` | oracle 主题词 ↔ `global.brand_primary` 主题词;`oracle.sids` ↔ `changes[].id` 双向 | `oracle 基线问题(G11 · … 类 → 拒绝执行):主题错配 …` |
52
+ | **G1 suppress 收口** | 条目声明某 `form`,词典 `suppress_rules[form]`(或 forms 描述「suppress 必含 x」内联标记)要求收口的出厂互斥通道未全部出现在该条目 `suppress[]` | 词典条目 `suppress_rules` | `suppress 缺口:…必须收口出厂互斥通道 [x],缺 [x]` |
53
+ | **G5 几何语境** | 词典 preconditions 含「几何语境随值迁移」标记 ∧ `style` 含 padding/margin 族几何字段落宿主 ∧ 未声明 `suppress_inner` | 词典条目 preconditions 标记句 | `suppress_inner 缺口:…两层之和 ≠ 设计值` |
54
+
55
+ 三闸与禁词校验同级阻断(`exit 1`)——「新旧形态叠加」「两层 padding 相加」「伪还原只换主题」都是历史事故源(双竖条、28px 列挤压、「还原后布局细节零变化」),不允许靠观感兜底。G8 判据一句话:**「把系统 / 页面改成 X」默认是还原(restore),必须带齐 `scheme` + `oracle.mockup` + `coverage.registry`;只有「显式声明只改主题色、其它不动」才用 `design`**(2026-09-20 事故机制化:还原项目后重跑,无登记表无基线的轻量变更集一路绿灯,落地后「只变了主题、布局细节零变化」;二轮强化再堵住 `oracle`/`coverage` 只给空壳、无 `mockup`/`registry` 芯的写法)。**降级不许静默发生**:变更集 `notes` 与交付说明都须显式写出本次 `mode` 与范围。restore 模式下 G9/G10/G11 同时生效(登记表身份、dims 维度兑现、oracle 基线三道复闸),三者判据细节见上表与「登记表覆盖率」小节。
56
+
57
+ **验收基线输出**:转换计划末尾另打印 `=== 验收基线 oracle ===`(效果图路径 + 待比对点位)与 `=== 覆盖率 coverage ===`(登记项 R / 适用 A / 已兑现 C)。有 `oracle` → 落地后必须跑第 6 步 `verify`;缺 `oracle` / `coverage` → 输出提示,把「补基线 / 补登记覆盖率」回流设计侧(场景还原应给)。
58
+ **覆盖率校验**:`coverage.covered` 必须等于 `coverage.applicable`、`gaps` 为空,否则打印缺口清单——`C < A` 即**欠声明**(有规范子项未落进 `changes[]`/`visible`/`pending`),属设计侧交付不完整,必须回流,不得在项目侧"猜着补"。
@@ -0,0 +1,23 @@
1
+ # design-apply · 第 1 步附加 · 挂载点审计(audit · 静态查三类隐性缺口)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:match 通过后、施工前。
4
+
5
+ ---
6
+
7
+ ### 第 1 步附加 · 挂载点审计(,静态查三类隐性缺口)
8
+
9
+ ```bash
10
+ node parser/index.js audit --project <目标项目根目录> [<changeset.json…>]
11
+ ```
12
+
13
+ 不开浏览器即可查出的三类历史高发缺口:
14
+
15
+ | 检查 | 抓什么 | 对应历史缺口 |
16
+ |---|---|---|
17
+ | **挂载点缺失 / 可疑** | `selector` / `anchors.target` 里的类名在项目里**只在样式文件出现、模板没挂**,或**完全找不到** | 列未绑 `class-name` → 金额列右对齐 / 缩略图尺寸永不生效;操作栏规则有定义无引用 |
18
+ | **死通道** | `anchors` 里的 CSS 变量在项目中**无 `var()` 消费者**(两类豁免:`--el-*` 组件库变量由 EP 运行时消费;设计层已显式接管定义的变量属故意 suppress) | 变量有定义无引用,翻译再准也不生效 |
19
+ | **词典无此条目** | 变更集引用了词典未建的 ID | L3 新增点位须当场落地并回写临时映射 |
20
+ | **G2 structure_ops 施工证据** | 变更集声明 `structure_ops` 的点位,按词典 anchors/selector 语义类名 + `op.node` 提取探针,在**非设计层结构源码**中查证施工痕迹;零命中 = 纯 CSS 冒充结构施工 | 操作列分割线 `add_node` 声明多轮从未施工 |
21
+ | **G4 T 通道对账** | `global.brand_primary`(语义值解析 hex)↔ `platform-config.EpThemeColor`;页签 `form` ↔ `ShowModel`;`visible:false` 点位的 `visible_prop` 开关 ↔ platform-config 实值 | 变更集孔雀绿、platform-config 残留旧主题;flat 页签叠加 chrome 结构 |
22
+
23
+ 挂载点疑似但**设计层文件已承载该类名** → 降级不阻断(C 通道由 design-shell 兜底是合法落点)。G2 / G4 违规与挂载点问题同置 `exitCode 1`。审计报错 = **能力缺口**:当场按 `structure_ops` 补挂载 / 补消费者,交付说明单列申报;不得以「词典没建」为由跳过。审计通过 ≠ 还原达标——**静态审计查不出「值对了、位置不对」**,那要靠第 6 步渲染态验收。
@@ -0,0 +1,29 @@
1
+ # design-apply · 第 1 步附加(之二)· 登记表覆盖率(子项级细闸)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:变更集带 coverage.registry / --registry 时。
4
+
5
+ ---
6
+
7
+ ### 第 1 步附加(之二)· 登记表覆盖率(子项级细闸 · )
8
+
9
+ 组级台账(`restore-checklist`)只能防「整组忘光」;**组内子项**是否被静默丢失,用登记表计数。
10
+
11
+ ```bash
12
+ node parser/index.js match <cs.json> --registry <restore-registry.json> # 匹配 + 覆盖率当场重算
13
+ node parser/index.js registry <restore-registry.json> [--verbose] # 只核验登记表对词典的通道就绪度
14
+ ```
15
+
16
+ | 量 | 定义 | 谁重算 |
17
+ |---|---|---|
18
+ | **R 登记项** | 登记表条数(= 规范里带样式结论的子项数) | 读表 |
19
+ | **A 适用** | `always:true` 的子项 ∪ 效果图已标注同名 `data-sid` 的子项 | parser 当场算 |
20
+ | **C 兑现** | A 中在 `changes[]` / `visible:false` / `pending[].proposed_id` 出现者 | parser 当场算 |
21
+ | **缺口** | `A − C`,逐条列出 `rule + sid + dims`(同组超过 6 条需加 `--verbose` 展开) | parser 当场算 |
22
+
23
+ **关键口径**:A/C **由 parser 以登记表为权威当场重算,设计侧自报的 `coverage` 数字不参与**——所以「把 applicable 写小」蒙混不过去。有缺口 → `exit 1`,属**交付不完整**,回流设计侧补齐后重跑。
24
+
25
+ 另有一项**效果图标注缺口**告警:`always:true` 的子项若在效果图里找不到同名 `data-sid`,基线根本抽不出来(效果图标注粒度必须与登记表同分辨率,否则第 6 步的 oracle 必然残缺)。
26
+
27
+ `registry` 子命令单独回答「这张登记表里有多少必登项在项目侧真有承载字段」:
28
+ - **硬缺口**(引用了词典不存在的点位且未标 `pending`)→ `exit 1`;
29
+ - **通道缺口**(设计侧维度在词典无对应字段)→ 列出,属**项目侧补词典**事项,补齐后还原度才可达 100%。
@@ -0,0 +1,68 @@
1
+ # design-apply · 第 2 步 · 结构先行(visible / position / form · structure_ops · layer · suppress · priority 消费)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:进入施工时(先于一切样式)。
4
+
5
+ ---
6
+
7
+ ### 第 2 步 · 结构先行(visible / position / form)
8
+
9
+ **先改结构,后改样式**——结构变了选择器才稳定,样式才有处可落。
10
+
11
+ - `visible: false` → 按条目 `visible_prop`(如 `platform-config.json` 的 `HideTabs`)或组件 `v-if` 隐藏;无现成通道时 `display: none`,作用域限定在条目 `style_scope` 内。**不删除任何代码行。**
12
+ - `position` → 优先用 flex 顺序(`order` / DOM 位置调整),禁止绝对定位像素坐标。
13
+ - `form` → 按条目 `forms` 枚举切换(如 tabs 的 `chrome`/`card` 走 `platform-config.json ShowModel`;内容区滚动模式走 `admin.content.container` 的 form(`fixed`/`scroll`/`auto` → 路由组件根节点 `data-content-mode` 属性,`auto` 为省略即钩子类探测)。枚举外的形态 → 报告,不猜。
14
+ - **结构维度缺失即申报,禁止「只改令牌冒充落地」**:变更集把结构/方位/有无类意图写进 `style`(如指示条只在 `style.menu_active_indicator` 出现、无对应 `form`)时,按「结构意图缺失」处理——交付说明申报「设计侧需补 form + 几何 + 色值」,不得只覆盖颜色令牌交差(历史事故:竖条只换令牌 → 图上有、页面上没有)。
15
+ - `form` 的落点按上文「落地三落点判据」执行:**有 DOM/配置通道走通道,无通道需新节点走结构增量,纯视觉形态走设计层样式文件**。当某形态在本项目只有样式表达(如菜单指示条方位)时,该 form 允许落到样式层——这与「禁止把内容区高度模式降级成 SCSS」不冲突,判据是**该形态有没有非样式通道**。
16
+ - `layout_type` → 改 `platform-config.json Layout` 字段,值域 `vertical/horizontal/mix`。**大屏全屏沉浸式等独立页不走此通道**(设计侧不填 `layout_type`,点位走 L3 落地)。
17
+
18
+ **存在性收口(通用机制,第 2 步随结构处理)**:变更集未声明的**出厂多余元素**(设计效果图上不存在的按钮/图标/入口,如顶栏设置按钮)→ 按各条目口径处理:有条目者在对应点位上以 `visible:false` 收口(代码保留,`v-if`/`display:none`);无条目者列入缺口清单申报「设计侧未声明,按无此元素收口」,同样以隐藏通道落地。禁止既不声明也不收口、让出厂元素顶替设计效果(顶栏设置按钮漏收口已实证:效果图无此按钮,落地后仍显示)。反向同理:**设计声明了而出厂没有的元素**(如欢迎区问候语)必须按条目 `$note`/设计规范补齐结构(结构通道豁免底线二),缺失 = 未交付。
19
+
20
+ **结构/样式图层分工**:`form`(高度模式、形态枚举)是**结构意图**,必须落到 DOM 属性/组件开关/配置字段(如 `data-content-mode`、`ShowModel`);**禁止把结构意图降级翻译成 SCSS 变量写进样式文件**(form=scroll 只写 `--vts-margin` = 未施工,已实证)。样式文件(如 design-shell.scss)只承载 css_vars/custom_style_map 翻译产物;壳层通用文件禁止代打页面级结构属性(lay-content 硬编码 `data-content-mode="scroll"` 曾压掉 `:has()` 自动定高探测,useTableSearch 高度链断裂致列表区整体崩坏——已回退,禁止复活)。
21
+
22
+ **结构链不可侵(高度链保命红线)**:内容区高度链是**结构层**,已与视觉解耦,两侧各有边界——
23
+
24
+ | 结构层(禁止改写) | 视觉层(设计自由落点) |
25
+ |---|---|
26
+ | `data-content-mode`(滚动归属,**页面根节点属性**) | 页面容器形态(卡 / 通栏 / 自绘)、底色、圆角、边框、内边距、阴影 |
27
+ | `data-fill`(填满剩余高度,**逐层节点属性**) | 容器内部排布(标题区 / 筛选区 / 表格区的位置与间距) |
28
+
29
+ - 设计要求换掉出厂卡片容器(去卡片、改通栏、改内部排布)→ **照做,不打折**:页面根声明 `data-content-mode`,把 `data-fill` **平移**到新容器及其「体」层,视觉全落设计层文件。此路径下 `tableHeight` 几何实测照常成立。
30
+ - **双向禁止**:① 以「保高度」为由拒绝改容器/内边距/去卡片(= 放弃设计还原);② 为凑还原效果改写壳层结构层规则、或在视觉层重写/压掉 `[data-fill]` / `.main-content[data-content-mode]`(= 高度链断裂,返工项)。
31
+
32
+ #### 第 2 步附加 · 结构施工(structure_ops)与优先级策略()
33
+
34
+ **A. 结构施工 `structure_ops`(数据 / 结构驱动点位)**——有些点位**换不掉也写不出来**,因为呈现由数据源或模板结构决定。变更集给出 `structure_ops` 时必须照做,**只写 CSS = 无效声明**:
35
+
36
+ | `op` | 含义 | 施工动作 |
37
+ |---|---|---|
38
+ | `add_node` | 新增语义节点 | 在模板按 `form` 保形插入(不删原代码),落点见「落地三落点判据」第 2 条 |
39
+ | `remove_node` | 移除语义节点 | 按 `visible:false` 收口(隐藏不删);确需物理移除时先确认无业务耦合 |
40
+ | `move_node` | 调整节点位置 | 优先 flex `order` / DOM 位置调整,禁止绝对定位像素坐标 |
41
+ | `render_branch` | 补渲染分支 | 例:状态列 `formatter` 返回纯文本 → 改为 `el-tag` 分支(`source` 指出数据来源) |
42
+ | `bind_source` | 绑定数据源 | 例:金额列补 `class-name` / `align`、缩略图列补 `class-name` —— 属数据侧结论,**改 CSS 不算** |
43
+
44
+ **判据一句话**:**这个点位的呈现,改 CSS 能改吗?** 改不了(图标在数据里、Tag 在模板分支里、类名没绑)→ 必须走 `structure_ops`;能改(颜色 / 圆角 / 间距)→ 走第 3 步样式落地。
45
+
46
+ **B. 落点层级 `layer`(专治「值对了、位置不对」)**——同一点位的样式可能落在**宿主盒**或**内层文本盒**,两者不通用:
47
+
48
+ - 变更集给了 `layer` → 严格按 `layer` 从条目 `anchors` 取对应选择器(parser 已在转换计划里给出 `@ … · host/inner 层`)。
49
+ - 变更集**没给** `layer`、但条目 `preconditions` 指出必须落内层(如 EP 表头 `white-space`)→ 按 `preconditions` 落 inner 层,并在交付说明注明「设计侧未给 layer,按条目前置条件处理」。
50
+ - **内层盒属性族强制校验**:`white-space` / `text-overflow` / `overflow` / `word-break` / `text-align` / `line-height` / `vertical-align` 这组属性**只在内层文本盒生效**——逐字段核对 `layer`;未指认且条目前置条件也没说 → **退回设计侧补声明**,禁止默认落 host(历史缺口:表头「禁止换行」落 host 被内层默认 `normal` 吃掉 → 表头竖排、行高撑大、列内容被压)。
51
+ - 常规分工:高度 / 背景 / padding 落 host;文本换行、省略、对齐落 inner。
52
+ - **几何语境必须随值迁移(双重内边距,历史缺口:表头标题截断成 类…/包…/操…)**:出厂内层文本盒自带 padding 时(EP `.el-table .cell` 出厂 `padding: 0 12px`),把设计的 16px 落到 host 后**必须同步清零内层自带 padding**——否则实际内边距 = 16+12 = 28px/侧,列宽被挤、表头标题被省略号截断、视觉不适配常规。判据:**效果图的距离语义是「列缘到文字」的总距离;宿主/内层两层结构下必须拆成两段落地,两段之和等于设计值**。凡向 host 落 padding/border 类几何值,先查出厂内层盒的自带同族值再决定是否归零。
53
+
54
+ **B2. 出厂形态互斥收口 `suppress`(治「新形态上了、旧形态残留」)**——条目带 `suppress` 时,逐通道执行收口,**收口优先走令牌重映射**(在令牌宿主作用域重声明令牌,零权重战争),令牌不存在才写属性:
55
+
56
+ - 每条通道收口后必须在交付说明列出「通道名 → 收口方式 → 落点」,漏一条 = 出厂旧装饰残留。
57
+ - 实例:侧栏 `form=pill` → `suppress: ["右指示条通道"]` → 在侧栏作用域把出厂右竖条令牌重映射为 `none`(出厂 `.el-menu-item.is-active { border-right: var(--…) }` 与 `design-tokens` 的 `3px solid` 令牌都无需改动)。
58
+ - 页签 `form=flat` 属**多通道收口**:透明化激活底色块 + 去圆角间距 + 关闭钮常显 + 贯穿分割线 + 首页页签仅图标——必须逐通道列出并收口,漏任何一条 = 「整个样式和设计不一样」。
59
+
60
+ **C. 覆写优先级 `priority`(禁止逐点硬堆 `!important`)**——条目 `priority.strategy` 给出本点位该怎么赢:
61
+
62
+ | 策略 | 施工口径 |
63
+ |---|---|
64
+ | `scope_qualified` | 用条目 `style_scope` 作用域限定即可覆盖 |
65
+ | `self_plus_important` | 目标处于**行内 style**(`:header-cell-style` 等)竞争下 → 先移除页面行内样式;无法移除时,作用域内提权并在交付说明申报 |
66
+ | `deep_qualified` | 目标与**组件 scoped 规则同权重** → 提高选择器权重或走深度选择器显式取胜(**不能只靠「后置加载」**) |
67
+
68
+ > **为什么必须显式处理**:同权重时胜负由样式注入顺序决定、不可控;靠「加 `!important` / 加宽选择器」逐点硬压,会把互不相干的点位耦合起来、副作用无人发现 → **累积成漂移而不是收敛**(这正是「越改越乱」的机理)。
@@ -0,0 +1,27 @@
1
+ # design-apply · 第 3 步 · 样式落地(两层转换 + 语义值译表)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:结构完成后。
4
+
5
+ ---
6
+
7
+ ### 第 3 步 · 样式落地(两层转换 + 语义值译表)
8
+
9
+ 对每个 `style` 字段,按 parser 转换指令执行(parser 已把语义值解析为精确值,如 `钴蓝-5` → `#245BFF`)。**冲突裁决规则(免问):凡变更集声明与项目出厂现状/模板既有口径冲突,一律按变更集执行——变更集是唯一施工依据,不反问、不逐次确认。**
10
+
11
+ 1. **css_vars 层(优先)**:在条目 `style_scope` 作用域内覆盖该 CSS 变量。
12
+ ```scss
13
+ // 例:admin.layout.sidebar.menu 的 menu_bg = 钴蓝-9(#0D2A7F)
14
+ .sidebar-container {
15
+ --vts-theme-menu-bg: #0D2A7F;
16
+ }
17
+ ```
18
+ 2. **custom_style_map 层(兜底)**:无官方变量可用时,生成 `:deep()` 隔离样式。
19
+ ```scss
20
+ // 例:admin.layout.header.user_profile 的 avatar_width
21
+ .navbar :deep(.el-dropdown-link img) { width: 36px; height: 36px; }
22
+ ```
23
+ `sub_selectors` 有定义的字段(如 `avatar_*` → img、`name_*` → p)按对应选择器路由。
24
+ 3. **两层都未命中** → 值合法且选择器可定位时,当场生成作用域内自定义规则落设计层文件并在交付说明申报;仅「值非法 / 无法定位」才进缺口清单。
25
+ 4. **值未命中译表且非 hex**(parser 会提示)→ 能按数值字面量 / hex / 上下文判定的当场落地并申报;仅完全无法判定时进缺口清单、回流设计侧补齐(**不向用户反问**)。
26
+
27
+ 全局令牌(`global` 字段,**整套主题切换优先通道**)→ `design-tokens.scss` 对应变量(`basic/` 词典翻译,语义值走 `mapping/basic/semantic-values.json` 译表),主色走 `setEpThemeColor()` 链路。**壳层模块底色注意**:顶栏底色不走 global(无独立令牌),须以 `{"id": "admin.layout.header", "style": {"bg": "<值>"}}` 场景条目声明(scoped 覆盖 .navbar 底色);侧栏底色两者皆可——global 走 `sidebar_bg`(--sidebar-bg 令牌链),场景条目走 `admin.layout.sidebar` 的 `bg`(--vts-theme-menu-bg)。
@@ -0,0 +1,56 @@
1
+ # design-apply · 第 3 步附加 · 设计层落点文件 design-shell.scss(强制 · 覆写定律 · 自举)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:写任何新 CSS 规则前。
4
+
5
+ ---
6
+
7
+ ### 第 3 步附加 · 设计层落点文件(强制)
8
+
9
+ 所有「新增的 CSS 规则」一律写入 **`src/styles/design-shell.scss`**(出厂空文件,经 `index.scss` 末位 `@use` 加载),或写入页面级 `<style scoped>`;**不得**写进 `sidebar.scss` / `element-plus.scss` / `theme.scss` / `lay-*.vue` 等出厂文件去表达某张效果图的结论。
10
+
11
+ ⚠ **「末位加载」只决定「同源、同特异度」时的先后,压不过两类对手**——这是「规则明明写了却不生效」的头号成因:
12
+
13
+ | 对手 | 为什么本文件会输 | 取胜方式 |
14
+ |---|---|---|
15
+ | **组件 `<style scoped>`** | Vite 下组件样式在全局样式**之后**动态注入;scoped 选择器末元素带 `[data-v-x]`(按一个类计权)。同特异度时后注入者胜 → 本文件出局 | 提权(≥3 层作用域限定 / 叠加属性伪类)——**不是靠文件顺序** |
16
+ | **出厂规则里的 `!important`** | `!important` 高于任何特异度,提权无效 | 本点位也必须 `!important`,或改走通道变量 |
17
+
18
+ 每写一条新规则前,先按第 1 步输出的 `▸ 覆写优先级 priority` 判定对手类型与取胜方式(见下节)。
19
+
20
+ #### 特异度必须**逐位比较**(`html` / `body` 抬不动「类位」)
21
+
22
+ 特异度写成三元组 `(a, b, c)`:`a` = id,`b` = **类 / 属性选择器 / 伪类**,`c` = 类型选择器 / 伪元素。比较顺序是**先比 `a` → 再比 `b` → 最后比 `c`**,`b` 位为 0 时 `c` 再大也没用。
23
+
24
+ - `html` / `body` 是**类型选择器**,只加 `c` 位。对手 `b` 位更高时,加 `html body` **完全无效**。
25
+ - 对手是组件 scoped(末元素 `[data-v-x]` 只加一个类,`b` 通常 ≤2)时,「抬一级作用域」有效;对手是 `body[layout='vertical'] .sidebar-container .el-menu-item`(属性 + 2 类 = `b=3`)时,`html body .sidebar-container .el-menu-item`(`b=2`)无论再加多少 `html`/`body` 都赢不了。
26
+ - 正确的抬法是**加类**:在祖先链上补稳定的语义类(如 `.el-menu`)把 `b` 抬到与对手相等,再靠 `c`(`html body`)胜出。
27
+
28
+ > **实例(已发生的回归)**:`sidebar.scss` 的 `body[layout='vertical'] .sidebar-container .el-menu-item { color: var(--vts-theme-menu-text) !important }`(`b=3`)压掉了设计层的 `html body .sidebar-container .el-menu-item { color: rgb(255 255 255 / 65%) !important }`(`b=2`)→ 菜单文字改用出厂令牌的**浅色主题值(黑)**落在设计强制的深色侧栏上 → **整栏菜单字全部消失**。规则没写错,是权重没算对。
29
+
30
+ #### 改通道(令牌)优先于抢属性
31
+
32
+ 出厂用**语义令牌间接**设置属性时(`color: var(--vts-theme-menu-text)`、`background: var(--vts-theme-menu-bg)`…),**不要写同名属性去抢**,而是**在令牌宿主作用域重映射令牌**:
33
+
34
+ ```scss
35
+ html body .sidebar-container { /* 令牌宿主 = 该令牌被消费的元素所在作用域 */
36
+ --vts-theme-menu-text: rgb(255 255 255 / 65%);
37
+ }
38
+ ```
39
+
40
+ 判据:**令牌在哪个元素上被声明,就在那个作用域重映射**。自定义属性按继承解析,出厂规则自己会消费新值 ⇒ **零权重战争**,也不受对手 `!important` 影响。适用范围:`--vts-theme-*` 全族。
41
+
42
+ 只有在「出厂没有该令牌」或「令牌语义与设计不符(如胶囊几何 `inset`/`radius`)」时才回到抢属性,并按上一条逐位比较。
43
+
44
+ **统一顺序:① 先找令牌通道 → ② 无通道才抢属性(逐位比特异度)→ ③ 都不行才 `!important` + 注释对手。**
45
+
46
+ > 上例的正解就是①:在设计层把 `--vts-theme-menu-text/bg/hover/active-bg` 在 `.sidebar-container` 上重映射,出厂规则自己就画出白色的字与蓝色胶囊。
47
+
48
+ 写入纪律:
49
+
50
+ - **本文件是产物,不是手改对象(流程红线)**:`design-shell.scss` 的每一行都必须由「变更集 + 词典」经本协议产出——发现缺规则时,正确动作是**补词典字段 / 前置条件 / 登记项**让下一次 design-apply 自动生成,**禁止绕过流程直接手写项目文件**。历史规则已落词典的(侧栏令牌 / suppress / 表头内层 nowrap / 双重内边距归零 / 分割线通道),重生成后会自动带出;仅「补通道」(变量消费者 / form 枚举 / 组件中性默认)允许动出厂源码并单列申报。
51
+
52
+ - 每条规则带来源标注(`/* <语义 ID> · <变更条目> */`),换设计时整段可替换;
53
+ - 本文件内新增的 CSS 变量必须**定义 + 引用成对出现**(出厂已有消费者也算),避免死通道;
54
+ - 出厂元素需关闭时(存在性收口)也在这里做:令牌置 `transparent` 或 `display:none`,**绝不删出厂代码行**;
55
+ - 出厂 `--vts-theme-menu-active-before` 默认 `transparent` 且无消费者 → 声明 `form=indicator_*` 时必须在此文件内**同时**落地「关胶囊令牌 `menu_active_bg: transparent`」与「新建 `::after` 消费者」,缺一即未施工成功。
56
+ - **自举(项目被还原到出厂时必做,幂等)**:文件不存在 → 新建(仅保留文件头纪律注释,无任何设计结论)+ 在 `src/styles/index.scss` **末位**补 `@use 'design-shell';`(必须末位,靠后置压出厂)。此动作属「补通道」,交付说明单列申报。**文件缺失时径直把设计规则写进 `element-plus.scss` / `sidebar.scss` / `theme.scss` = 污染出厂文件,禁止**(这也是「设计还原度为零」的常见成因:规则无处可落)。
@@ -0,0 +1,26 @@
1
+ # design-apply · 第 3 步附加(之二)· 覆写优先级消费(硬步骤)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:与 step3b 配套,落规则前逐条判定。
4
+
5
+ ---
6
+
7
+ ### 第 3 步附加(之二)· 覆写优先级消费( 硬步骤)
8
+
9
+ 第 1 步输出的 `▸ 覆写优先级 priority` **不是提示,是落地写法的硬要求**。每落一条规则前先按策略决定写法;写法错了,规则就是「写了不生效」。历史缺口「面包屑 `visible:false` 写了 `display:none` 却照旧显示」「页签关闭钮 `opacity` 写了却仍要 hover 才显」全部源于此——两条规则本身都没写错,是**赢了才是硬道理**这一步没人做。
10
+
11
+ | `priority.strategy` | 对手 | 必须的写法 | 自检判据 |
12
+ |---|---|---|---|
13
+ | `scope_qualified` | 无,或出厂**全局样式**(`sidebar.scss` / `element-plus.scss` / `theme.scss`,注意它们也在 `index.scss` 的 `@use` 链里、可能带 `!important` 且 `b` 位更高) | 按词典 selector 原样落;**逐位比过对手**(先 b 后 c);出厂用 `var(--vts-theme-*)` 时优先重映射令牌 | 若实测仍被覆盖 → 升格按 `deep_qualified` 处理 |
14
+ | `deep_qualified` | 组件 `<style scoped>`(平手 + 后注入) | **禁止裸类名**。≥3 层作用域限定(如 `html .a .b`)或叠加属性/伪类;仍平手才对本条补 `!important` | 写前自问:这条与组件 scoped 谁特异度高?**平手即错** |
15
+ | `self_plus_important` | 出厂规则带 `!important` | 本条必须 `!important` + 注释写明「对手带 `!important`」;能改走通道变量时优先改通道 | 只抬特异度无效,别白费 |
16
+
17
+ 落地写法模板(每条规则标注来源 + 取胜依据):
18
+
19
+ ```scss
20
+ /* <语义 ID> · <变更条目> · 取胜依据:deep_qualified(对手 lay-*.vue scoped) */
21
+ html .navbar .navbar-breadcrumb-wrap {
22
+ display: none; /* visible:false · 存在性收口,不删出厂代码行 */
23
+ }
24
+ ```
25
+
26
+ **`!important` 只允许出现在两种情形**:① `strategy = self_plus_important`(对手带 `!important`);② 对手是组件 scoped 且提权后**实测**仍平手。其余一律靠作用域限定解决——逐点堆 `!important` 会让点位互相耦合、副作用累积成漂移,也就是「越改越乱」的机理。
@@ -0,0 +1,13 @@
1
+ # design-apply · 第 4 步 · L3 新模块处理(分级布局)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:存在未命中点位 / 新页面生成时。
4
+
5
+ ---
6
+
7
+ ### 第 4 步 · L3 新模块处理(分级布局)
8
+
9
+ - **验收对象闸(角色集合必须齐)**:验收页面的**角色集合**必须覆盖变更集声明的角色。缺角色的,按第 0.2 步「对接匹配 → 需适配」处置——**项目侧补齐该角色的骨架 / 结构**(走 `crud-pages` 样板 + L3 落地并申报),**不是要求设计侧换页面**。不得用出厂 demo 页充数:demo 页**结构上就没有**标题区 / 批量按钮 / 状态 Tag 这些角色 → 这类差异**无论怎么调 CSS 都消不掉**(不是样式问题,是角色集合不匹配)。
10
+ - **列宽口径(业务层 / 设计层边界)**:表格**业务列宽度属业务层**,设计侧不声明、项目侧不按效果图硬套——效果图里的列宽只是其示例数据下的参考值。**唯一例外是操作列**:宽度由组件公式推算(`resolveOperateColumnWidth`,已含分割线占位),业务页禁止写死。**固定列自查(落完后必做,防「符合规范但不合常规」)**:操作列按钮不被裁、不换行、分割线居中可见;状态列标签完整;表头/单元格标题不被省略号截断——任何一项不满足即返工,禁止用「设计值就是对的」搪塞。
11
+
12
+ - **L3 是施工指令,不是待办**:词典未命中的点位一律当场落地、交付说明申报「补映射」,不留待确认。新模块按「定制布局」三步走:① 基于全局规范生成结构(继承命名/作用域/组件规范)② 原子层字段(色彩/圆角/组件级)从 `basic/` + `component/` 词典借力 ③ 场景专属点位生成后**立即写入 mapping/ 对应场景域**(临时映射),累计复用 ≥3 次建议升级标准(由人工评审)。
13
+ - 生成的新页面必须带构图钩子(`vts-page-card` / `vts-filter-area` / `vts-table-area` 等),保证后续变更集可命中。
@@ -0,0 +1,44 @@
1
+ # design-apply · 第 5 步 · 合规闸门(变更集专属检查清单)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:施工完成后、验收前。
4
+
5
+ ---
6
+
7
+ ### 第 5 步 · 合规闸门(变更集专属检查)
8
+
9
+ 跑 `code-quality` 全量清单之外,追加:
10
+
11
+ - [ ] 变更集外的任何点位**零改动**(diff 只含变更集提到的文件/选择器)
12
+ - [ ] `visible: false` 的模块代码仍存在(只是隐藏)
13
+ - [ ] **`!important` 使用合规**:新增 `!important` 仅允许两种情形——① 词典 `priority.strategy = self_plus_important`(对手带 `!important`);② 对手为组件 scoped 且提权后**实测**仍平手;且每条带理由注释。其余一律靠作用域限定解决。无内联 style 硬编码色值(全部走变量)
14
+ - [ ] 未修改 `src/components/`(Re* 组件库源码——**底线一**)
15
+ - [ ] 未改动业务逻辑层(API/状态/事件——**底线二**;样式与结构通道内的 DOM 调整除外)
16
+ - [ ] 两层样式全部落在 `style_scope` 作用域内,无全局泄漏
17
+ - [ ] **类名冲突检查(AI 施工硬性步骤)**:新增 class 之前先在目标文件与同作用域全局样式中检索同名类——已存在时禁止直接追加重复定义,按三选一处理并在交付说明申报:① 语义相同 → **合并**进既有规则;② 语义不同 → 改用带点位前缀的新类名(如 `vts-<语义id末段>`);③ 确需覆盖 → 走作用域内更高优先级(不写 `!important`)。重复类名(尤其跨 `<style>` 块的 scoped 样式重复定义)会触发编辑器/构建报错,**本项不通过不得交付**
18
+ - [ ] **出厂中性检查(架构红线,不通过必须回退重做)**:diff 中不得出现「为表达本次设计而改写出厂文件」的产物——典型症状:把指示条方位/问候语 DOM/某个具体尺寸直接写进 `sidebar.scss`、`element-plus.scss`、`lay-navbar/index.vue`、`lay-content/index.vue` 等出厂载体;在出厂 `<component>` 上硬编码 `data-content-mode`/样式钩子。出厂文件若被改动,只能是「补通道」(补变量消费者 / 补 form 枚举 / 修层叠优先级,如已修的 `:has()` 与显式模式优先级反转),且必须在交付说明单列「补通道」条目写明缺失点;非此情形一律回退,改由 `design-shell.scss` + 变更集驱动。**模板源码注释保持中性**:diff 中不得出现「语义 ID / 本协议步骤号 / 面向 AI 的纪律条款」写进模板源码注释(如 `lay-content/index.vue`、`element-plus.scss`、`design-shell.scss` 的文件头与段落注释);这类内容只允许存在于技能侧文档
19
+ - [ ] **文本溢出回归检查**:改动侧栏菜单/顶栏/页签等含文字的模块后,必须确认「长文本显示」未被破坏(菜单项名称完整可见,必要时保留 ellipsis 溢出策略而不是隐藏/截断);宽度相关字段(width/min-width/padding)改动后逐项目视验证
20
+ - [ ] **形态与存在性目视验证(历史漏还原高发区,声明即必须验证,没做视同未交付)**:变更集声明了以下意图时,逐项在页面上确认真实生效——
21
+ - 语言切换 form=inline_switch → 顶栏出现「中|EN」并排文字(不再是纯图标)
22
+ - 折叠按钮 form=header_inline → 顶栏最左出现 40×40 折叠按钮且与首页页签左对齐;**同时侧栏底部出厂折叠条按设计隐藏(visible:false 声明时)**,避免双折叠按钮并存
23
+ - 侧栏 `menu_active_*` / `form=indicator_*` → **按变更集声明的 form 逐项核对**(indicator_left → 左侧竖条;indicator_right → 右侧竖条;indicator_underline → 底部横线;pill → 胶囊底色;none → 无指示):方位/粗细/长度/圆角与变更集 style 字段一致,且出厂胶囊已关闭(`--vts-theme-menu-active-bg: transparent`)、`--vts-theme-menu-active-before` 消费者真实建成。**禁止用「左侧 3px」这类历史/词典结论替代当次声明**——设计换了就必须是新的方位与数值
24
+ - 顶栏未声明点位(设置按钮等)→ 已收口不显示;用户区 → 按 `form` 核对组合形态(`avatar_name` / `greeting_avatar_name` / `greeting_name` / `avatar_only` / `name_only`),其中 greeting 为结构增量节点(出厂无此 DOM,需 AI 按 form 插入后再验)
25
+ - 页签图标 → 按 `form` 核对(item 的 `text_only`/`with_icon`,home_tab 的 `icon_only`/`text`),出处是路由 `meta.icon` 数据或本次隐藏规则,不是源码常量
26
+ - 内容区 form=scroll/fixed → `data-content-mode` 属性落在**页面根节点**(不是样式文件、不是壳层组件),列表页自动定高未被压掉;填满链逐层带 `data-fill`(详见下方「高度链存活检查」)
27
+ - 操作栏 form=with_tools/left_batch → 刷新/密度/列设置三件套齐全;批量删除红底/导出白底/未选中置灰
28
+ - 操作列 form=text_link → **业务列定义的 icon 字段已移除**(纯文字无图标,只改 CSS 保留图标 = 未还原);按钮单行不换行(列宽 ≥160px + nowrap);删除项红色;≥3 个折叠「更多」带箭头
29
+ - tabs form → 页签形态切换生效(chrome/card);激活态表现(有无下划线 / 是否仅文字变色 / 字重)按当次变更集 style 字段核对,**不以历史设计稿口径为准**
30
+ - [ ] **高度链存活检查(结构层不被设计改动压垮,也不被"保高度"绑架)**:定高页(`form=fixed` 或列表页自动定高)还原后逐项确认——
31
+ - `data-content-mode` 落在**页面根节点**;从页面根到表格/画布容器**每层需填满的节点都带 `data-fill`**(换了视觉容器时属性已平移;横向分栏用 `data-fill="row"`);
32
+ - `content` ref 仍绑在定高容器上(换容器后未丢),`otherRef` 仍在表格上方、分页仍在表格正下方;
33
+ - 表头 / 行 / 分页都在视口内,仅表格体内滚动,无外层滚动条、无拉伸 / 塌陷 / 双滚动条,`tableHeight > 0`;
34
+ - **结构层 diff 为空**:`lay-content/index.vue` 的 `.main-content[data-content-mode]` 与 `element-plus.scss` 的 `[data-fill]` 未被改动;同时确认没有「为保高度而放弃设计还原」(出厂卡片 / 内边距 / 内部排布原样未动而变更集声明了改动)——两个方向任一命中即返工
35
+ - [ ] **映射通道活性检查(杂必查)**:样式落地引用的每个 CSS 变量必须在项目样式中**存在消费者**(`变量名` 有 `var(--xxx)` 引用点);只定义不消费的变量 = 通道死路,翻译再准也不生效(menu_active_indicator 曾因 --vts-theme-menu-active-before 无消费者而「映射了却没效果」)。施工时 grep 核对,无消费者时改走消费者存在的作用域或补挂载点并申报。
36
+ - [ ] **结构施工兑现检查(structure_ops 逐条对账,与红线同级)**:变更集 `structure_ops[]` 的**每一条 op** 都必须在交付说明给出「op → 落在哪个文件 / 哪个节点 / 怎么落的」;`add_node` 必须真的新增了元素或渲染分支(模板 diff 可验),`bind_source` 必须真的改了绑定(`class-name` / `align` / `formatter`)。出现「声明了 op、代码里找不到对应改动」= 交付不完整,禁止只改 CSS 冒充结构施工(历史缺口:操作列分割线 `add_node` 声明了但从未施工 → 按钮间竖线一直缺失)
37
+ - [ ] **同权重失效检查( · 专查「写了不生效」)**:逐条核对设计层新增规则是否真能取胜——① 对手是组件 `<style scoped>` 时,本条特异度必须**严格高于**它(**平手即错**,因为组件样式在全局之后注入);② 对手带 `!important` 时本条必须同样 `!important`,或改走通道变量。**判定方法(必须真数,不许目测)**:对每条新规则与其对手分别写出特异度三元组 `(a,b,c)` 并**逐位比较(先 b 后 c)**,本条的 `b` 不大于对手即判为「失效」;`html` / `body` 只加 `c` 位,**对手 `b` 更高时加 `html body` 无效**,必须靠**加类**(祖先链补稳定语义类,如 `.el-menu`)把 `b` 抬到相等。同 `b` 时,`c` 更高者胜。③ **出厂用语义令牌间接设置该属性时(`var(--vts-theme-*)`),必须先走「令牌重映射」而不是抢属性**——在令牌宿主作用域重声明令牌即生效、零权重战争;只有无令牌或令牌语义不符时才抢属性。历史缺口全部命中本项:面包屑 `display:none`(与组件 scoped 同为 0,2,0)→ 照旧显示;页签关闭钮 `opacity`(同为 0,5,0)→ 仍要 hover 才显;页签项 `padding`(对手带 `!important`)→ 无论怎么抬特异度都改不动;**侧栏菜单 `color`(`b=2` 输给出厂 `b=3` + `!important`)→ 整栏菜单文字用浅色主题的黑色落在深色侧栏上、字全部消失**
38
+ - [ ] **oracle 基线可用性检查**:变更集带 `oracle` 时——① `oracle.mockup` 必须与**本次主题、本次页面**一致;**同构异色复用除外**:变更集声明 `oracle.theme_mapping: { "from": "<效果图主题>", "to": "<本次主题>" }`(同场景 / 同页面 / 同角色集合、仅主题色板不同)时,允许复用 from 主题效果图,verify 必须带 `--from-theme/--to-theme` 做色值归一,**不得因换主题色就判死闭环**;结构 / 形态有差异时禁止复用;② `oracle.sids` 与 `changes[]` **双向闭合**:效果图里有、changes[] 未声明 = **欠声明**(该点位永远不可能被还原);changes[] 已声明、效果图无 sid = **无基线**——**仅 `visible:false` 的隐藏点位豁免**(效果图上无可见元素可标 `data-sid`,parser 已自动豁免并打印清单)。其余两类出现即回流设计侧补齐,**不得直接开工**(`parser match` 已自动报出)
39
+ - [ ] **dark.scss 暗色同步**:新增视觉规则在 `html.dark` 有对应覆盖
40
+ - [ ] **缺口清单只含意图缺口**:清单每一项都必须是「设计侧未给值 / 值非法」且已注明「回流设计侧补齐」;能力缺口(词典缺 ID / 缺字段枚举 / 缺 form)不得出现在清单里——出现即把可落地项搁置
41
+ - [ ] **台账逐行兑现对账(对账闸门)**:把设计侧交付的提取台账逐行过一遍,每行必须有落地结论——已落地(写明落在哪个文件/选择器)或已入缺口清单(写明缺失字段)。存在「台账有行、落地无结论」的行 = 交付不完整,与红线同级
42
+ - [ ] **登记表覆盖率对账(子项级细闸,)**:带登记表交付时必须跑 `match --registry`——`C = A` 且无缺口才可交付;同时确认无「效果图标注缺口」(`always:true` 子项在效果图上都有同名 `data-sid`)。**禁止采信设计侧自报的 `coverage` 数字**(parser 会当场重算,自报数不参与);缺口逐条点名回流设计侧
43
+ - [ ] **零搁置交付**:最终回复不含「待确认」类停顿项;交付说明的「补映射 / 补通道 / 缺口回流」三段齐全(无内容写「无」)
44
+ - [ ] `node parser/index.js build --dry` 通过(mapping 若有临时新增)
@@ -0,0 +1,58 @@
1
+ # design-apply · 第 6 步 · 渲染态验收(oracle 逐点 diff · 快照回归 · 残差豁免)
2
+
3
+ > 本文件自 `design-apply.md` 拆出(上下文预算优化,内容未改动)。**主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:变更集含 oracle 时强制。
4
+
5
+ ---
6
+
7
+ ### 第 6 步 · 渲染态验收(变更集含 `oracle` 时强制 · 闭环回路)
8
+
9
+ 第 5 步是静态自查,查不出「值对了、位置不对 / 写了没生效」。**只要变更集带 `oracle`(效果图基线),落地后必须做机器逐点比对**——这是「1:1 还原」能被证明、且不再漂移的唯一手段。
10
+
11
+ **链路(抽取由浏览器完成,diff 由 parser 完成)**:
12
+
13
+ 1. **抽取期望值**:在浏览器打开效果图(`oracle.mockup`,元素已带 `data-sid`),对 `oracle.sids` 中每个 sid 取其代表性元素的 computed style,导出为 `{ "<sid>": { "<css属性>": "<值>" } }` → `oracle.json`。
14
+ 2. **抽取实测值**:在浏览器打开已落地页面,**按词典 `selector` / `anchors.target` 定位元素**(**项目页不要求打 `data-sid`**)做抽取 → `actual.json`。
15
+ - 先跑 `node parser/index.js verify --oracle oracle.json --resolve` 得到「sid → 词典 selector」定位计划;
16
+ - 抽取脚本(Playwright / 浏览器控制台)按计划 selector 取 `getComputedStyle(el)` 的白名单属性(padding / font-size / font-weight / text-align / color / background-color / border-radius / gap 等);
17
+ - **期望端(效果图)用 `data-sid`、实测端(项目页)用词典 selector——两侧定位方式不必对称**:效果图是设计侧自控产物,项目页是消费方、不感知设计坐标。selector 挂载点错位由 `audit` 先于 `verify` 报出,责任链回到词典;
18
+ - 期望值**优先直接消费设计侧交付的 `oracle.json` 抽取产物**(期望 / 实测同源同口径);无产物时再从 `oracle.mockup` 现场抽取;
19
+ - 两个页面的属性白名单必须一致,否则出现假缺口。
20
+ 3. **逐点 diff**:
21
+ ```bash
22
+ node parser/index.js verify --oracle oracle.json --actual actual.json
23
+ # 可选 --sids admin.content.table.header_cell,admin.layout.tabs.item 只验部分点位
24
+ # 同构异色复用(oracle.theme_mapping 已声明时必带)——效果图色值按语义槽位归一为本主题色值再比:
25
+ node parser/index.js verify --oracle oracle.json --actual actual.json --from-theme 钴蓝 --to-theme 橘橙
26
+ ```
27
+ 退出码:存在缺口(含存在性缺口 / 基线漂移)→ `1`。
28
+
29
+ **归因与处置(四类,禁止用 `!important` 掩盖)**:
30
+
31
+ | 归因 | 触发 | 处置 |
32
+ |---|---|---|
33
+ | **选择器落空** | oracle 有点位、actual 无(或某属性取不到) | 补挂载点:按 `structure_ops` 挂类 / 补 `data-sid` / 确认元素已渲染(属能力缺口,交付说明申报) |
34
+ | **权重被压** | 颜色 / 字重 / 透明度 / 阴影类属性值不符 | 按词典 `priority` 声明的策略提权(`scope_qualified` / `self_plus_important` / `deep_qualified`) |
35
+ | **语境错位** | 几何 / 盒模型属性(padding / 尺寸 / 对齐 / 行高)值不符 | 校准 `layer`(`host` vs `inner`)——值对了落错层 |
36
+ | **存在性缺口(G12)** | `oracle.absent` 点位在页面仍渲染可见(`display` 非 `none`) | 补 `visible:false` 收口并按词典 `priority` 提权(历史缺口:面包屑 `display:none` 被同权重 scoped 规则反压——写了不生效也是它) |
37
+
38
+ **存在性闸(`oracle.absent`)**:效果图上不存在的出厂点位(面包屑 / 设置铃铛等)逐条列入变更集 `oracle.absent`,verify 逐个断言「actual 不存在或 `display:none` / `visibility:hidden`」。**这类缺口无期望值,逐点 diff 永远验不到——不进 absent 就不在验收范围内**(2026-09-21 面包屑事故机制化)。
39
+
40
+ **残差豁免(`oracle.residual_accepted`)**:`[{ "sid": …, "reason": … }]`(reason 必填)。命中豁免的属性差异降级为「已申报固有残差」提示行,不进缺口计数;验收报告单列豁免明细,逐条可审计。**机制推算值(等宽槽宽)、业务资产(logo 图形)必须申报**——不申报 = 每轮验收重新报缺口 = 「改了很多版始终不行」的体感来源。
41
+
42
+ **快照回归(`--snapshot` / `--baseline`,治「上一轮改对的这一轮漂回」)**:
43
+
44
+ ```bash
45
+ # 每轮动工前:先对当前页面跑一次 verify 并导出快照
46
+ node parser/index.js verify --oracle oracle.json --actual actual.json --snapshot snapshot-r1.json
47
+ # 本轮交付前:带 --baseline 与上轮快照比对
48
+ node parser/index.js verify --oracle oracle.json --actual actual.json --baseline snapshot-r1.json
49
+ ```
50
+
51
+ - 上轮 `hit` / `absent-hit`、本轮退步的点位 / 属性 = **基线漂移**,逐条列出且 `exit 1`——先回归上轮修法,再谈新缺口。
52
+ - 项目还原到出厂(design-shell 回空壳)后第一轮验证**不带** `--baseline`(基线已失真),改以 clean 夹具重新起拍。
53
+
54
+ **夹具与设计资产的边界(职责单侧沉淀红线)**:`「页面名-主题」`命名法(如 `运单管理-钴蓝.html`)是设计侧效果图库的专属资产命名——**项目侧(含 parser/fixtures 回归夹具)禁止出现与设计侧资产同名的文件**。回归需要 mockup 实物时,一律用「回归夹具-」前缀合成名(如 `回归夹具-列表页-钴蓝.html`),点集为回归机制定制、与真基线**不同且不可互替**;真实效果图基线唯一沉淀在设计侧 `page-specs/styles/<方案>/scenes/<场景>/mockups/`,项目侧 `oracle.mockup` 指向它靠 `resolveFirstExisting` 跨库解析(变更集同目录 → cwd → 技能根 → 设计侧兄弟目录),不做本地拷贝。
55
+
56
+ - 验收结果写入最终回复(命中 N / 缺口 M / 归因分布 / 修正)与 `code-quality` 结果块;**不得只报「已完成」**。
57
+ - 变更集无 `oracle` 时输出 `N/A`(无基线),并在交付说明注明「无验收基线」——这是设计侧应补的项,回流设计侧。
58
+ - 静态审计(audit)与渲染态验收(verify)**互补**:audit 查「通道是否存在」,verify 查「渲染结果是否一致」,两者都过才算闭环。