@qilitt-mickey/vue3-temp-skill 1.1.76 → 1.2.2
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/README.md +99 -82
- package/SKILL.md +65 -28
- package/bin/cli.js +5 -6
- package/mapping/admin.json +60 -0
- package/package.json +5 -13
- package/references/adapters/_new-adapter.md +88 -0
- package/references/adapters/vue-antdv.md +110 -0
- package/references/adapters/vue-element-plus.md +132 -0
- package/references/design-apply.md +259 -122
- package/scripts/check-landing.mjs +419 -0
- package/scripts/modules.json +2 -2
- package/dist/mapping-type.d.ts +0 -33
- package/dist/theme-vars.js +0 -62
- package/dist/theme-vars.ts +0 -113
- package/dist/theme.css +0 -73
- package/mapping/basic/color.json +0 -35
- package/mapping/basic/radius.json +0 -17
- package/mapping/basic/semantic-values.json +0 -72
- package/mapping/basic/spacing.json +0 -21
- package/mapping/basic/typography.json +0 -21
- package/mapping/component/button.json +0 -90
- package/mapping/component/card.json +0 -31
- package/mapping/component/input.json +0 -42
- package/mapping/component/overlay.json +0 -79
- package/mapping/component/pagination.json +0 -34
- package/mapping/component/table.json +0 -42
- package/mapping/component/tag.json +0 -48
- package/mapping/layout/breakpoint.json +0 -20
- package/mapping/layout/shell-geometry.json +0 -26
- package/mapping/scenes/admin/content.json +0 -497
- package/mapping/scenes/admin/layout.json +0 -577
- package/parser/fixtures/changeset-fullpage-restore.json +0 -259
- package/parser/fixtures/changeset-gap-block.json +0 -24
- package/parser/fixtures/changeset-legacy.json +0 -11
- package/parser/fixtures/changeset-neg1.json +0 -8
- package/parser/fixtures/changeset-neg2.json +0 -10
- package/parser/fixtures/changeset-neg3.json +0 -22
- package/parser/fixtures/changeset-neg4-g8.json +0 -15
- package/parser/fixtures/changeset-neg5-g8-stub.json +0 -26
- package/parser/fixtures/changeset-neg6-g9-identity.json +0 -39
- package/parser/fixtures/changeset-neg7-g10-dims.json +0 -57
- package/parser/fixtures/changeset-neg8-g11-oracle.json +0 -57
- package/parser/fixtures/changeset-neg9-g6-token-chain.json +0 -34
- package/parser/fixtures/changeset-pos-g6-token-chain.json +0 -35
- package/parser/fixtures/changeset-pos-theme-neutral.json +0 -264
- package/parser/fixtures/changeset-pos-theme-nometa.json +0 -260
- package/parser/fixtures/changeset-pos.json +0 -50
- package/parser/fixtures/changeset-registry-gap.json +0 -29
- package/parser/fixtures/changeset-v32-fields.json +0 -71
- package/parser/fixtures/fake-project/src/styles/app.scss +0 -5
- package/parser/fixtures/fake-project/src/views/list.vue +0 -13
- package/parser/fixtures/registry-bad.json +0 -11
- package/parser/fixtures/registry-g6-token-chain.json +0 -10
- package/parser/fixtures/registry-sample.json +0 -15
- package/parser/fixtures/verify/actual-clean.json +0 -35
- package/parser/fixtures/verify/actual.json +0 -33
- package/parser/fixtures/verify/mockup-baseline-admin-list.html +0 -27
- package/parser/fixtures/verify/mockup-g6-content.html +0 -12
- package/parser/fixtures/verify/mockup-neutral.html +0 -26
- package/parser/fixtures/verify/mockup-nometa.html +0 -26
- package/parser/fixtures/verify/oracle.json +0 -37
- package/parser/fixtures/verify/snapshot-latest.json +0 -103
- package/parser/generator.js +0 -178
- package/parser/index.js +0 -2706
- package/parser/loader.js +0 -66
- package/parser/override.js +0 -119
- package/parser/regression.js +0 -301
- package/parser/validator.js +0 -206
- package/parser/watch.js +0 -103
- package/references/steps/maintenance.md +0 -31
- package/references/steps/regression.md +0 -49
- package/references/steps/step0-preflight.md +0 -58
- package/references/steps/step1-match.md +0 -67
- package/references/steps/step1b-audit.md +0 -23
- package/references/steps/step1c-registry.md +0 -29
- package/references/steps/step2-structure.md +0 -73
- package/references/steps/step3-style.md +0 -38
- package/references/steps/step3b-shell.md +0 -63
- package/references/steps/step3c-priority.md +0 -26
- package/references/steps/step4-l3.md +0 -14
- package/references/steps/step5-gates.md +0 -65
- package/references/steps/step6-verify.md +0 -77
- package/scripts/apply-final-gate.mjs +0 -170
- package/scripts/check.mjs +0 -207
- package/scripts/design-audit.mjs +0 -1707
- package/scripts/validate.mjs +0 -106
|
@@ -1,167 +1,304 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: design-apply
|
|
3
|
-
description:
|
|
3
|
+
description: 视觉契约落地协议。接收设计侧产出的视觉契约 JSON(ui.visual-contract/1.0),照抄生成三份样式文件(令牌 / 角色 / 布局)。AI 在本协议中的工作是翻译,不是判断。
|
|
4
4
|
scope: project
|
|
5
|
-
tags: [design-apply,
|
|
5
|
+
tags: [design-apply, visual-contract, design-tokens, role, layout]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
#
|
|
8
|
+
# 视觉契约落地(design-apply)
|
|
9
9
|
|
|
10
10
|
## 定位
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
把设计侧的视觉契约翻译成项目样式。**唯一输入是一份契约 JSON,唯一输出是三份 CSS。**
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
```
|
|
15
|
+
契约 JSON(技术栈中立)
|
|
16
|
+
↓ ① 展开令牌引用 ② 角色 → .role-<name> ③ 布局 → .ui-page 网格
|
|
17
|
+
src/styles/ui-tokens.css :root 变量
|
|
18
|
+
src/styles/ui-roles.css 角色规则
|
|
19
|
+
src/styles/ui-layout.css 区域网格
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**分工**:契约负责精确(写什么值、放哪一层),本协议负责翻译(怎么变成 CSS),组件库差异由 adapter 承担。
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 边界与约束(不可越)
|
|
27
|
+
|
|
28
|
+
本能力组只处理视觉落地,与 AI 工具无关;**只服务 Vue 3 项目**。
|
|
29
|
+
|
|
30
|
+
| 约束 | 说明 |
|
|
31
|
+
|---|---|
|
|
32
|
+
| **契约是唯一输入** | 不引入其他协议、不解析其他格式 |
|
|
33
|
+
| **契约里没有技术栈信息** | 只有 CSS 属性、令牌引用、区域与角色——因此不需要理解组件内部实现也能生成样式 |
|
|
34
|
+
| **路径约定用通用目录** | 读契约:`<项目根>/.design/visual-contract-*.json`;写样式:`src/styles/ui-*.css`。两者都是通用项目目录 |
|
|
35
|
+
| **组件库差异只在 adapter** | 深度选择器语法、组件库前缀、布局占位挂载点——adapter 的全部职责,adapter 只覆盖 Vue 组件库 |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 执行流程(六步)
|
|
40
|
+
|
|
41
|
+
### 第 0 步 · 落地自检(先跑,断在哪一目了然)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
node <技能>/scripts/check-landing.mjs --project <项目根>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**六项检查,逐项给修复动作,exit 1 表示链路有断点:**
|
|
48
|
+
|
|
49
|
+
| # | 检查项 | 断点含义 |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| 1 | `contract-found` | `.design/visual-contract-*.json` 不存在 → 设计侧没落盘 |
|
|
52
|
+
| 2 | `contract-valid` | 契约字段缺失(`meta.scene` / `tokens.color` / `roles` / `layout.areas`) |
|
|
53
|
+
| 3 | `css-generated` | 三份 CSS 未生成 → 第 3/4/5 步没执行 |
|
|
54
|
+
| 4 | `css-imported` | **生成了但没被 import** → 浏览器根本不加载 |
|
|
55
|
+
| 5 | `roles-mounted` | **CSS 有规则但模板没挂类** → 死样式,视觉不变 |
|
|
56
|
+
| 6 | `layout-mounted` | 模板没出现 `.ui-page` → 骨架仍是项目原样 |
|
|
57
|
+
|
|
58
|
+
**六项全过是交付前置条件。** 不过就修断点,**不要直接目视猜问题在哪**。
|
|
59
|
+
|
|
60
|
+
### 第 1 步 · 读契约(只读一次)
|
|
61
|
+
|
|
62
|
+
读取 `<项目根>/.design/visual-contract-*.json`。多份契约(多页型)逐份独立施工。
|
|
63
|
+
|
|
64
|
+
**读之前先确认 `meta`**:场景、页型、值来源。契约里已声明这三项,**不从项目源码反推、不自行猜测**。
|
|
65
|
+
|
|
66
|
+
契约是项目的完整视觉事实源——**不读项目现有样式来决定怎么落地**。项目现有样式与契约冲突时,以契约为准。
|
|
67
|
+
|
|
68
|
+
### 第 2 步 · 选 adapter(按项目事实判定)
|
|
69
|
+
|
|
70
|
+
读 `package.json` 判定所用组件库,选取对应 adapter:
|
|
71
|
+
|
|
72
|
+
| 项目依赖 | adapter |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `element-plus` | `adapters/vue-element-plus.md` |
|
|
75
|
+
| `ant-design-vue` | `adapters/vue-antdv.md` |
|
|
76
|
+
| 其他 / 暂无 | 按 `adapters/_new-adapter.md` 模板补一份 Vue 组件库 adapter |
|
|
77
|
+
|
|
78
|
+
**本技能只服务 Vue 3 项目**,因此 adapter 只覆盖 Vue 组件库。需要支持其他前端框架时,由对应框架的项目技能自带 adapter——契约格式不变,改的只是落地那一侧的 adapter。
|
|
79
|
+
|
|
80
|
+
**adapter 只回答三件事**:① 深度选择器语法 ② 组件库穿透前缀 ③ 三份 CSS 的落点文件与引入方式。
|
|
81
|
+
|
|
82
|
+
**adapter 不定义设计意图、不定义风格、不改写契约值。**
|
|
83
|
+
|
|
84
|
+
### 第 3 步 · 写令牌 → `src/styles/ui-tokens.css`
|
|
85
|
+
|
|
86
|
+
契约 `tokens` 逐条转 CSS 变量:
|
|
87
|
+
|
|
88
|
+
```css
|
|
89
|
+
:root {
|
|
90
|
+
--color-brand: #2B5AED;
|
|
91
|
+
--color-brand-hover: #1F4FD8;
|
|
92
|
+
--color-text-primary: #1F2329;
|
|
93
|
+
--space-4: 16px;
|
|
94
|
+
--radius-md: 6px;
|
|
95
|
+
--size-control-height: 32px;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**命名规则**:`tokens` 的 `<族>.<名>` → `--<族>-<名>`,点号转连字符(`space.4` → `--space-4`,`control.height` → `--control-height`)。
|
|
100
|
+
|
|
101
|
+
**值原样抄**:契约里是实值就写实值,是 `{令牌引用}` 就先完成替换。**不重新取色、不换算、不四舍五入。**
|
|
15
102
|
|
|
103
|
+
### 第 4 步 · 写角色 → `src/styles/ui-roles.css`
|
|
104
|
+
|
|
105
|
+
契约 `roles` 逐条转类规则。**这是纯粹的翻译,每个角色一段:**
|
|
106
|
+
|
|
107
|
+
```css
|
|
108
|
+
/* 角色:table.headerCell */
|
|
109
|
+
.role-table-header-cell { background-color: #FAFAFA; height: 48px; padding: 16px; border-bottom: 1px solid var(--color-border-base); }
|
|
110
|
+
.role-table-header-cell :deep(span) { font-size: var(--font-size-md); font-weight: 500; color: var(--color-text-primary); text-align: left; white-space: nowrap; }
|
|
16
111
|
```
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
112
|
+
|
|
113
|
+
**翻译规则表**:
|
|
114
|
+
|
|
115
|
+
| 契约结构 | 生成 |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `roles.<名>.host[]` | `.role-<名转连字符> { … }` |
|
|
118
|
+
| `roles.<名>.inner[]` | 同类名 + adapter 的内层穿透语法(`:deep()` / `>>>` / 属性选择器) |
|
|
119
|
+
| `roles.<名>.states.hover.host[]` | `.role-<名>:hover { … }` |
|
|
120
|
+
| `roles.<名>.states.disabled.inner[]` | `.role-<名>:disabled { … }`(或 adapter 的 disabled 通道) |
|
|
121
|
+
| 声明值 `{令牌}` | 替换为 `var(--令牌)` |
|
|
122
|
+
|
|
123
|
+
**角色名转换**:`table.headerCell` → 类名 `.role-table-header-cell`(点号转连字符 + `role-` 前缀,避免与组件库类名冲突)。
|
|
124
|
+
|
|
125
|
+
**AI 在这一步不做的事**:
|
|
126
|
+
|
|
127
|
+
| 不做 | 为什么 |
|
|
128
|
+
|---|---|
|
|
129
|
+
| 判断某属性落 host 还是 inner | 契约已用两个数组物理二分,照抄 |
|
|
130
|
+
| 判断该不该加 `!important` | 契约禁止;层叠由 adapter 统一处理 |
|
|
131
|
+
| 判断该不该提权覆盖组件库 | 角色是独立类 + 独立文件,天然不与组件库同类规则竞争;确有冲突时由 adapter 的唯一提权通道处理 |
|
|
132
|
+
| 补角色库没有的角色 | 图上没有的角色不写进契约,契约里没有就不生成 |
|
|
133
|
+
| 合并 / 简化声明 | 一条声明一个属性,原样生成 |
|
|
134
|
+
|
|
135
|
+
### 第 5 步 · 写布局 → `src/styles/ui-layout.css`
|
|
136
|
+
|
|
137
|
+
契约 `layout` 转网格。**这是布局差异的落点——设计布局与项目布局不一致时,差异只体现在这份文件的取值上。**
|
|
138
|
+
|
|
139
|
+
```css
|
|
140
|
+
.ui-page {
|
|
141
|
+
display: grid;
|
|
142
|
+
grid-template-columns: 208px 1fr;
|
|
143
|
+
grid-template-rows: 54px 40px 1fr;
|
|
144
|
+
grid-template-areas: "side head" "side tabs" "side body";
|
|
145
|
+
}
|
|
146
|
+
.ui-region-sidebar { grid-area: side; background-color: var(--color-shell-bg); width: 208px; }
|
|
147
|
+
.ui-region-header { grid-area: head; height: 54px; background-color: var(--color-surface); padding: 0 20px; }
|
|
148
|
+
.ui-region-tabs { grid-area: tabs; height: 40px; background-color: var(--color-surface); }
|
|
149
|
+
.ui-region-content { grid-area: body; padding: 24px; background-color: var(--color-page-bg); gap: 20px; }
|
|
20
150
|
```
|
|
21
151
|
|
|
22
|
-
|
|
152
|
+
**翻译规则**:
|
|
153
|
+
|
|
154
|
+
| 契约字段 | 生成 |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `layout.grid` | `grid-template-columns` |
|
|
157
|
+
| `layout.rows` | `grid-template-rows` |
|
|
158
|
+
| `layout.areas[]` | `grid-template-areas`(由各区域的 `area` 值排布)+ `.ui-region-<名> { grid-area: <area> }` |
|
|
159
|
+
| `layout.regions.<名>` 几何键 | `width` / `height` / `min-height` / `padding` / `gap` |
|
|
160
|
+
| `layout.regions.<名>` 排布键 | `display` / `flex-direction` / `justify-content` / `align-items` / `flex-wrap` |
|
|
161
|
+
| `layout.regions.<名>` 定位键 | `position` + `top/right/bottom/left`(`offset` 的键)/ `z-index` |
|
|
162
|
+
| `layout.regions.<名>` `bleed` | 负 margin 抵消父容器内边距 + 自身宽度撑回 |
|
|
163
|
+
| 未写入 `areas` 的区域 | **不生成规则**(即为不渲染)——不需要单独的显隐声明 |
|
|
164
|
+
|
|
165
|
+
**`bleed` 的生成示例**(页签栏在内容区内但要通栏):
|
|
166
|
+
|
|
167
|
+
```css
|
|
168
|
+
/* 契约:tabs 区域 bleed: { top: true, left: true, right: true },内容区 padding: 24px */
|
|
169
|
+
.ui-region-tabs {
|
|
170
|
+
margin: -24px -24px 16px; /* 抵消父内边距 */
|
|
171
|
+
padding-left: 24px; /* 自身内容补回 */
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**关键**:项目现有的布局组件退化为**占位容器**(保留业务插槽,不参与布局决策)。页面骨架由本步生成的 `.ui-page` 网格决定。
|
|
176
|
+
|
|
177
|
+
### 第 5b 步 · 生成角色的几何与排布
|
|
178
|
+
|
|
179
|
+
角色除视觉声明外还带结构键,**这些键决定元素「为什么在这个位置」**:
|
|
23
180
|
|
|
24
|
-
|
|
181
|
+
| 契约结构 | 生成 |
|
|
182
|
+
|---|---|
|
|
183
|
+
| `roles.<名>.box` | `width` / `min-width` / `max-width` / `height` |
|
|
184
|
+
| `roles.<名>.flow` | `display` / `align-items` / `gap` / `flex` / `min-width` |
|
|
185
|
+
| `roles.<名>.align` | `text-align` / `vertical-align` |
|
|
186
|
+
| `roles.<名>.span` | `flex` / `flex-shrink` / `min-width` |
|
|
187
|
+
| `roles.<名>.sticky` | `position: sticky` + 对应方位的 `top/right/bottom/left` |
|
|
188
|
+
| `pages.<页型>.nodes[].box` | 该节点绑定的几何约束(覆盖角色默认) |
|
|
189
|
+
| `pages.<页型>.nodes[].sticky` | 该节点绑定的吸附方位 |
|
|
25
190
|
|
|
26
|
-
|
|
191
|
+
**三条必须落实的派生规则**:
|
|
27
192
|
|
|
28
|
-
|
|
193
|
+
| 规则 | 生成什么 |
|
|
194
|
+
|---|---|
|
|
195
|
+
| **弹性收缩配 `min-width: 0`** | 契约给了 `span: { flex: "1" }` 就必须同时生成 `min-width: 0`,否则长内容撑破容器 |
|
|
196
|
+
| **宽度三态照抄** | 契约写 `minWidth` 就生成 `min-width`,不擅自补 `width` |
|
|
197
|
+
| **吸附列补底色** | `sticky` 存在时必须给 `background`(否则滚动时透出下层内容) |
|
|
29
198
|
|
|
30
|
-
|
|
31
|
-
2. **设计技能产出**:用户在设计会话产出变更集后转来落地。若用户尚未产出,可先**下发词汇约束**提升命中率——把 `node parser/index.js list --verbose` 的点位清单(ID + 字段 + 形态枚举)一并提供给设计侧(`mapping_version` 恒为 `1.0.0`,设计侧无需查询版本),设计侧按约束输出(约束外意图走其 pending 通道,落地时按 L3 处理)。
|
|
199
|
+
### 第 5c 步 · 处理跨元素联动
|
|
32
200
|
|
|
33
|
-
|
|
201
|
+
契约 `pages.<页型>.nodes[].when` 声明的联动,由 adapter 提供实现方式:
|
|
34
202
|
|
|
35
|
-
|
|
203
|
+
| `when` | adapter 的实现方式 |
|
|
204
|
+
|---|---|
|
|
205
|
+
| `rowHover` | 用行状态的 class 覆盖绑定元素底色 |
|
|
206
|
+
| `rowSelected` | 用选中态 class 覆盖绑定元素底色 |
|
|
207
|
+
| `colSticky` | 吸附列底色跟随所在行——**必须实现**,否则滚动时露底 |
|
|
208
|
+
| `groupHover` | 用分组 hover 的 class 覆盖 |
|
|
36
209
|
|
|
37
|
-
|
|
38
|
-
2. **落地会话禁读设计侧规范库**:设计技能的 `page-specs/`(规范/令牌/效果图)不属于项目侧视野——项目侧消费的是**变更集 + oracle.json + 登记表**三个交付物;`oracle.mockup` 指向的效果图由 `resolveFirstExisting` 跨库解析给 parser 使用,但人(AI)**不打开、不阅读设计侧效果图与规范文件**。
|
|
39
|
-
3. **效果图只读一次**:期望值优先直接消费设计侧交付的 `oracle.json`;确需现场抽取时(无产物降级路径),抽取完成后值落盘,**后续轮次禁止反复打开效果图 HTML/JPG**。
|
|
40
|
-
4. **做到哪一步读哪一份**:各步骤细节在 `steps/` 子文件(见下方索引),按当前阶段加载,禁止一次全部通读。
|
|
210
|
+
**实现方式二选一**:能挂 class 就挂 class(简单可靠);挂不上就用组件的 `row-class-name` 回调。**由 adapter 决定,不由落地端临时发明。**
|
|
41
211
|
|
|
42
|
-
|
|
212
|
+
### 第 6 步 · 挂载 + 覆盖验证
|
|
43
213
|
|
|
44
|
-
|
|
214
|
+
1. 在样式入口引入三份文件(一次性,入口位置按项目现状)
|
|
215
|
+
2. 页面根节点挂 `.ui-page`,各区域挂 `.ui-region-<名>`
|
|
216
|
+
3. 按 adapter 的「角色类挂载方式」给组件挂 `.role-*`(**表格走插槽,不是在 `<el-table>` 上加类**)
|
|
217
|
+
4. **重跑第 0 步的落地自检,六项全过才算挂载完成**
|
|
218
|
+
5. 目视对照:打开页面与契约 `meta.source.mockup` 指向的效果图并排看
|
|
45
219
|
|
|
46
|
-
| |
|
|
220
|
+
| 现象 | 根因 | 修正动作 |
|
|
47
221
|
|---|---|---|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
222
|
+
| 页面完全没变化 | 三份 CSS 没被 import | 在样式入口 import 一次 |
|
|
223
|
+
| 只有个别地方变了 | 角色类挂载覆盖率低 | 按 adapter 挂法补齐,重跑自检 |
|
|
224
|
+
| 布局还是项目原样 | 没挂 `.ui-page` / `.ui-region-*` | 布局组件加类 |
|
|
225
|
+
| 有差异 | 契约值或落点层不对 | **改契约 → 重新生成 CSS** |
|
|
226
|
+
| 颜色不对 | 令牌值抄错 | 改 `tokens` → 重新生成 |
|
|
227
|
+
| 字号 / 字重不对 | 落错层(该进 `inner[]` 进了 `host[]`) | 改契约的数组归属 → 重新生成 |
|
|
228
|
+
| 表头竖排换行 | `white-space` 没进 `inner[]` | 同上 |
|
|
229
|
+
| 组件库样式盖住角色 | adapter 的穿透前缀不对 | 改 adapter 的穿透目标 |
|
|
230
|
+
| 布局位置不对 | `areas` 排布或 `regions` 取值不对 | 改 `layout` → 重新生成 |
|
|
231
|
+
| 某角色完全没生效 | 该角色没写进契约 | **回设计侧补抽**,不是项目侧猜 |
|
|
50
232
|
|
|
51
|
-
|
|
233
|
+
### 修正的唯一定向(不可破)
|
|
52
234
|
|
|
53
|
-
|
|
54
|
-
- ✅ 正例:`admin.layout.sidebar.menu` 暴露 `forms`(pill/indicator_left/indicator_right/indicator_underline/none)+ 几何字段,方位与粗细由变更集驱动;高度模式出厂不带任何属性,由页面根节点按变更集声明。
|
|
235
|
+
**只改契约或改 adapter,永远不直接改生成出来的 CSS。**
|
|
55
236
|
|
|
56
|
-
|
|
237
|
+
直接改 CSS 会在下次重新生成时被覆盖,且这份覆盖不会留下痕迹——同类问题会在下一轮以另一种形态复发。改契约的成本远低于改代码,因为契约是结构化的、可定位的、可重放的。
|
|
57
238
|
|
|
58
|
-
|
|
59
|
-
2. **无通道且需改 DOM**(新增节点,如问候语欢迎区)→ 结构增量施工(AI 在组件模板内按 `form` 插入,保形插入、不删原代码)。
|
|
60
|
-
3. **纯视觉表达**(颜色/圆角/间距/指示条几何)→ 设计层文件(见第 3 步)。
|
|
239
|
+
**不做**:不建期望值文件、不建采集脚本、不跑回归、不写逐点 diff 报告。
|
|
61
240
|
|
|
62
|
-
|
|
241
|
+
---
|
|
63
242
|
|
|
64
|
-
|
|
243
|
+
## 三列变量映射表
|
|
65
244
|
|
|
66
|
-
|
|
245
|
+
`mapping/<场景>.json` 是项目现状与契约区域名的对照表,**只有三列**:
|
|
67
246
|
|
|
68
|
-
```
|
|
247
|
+
```json
|
|
69
248
|
{
|
|
70
|
-
"schema": "
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
{ "
|
|
79
|
-
|
|
80
|
-
"global": { "brand_primary": "钴蓝-5" }, // 可选:全局令牌通道(整套主题切换优先走此节点;值 = 语义名或临时主题 hex)
|
|
81
|
-
"changes": [
|
|
82
|
-
{
|
|
83
|
-
"id": "admin.layout.sidebar.menu", // 语义 ID(词典 key)
|
|
84
|
-
"visible": true, // 可选:隐藏用 false(v-if/display,不删代码)
|
|
85
|
-
"position": "right", // 可选:相对方位(left/right/top/bottom)
|
|
86
|
-
"form": "card", // 可选:形态切换(见条目 forms 枚举)
|
|
87
|
-
"style": { "menu_bg": "钴蓝-9" }, // 可选:抽象样式字段(词典 css_vars/custom_style_map key;值 = 语义名或 hex)
|
|
88
|
-
"apply_via": "admin.layout.sidebar.menu", // 可选:本声明引用的锚点来源条目(缺省 = 自身;值 = 语义 ID,不是选择器)
|
|
89
|
-
"layer": { "menu_text": "host" }, // 可选:落点层级(host 宿主盒 / inner 内层文本盒);可为字符串(整条生效)或「字段 → 层级」对象
|
|
90
|
-
"structure_ops": [ // 可选:结构施工声明(数据 / 结构驱动点位必须给,只写 CSS = 无效声明)
|
|
91
|
-
{ "op": "render_branch", "node": "status_tag", "source": "row.status" }
|
|
92
|
-
]
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
"pending": [ // 新增 ID 通道:parser 解析 function/parent 供 L3 施工
|
|
96
|
-
{ "proposed_id": "portal.content.banner.carousel", "function": "门户首页轮播横幅", "parent": "portal.content.banner" }
|
|
97
|
-
]
|
|
249
|
+
"schema": "ui.var-map/1.0",
|
|
250
|
+
"stack": "vue3 + element-plus",
|
|
251
|
+
"adapter": "vue-element-plus",
|
|
252
|
+
"layoutHost": "src/layout/lay-admin/index.vue",
|
|
253
|
+
"regions": {
|
|
254
|
+
"sidebar": { "scope": ".lay-sidebar", "var": "--ui-sidebar-w", "fallback": "208px" },
|
|
255
|
+
"header": { "scope": ".lay-header", "var": "--ui-header-h", "fallback": "54px" },
|
|
256
|
+
"tabs": { "scope": ".lay-tabs", "var": "--ui-tabs-h", "fallback": "40px" },
|
|
257
|
+
"content": { "scope": ".lay-content", "var": "--ui-content-p","fallback": "24px" }
|
|
258
|
+
}
|
|
98
259
|
}
|
|
99
260
|
```
|
|
100
261
|
|
|
101
|
-
|
|
262
|
+
| 字段 | 作用 |
|
|
263
|
+
|---|---|
|
|
264
|
+
| `scope` | 项目里承载该区域的现有类名(供 adapter 定位,生成 CSS 时不必写死) |
|
|
265
|
+
| `var` | 项目侧可选的尺寸变量名(项目已有则复用,没有则用契约值直接写) |
|
|
266
|
+
| `fallback` | 项目缺该区域时的占位值 |
|
|
267
|
+
| `layoutHost` | 布局占位容器路径(保留业务插槽,不参与布局决策) |
|
|
102
268
|
|
|
103
|
-
|
|
104
|
-
|---|---|---|
|
|
105
|
-
| `apply_via` | 指认本声明使用的**锚点来源条目**(在哪条词条的 `anchors` 上落地) | 语义 ID 字符串(2~4 段小写下划线);不是选择器 / 变量名 |
|
|
106
|
-
| `layer` | 指认样式落在**宿主盒**还是**内层文本盒** | `"host"` / `"inner"`;或 `{ "<style字段>": "host"|"inner" }` |
|
|
107
|
-
| `structure_ops[]` | 需要**结构施工**时声明「改哪个语义节点 / 数据源、怎么改」 | `op` ∈ `add_node` / `remove_node` / `move_node` / `render_branch` / `bind_source`;`node` / `source` / `from` / `to` 为语义名 |
|
|
108
|
-
|
|
109
|
-
硬约束:
|
|
110
|
-
- 变更集**只含变更点位**——未提到的点位一律不动。
|
|
111
|
-
- `style` 字段为**抽象视觉语义**(`menu_bg`、`radius`),不得出现 CSS 变量名、选择器、`!important`、技术栈词汇。值口径:官方 5 套主题用语义名(`钴蓝-5`,译表见 `mapping/basic/semantic-values.json`);库外临时主题直接 hex + `notes` 申报派生口径。
|
|
112
|
-
- `position` 用相对方位词,不用像素坐标。
|
|
113
|
-
- `visible: false` 只做隐藏,**永不删除代码**。
|
|
114
|
-
- `apply_via` / `layer` / `structure_ops` 与 `style` 同属**语义声明**,同样不得出现选择器、CSS 变量名、DOM 词、技术栈词:`apply_via` 必须是语义 ID(锚点名)、`layer` 只能取 `host` / `inner`、`structure_ops[].op` 只能取五枚举。
|
|
115
|
-
- `pending` 数组声明的是设计侧新点位,直接归入 L3 处理(不是错误)。**注意:pending 不是施工指令**——L3 施工的内容以 `changes[]` 中同 ID 新条目声明的意图为准;设计侧只登记 pending、未在 changes[] 声明意图的点位,落地时按出厂现状处理并在缺口清单中反馈「该点位设计意图缺失」。
|
|
116
|
-
- parser 校验已实现:schema 硬校验、mapping_version 缺失/不匹配拒绝、禁词与 hex 位置校验、语义 ID 命名校验、`layer` / `apply_via` / `structure_ops` 结构校验。
|
|
117
|
-
|
|
118
|
-
各步骤**子文件按需加载**(做到哪一步读哪一份,禁止一次全部通读):
|
|
119
|
-
|
|
120
|
-
| 步骤 | 子文件 | 内容 | 加载时机 |
|
|
121
|
-
|---|---|---|---|
|
|
122
|
-
| 第 0 步 | [`step0-preflight.md`](steps/step0-preflight.md) | 第 0 步 · 版本与场景检查 · 对接匹配(适配前置)· 运行时清场 | 每次落地开工前(版本/场景/对接匹配/运行时清场三件套) |
|
|
123
|
-
| 第 1 步 | [`step1-match.md`](steps/step1-match.md) | 第 1 步 · parser 确定性匹配(含词典硬闸 G8-G11/G1/G5) | match 执行与闸门判读 |
|
|
124
|
-
| 第 1 步附加 | [`step1b-audit.md`](steps/step1b-audit.md) | 第 1 步附加 · 挂载点审计(audit · 静态查三类隐性缺口) | match 通过后、施工前 |
|
|
125
|
-
| 第 1 步附加(之二) | [`step1c-registry.md`](steps/step1c-registry.md) | 登记表覆盖率(子项级细闸) | 变更集带 coverage.registry / --registry 时 |
|
|
126
|
-
| 第 2 步 | [`step2-structure.md`](steps/step2-structure.md) | 第 2 步 · 结构先行(visible / position / form · structure_ops · layer · suppress · priority 消费) | 进入施工时(先于一切样式) |
|
|
127
|
-
| 第 3 步 | [`step3-style.md`](steps/step3-style.md) | 第 3 步 · 样式落地(两层转换 + 语义值译表) | 结构完成后 |
|
|
128
|
-
| 第 3 步附加 | [`step3b-shell.md`](steps/step3b-shell.md) | 第 3 步附加 · 设计层落点文件 design-shell.scss(强制 · 覆写定律 · 自举) | 写任何新 CSS 规则前 |
|
|
129
|
-
| 第 3 步附加(之二) | [`step3c-priority.md`](steps/step3c-priority.md) | 覆写优先级消费(硬步骤) | 与 step3b 配套,落规则前逐条判定 |
|
|
130
|
-
| 第 4 步 | [`step4-l3.md`](steps/step4-l3.md) | 第 4 步 · L3 新模块处理(分级布局) | 存在未命中点位 / 新页面生成时 |
|
|
131
|
-
| 第 5 步 | [`step5-gates.md`](steps/step5-gates.md) | 第 5 步 · 合规闸门(变更集专属检查清单) | 施工完成后、验收前 |
|
|
132
|
-
| 第 6 步 | [`step6-verify.md`](steps/step6-verify.md) | 第 6 步 · 渲染态验收(oracle 逐点 diff · 快照回归 · 残差豁免) | 变更集含 oracle 时强制 |
|
|
133
|
-
| 维护 | [`maintenance.md`](steps/maintenance.md) | 词典维护纪律 · 出厂状态漂移排查 | 改 mapping / 排查词典假前提时 |
|
|
134
|
-
| 回归 | [`regression.md`](steps/regression.md) | 端到端回归 A-V · 配套工具 | 改 parser/mapping 后必跑 |
|
|
135
|
-
|
|
136
|
-
**红线摘要(全文适用,细节在各步子文件)**:出厂中性 · 变更集驱动(上文);先结构后样式(第 2 步先于第 3 步);缺口只分「能力缺口(当场落地)」与「意图缺口(回流设计侧)」两类;**效果图/大文件只读一次**——期望值落盘 `oracle.json` 后,后续环节一律消费落盘产物,禁止反复重读。环境无 Node 时按「环境备注」(见 maintenance.md)人工执行。
|
|
137
|
-
|
|
138
|
-
## 施工标记规范(G3:@sid / @closed,design-audit E15 机检)
|
|
139
|
-
|
|
140
|
-
结构性声明(`form` / `suppress` / `suppress_inner` / `structure_ops` / `text_visible:none` / `visible:false`)**必须在设计层留机读标记**——声明了不等于落地了,没有标记就没有对账凭证(悬空声明例:`collapse_trigger.form=header_inline` 声明后壳层零规则,落地端静默无效):
|
|
141
|
-
|
|
142
|
-
| 标记 | 写法 | 作用 |
|
|
143
|
-
|---|---|---|
|
|
144
|
-
| `@sid` | 规则上方 `/* @sid: <语义ID> */` | 「变更集 ↔ 设计层」逐条落点对账(@sid 强制) |
|
|
145
|
-
| `@closed` | 收口规则上方 `/* @closed: <通道名> */` | suppress 收口兑现证据(通道名 = 词典 forms/css_vars/custom_style_map 的键) |
|
|
269
|
+
**三列取代了原有的八件套词典**(`selector` / `css_vars` / `custom_style_map` / `style_scope` / `anchors` / `preconditions` / `priority` / `forms`)——落点层级由契约的 `host`/`inner` 二分承载,优先级由 adapter 统一,形态由契约声明本身承载。
|
|
146
270
|
|
|
147
|
-
|
|
271
|
+
---
|
|
148
272
|
|
|
149
|
-
##
|
|
273
|
+
## 与项目其他能力的关系
|
|
150
274
|
|
|
151
|
-
|
|
275
|
+
本能力组只管视觉落地。项目开发主流程(列表页、表单、API、权限等)见 `SKILL.md` 的能力组路由。
|
|
152
276
|
|
|
153
|
-
|
|
277
|
+
**两条链路的边界**:
|
|
278
|
+
|
|
279
|
+
| 场景 | 入口 | 产物 |
|
|
154
280
|
|---|---|---|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
158
|
-
|
|
281
|
+
| 常规开发 | 能力组路由(`crud-pages` / `form-advanced` / `http-api` …) | 业务代码 |
|
|
282
|
+
| **设计契约落地** | 本协议 | `ui-tokens.css` / `ui-roles.css` / `ui-layout.css` |
|
|
283
|
+
|
|
284
|
+
常规开发**不受本协议约束**——它写自己的页面样式,不生成角色类。两条链路的样式互不干扰:角色类是独立命名空间(`role-` 前缀),布局类是独立命名空间(`ui-` 前缀)。
|
|
285
|
+
|
|
286
|
+
---
|
|
159
287
|
|
|
160
|
-
|
|
288
|
+
## 红线
|
|
289
|
+
|
|
290
|
+
1. **契约是唯一事实源**——不读项目现有样式来决定怎么落地;冲突时以契约为准。
|
|
291
|
+
2. **照抄不判断**——不判断落点层级、不合并声明、不补角色库没有的角色、不改契约值。
|
|
292
|
+
3. **禁止 `!important`**——角色类是独立命名空间,天然不竞争;确有冲突走 adapter 的唯一提权通道。
|
|
293
|
+
4. **不改项目布局组件的布局决策**——它退化为占位容器;改它等于把设计结论烧进源码。
|
|
294
|
+
5. **工具中立**——协议内容不出现任何 AI 工具的专有概念;路径只用通用项目目录。
|
|
295
|
+
|
|
296
|
+
---
|
|
161
297
|
|
|
162
|
-
|
|
163
|
-
- 「全量覆盖是迭代项 / 随迭代补齐 / 后续迭代再补其余细项 / 不阻塞已落地代码」——**覆盖率欠账 = 交付未完成**,不是迭代计划;设计侧变更集 `coverage.note` 出现同类表述同样视为交付失败(设计侧闸 D4/D9 会先拦,话术绕过闸的在这里兜底)。
|
|
164
|
-
- 「核心点位已落地,其余点位影响不大」——影响大小不由落地端裁定,范围只由变更集 `coverage` 与登记表裁定。
|
|
165
|
-
- 「已落地主题色与关键视觉,还原度已达 X%」——还原度以 verify / 登记表对账为准,不得以点位抽样自评。
|
|
298
|
+
## 子文件(按需加载)
|
|
166
299
|
|
|
167
|
-
|
|
300
|
+
| 文件 | 加载时机 |
|
|
301
|
+
|---|---|
|
|
302
|
+
| `adapters/vue-element-plus.md` | 项目用 Element Plus |
|
|
303
|
+
| `adapters/vue-antdv.md` | 项目用 Ant Design Vue |
|
|
304
|
+
| `adapters/_new-adapter.md` | 项目用其他 Vue 组件库,需要补一份适配 |
|