@qilitt-mickey/vue3-temp-skill 1.1.44 → 1.1.46
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/mapping/component/button.json +8 -3
- package/mapping/component/card.json +31 -0
- package/mapping/component/input.json +4 -1
- package/mapping/component/pagination.json +34 -0
- package/mapping/component/tag.json +2 -1
- package/mapping/scenes/admin/content.json +40 -11
- package/mapping/scenes/admin/layout.json +21 -10
- package/package.json +1 -1
- package/parser/fixtures/changeset-v32-fields.json +2 -2
- package/parser/index.js +22 -22
- package/parser/regression.js +2 -2
- package/parser/validator.js +4 -4
- package/references/cobalt-admin-restore.changeset.json +468 -0
- package/references/code-quality.md +3 -1
- package/references/design-apply.md +49 -13
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"custom_style_map": {
|
|
26
26
|
"font_weight": "font-weight",
|
|
27
27
|
"padding_x": "padding-inline",
|
|
28
|
-
"shadow": "box-shadow"
|
|
28
|
+
"shadow": "box-shadow",
|
|
29
|
+
"height": "height",
|
|
30
|
+
"radius": "border-radius"
|
|
29
31
|
},
|
|
30
32
|
"$note": "EP 实证:.el-button--primary 类 = 给通用变量 --el-button-* 赋 --el-color-primary 系列值,无 --el-button-primary-* 独立变量。AI 施工必须以 .el-button--primary 限定选择器作用域(禁止裸写 :root);设计侧调主题主色优先动 --el-color-primary,按钮自动跟随。未列变量(hover-border/outline 等)按同规则推导"
|
|
31
33
|
},
|
|
@@ -44,7 +46,9 @@
|
|
|
44
46
|
},
|
|
45
47
|
"custom_style_map": {
|
|
46
48
|
"font_weight": "font-weight",
|
|
47
|
-
"padding_x": "padding-inline"
|
|
49
|
+
"padding_x": "padding-inline",
|
|
50
|
+
"height": "height",
|
|
51
|
+
"radius": "border-radius"
|
|
48
52
|
},
|
|
49
53
|
"$note": "default 按钮直接消费通用变量本体,无 variant 类覆写;primary/danger 与本条目共用通用变量,靠 variant 类作用域隔离"
|
|
50
54
|
},
|
|
@@ -67,7 +71,8 @@
|
|
|
67
71
|
"custom_style_map": {
|
|
68
72
|
"font_weight": "font-weight",
|
|
69
73
|
"padding_x": "padding-inline",
|
|
70
|
-
"radius": "border-radius"
|
|
74
|
+
"radius": "border-radius",
|
|
75
|
+
"height": "height"
|
|
71
76
|
},
|
|
72
77
|
"$note": "承接批量删除等危险操作按钮(admin.content.table.operation_bar 引用)。EP 实证:.el-button--danger 类 = 给通用变量 --el-button-* 赋 --el-color-danger 系列值,无 --el-button-danger-* 独立变量。AI 施工必须以 .el-button--danger 限定选择器作用域(禁止裸写 :root);调红的深浅优先动 --el-color-danger"
|
|
73
78
|
},
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "全局原子层 · 卡片容器组件映射(admin 列表页 .vts-page-card 壳层卡片;registry list-page §11.24 登记的 always 子项 bg_color/radius/border_color/padding_x/padding_y/box_shadow)。样式规则经 src/styles/design-shell.scss 落在 .vts-page-card(设计层文件,非出厂源码)。字段名严格对齐 restore-registry 的 dim(parser 逐项校验)。版本恒 1.0.0(由 SKILL.md 体系版本统一管理)。",
|
|
3
|
+
"meta": {
|
|
4
|
+
"layer": "basic",
|
|
5
|
+
"domain": "component_card",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"scene": "global",
|
|
8
|
+
"tech_stack": "vue3 + element-plus + vue3-web-temp"
|
|
9
|
+
},
|
|
10
|
+
"mappings": {
|
|
11
|
+
"component.card.base": {
|
|
12
|
+
"type": "global_component",
|
|
13
|
+
"component": "VtsPageCard(.vts-page-card 壳层卡片容器)",
|
|
14
|
+
"style_scope": ".vts-page-card",
|
|
15
|
+
"css_vars": {},
|
|
16
|
+
"custom_style_map": {
|
|
17
|
+
"bg_color": "background-color",
|
|
18
|
+
"radius": "border-radius",
|
|
19
|
+
"border_color": "border-color",
|
|
20
|
+
"padding_x": "padding-inline",
|
|
21
|
+
"padding_y": "padding-block",
|
|
22
|
+
"box_shadow": "box-shadow"
|
|
23
|
+
},
|
|
24
|
+
"priority": {
|
|
25
|
+
"strategy": "scope_qualified",
|
|
26
|
+
"reason": "设计层文件以 .vts-page-card 作用域限定即可覆盖出厂卡片默认样式。"
|
|
27
|
+
},
|
|
28
|
+
"$note": "列表页主卡片容器(crud-pages L1 样板 .vts-page-card)。registry §11.24 六项均为 always,变更集必须声明;bg_color/radius/border_color/box_shadow 为视觉,padding_x/padding_y 为卡片内边距(卡片本身内边距归零时由页面内容点位自行内缩)。字段名严格对齐 restore-registry 的 dim,禁止改用 border_radius/shadow/padding 等旧词(那是「声明了落不下去」的头号成因)。"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "全局原子层 · 分页组件映射(EP el-pagination / RePagination 根节点即 el-pagination)。registry list-page §11.83-11.94 登记的 always 子项 height/radius/hover_color/icon_size/gap/text_color/active_bg/active_color/border_color。样式规则经 src/styles/design-shell.scss 落在 .vts-page-card .el-pagination(设计层文件,非出厂源码)。字段名严格对齐 restore-registry 的 dim(parser 逐项校验;registry 11.88 原为 button_hover_color,已对齐为 hover_color 以匹配 host admin.content.pagination 与变更集)。版本恒 1.0.0(由 SKILL.md 体系版本统一管理)。",
|
|
3
|
+
"meta": {
|
|
4
|
+
"layer": "basic",
|
|
5
|
+
"domain": "component_pagination",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"scene": "global",
|
|
8
|
+
"tech_stack": "vue3 + element-plus"
|
|
9
|
+
},
|
|
10
|
+
"mappings": {
|
|
11
|
+
"component.pagination.base": {
|
|
12
|
+
"type": "global_component",
|
|
13
|
+
"component": "ElPagination(RePagination 根节点即 el-pagination)",
|
|
14
|
+
"style_scope": ".vts-page-card .el-pagination",
|
|
15
|
+
"css_vars": {},
|
|
16
|
+
"custom_style_map": {
|
|
17
|
+
"height": "height",
|
|
18
|
+
"radius": "border-radius",
|
|
19
|
+
"hover_color": "color",
|
|
20
|
+
"icon_size": "font-size",
|
|
21
|
+
"gap": "gap",
|
|
22
|
+
"active_bg": "background-color",
|
|
23
|
+
"active_color": "color",
|
|
24
|
+
"border_color": "border-color",
|
|
25
|
+
"text_color": "color"
|
|
26
|
+
},
|
|
27
|
+
"priority": {
|
|
28
|
+
"strategy": "scope_qualified",
|
|
29
|
+
"reason": "作用域限定到 .vts-page-card .el-pagination 即可覆盖 EP 出厂分页样式。"
|
|
30
|
+
},
|
|
31
|
+
"$note": "registry §11.83-11.94 多项均为 always,变更集必须声明;hover_color 为分页整体悬停/激活文字色(对齐 host 的 hover_color 字段名);active_bg/active_color 为当前页按钮底色与文字色;border_color 为分页器边框;text_color/gap/icon_size 为整体文字、间距与翻页图标尺寸。字段名严格对齐 restore-registry 的 dim。"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"height": "height",
|
|
29
29
|
"radius": "border-radius",
|
|
30
30
|
"font_size": "font-size",
|
|
31
|
-
"padding_x": "padding"
|
|
31
|
+
"padding_x": "padding",
|
|
32
|
+
"icon_size": "font-size"
|
|
32
33
|
},
|
|
33
34
|
"$note": "状态语义色走 EP 功能色变量:success=--el-color-success / processing=--el-color-primary / warning=--el-color-warning / error=--el-color-danger。列级声明机制:component.tag.status 是 :root 全局默认,逐列差异必须声明为内容点位(admin.content.table.cell_tag.<列语义> 走 pending/L3,或写入该列 notes),禁止对全局 ID 声明多份互相覆盖的 form"
|
|
34
35
|
},
|
|
@@ -43,7 +43,11 @@
|
|
|
43
43
|
"desc_color": "--page-desc-color",
|
|
44
44
|
"actions_gap": "--page-header-actions-gap"
|
|
45
45
|
},
|
|
46
|
-
"custom_style_map": {
|
|
46
|
+
"custom_style_map": {
|
|
47
|
+
"padding_y": "padding-block",
|
|
48
|
+
"padding_x": "padding-inline",
|
|
49
|
+
"text_color": "color"
|
|
50
|
+
}
|
|
47
51
|
},
|
|
48
52
|
"admin.content.filter_area": {
|
|
49
53
|
"type": "element",
|
|
@@ -58,12 +62,19 @@
|
|
|
58
62
|
"bg": "--filter-area-bg",
|
|
59
63
|
"border_bottom": "--filter-area-border-bottom"
|
|
60
64
|
},
|
|
61
|
-
"custom_style_map": {
|
|
65
|
+
"custom_style_map": {
|
|
66
|
+
"gap": "gap",
|
|
67
|
+
"text_color": "color",
|
|
68
|
+
"font_size": "font-size",
|
|
69
|
+
"text_align": "text-align",
|
|
70
|
+
"icon_size": "font-size",
|
|
71
|
+
"border_color": "border-color"
|
|
72
|
+
}
|
|
62
73
|
},
|
|
63
74
|
"admin.content.table.operation_bar": {
|
|
64
75
|
"type": "element",
|
|
65
76
|
"selector": ".vts-action-bar",
|
|
66
|
-
"file": "
|
|
77
|
+
"file": "出厂 src/components/ReTableBar/src/bar.vue 的工具栏行(标题/按钮/工具三件套所在行)已挂 .vts-action-bar;右侧工具三件套源码实证:刷新 svg-icon + el-dropdown 密度(宽松/默认/紧凑)+ el-popover 列设置(bar.vue 内层行)",
|
|
67
78
|
"style_scope": ".vts-page-card",
|
|
68
79
|
"forms": {
|
|
69
80
|
"with_tools": "工具三件套(刷新/密度/列设置)齐全——设计规范 list-page §4 要求三件套缺一不可(ReTableBar 出厂已具备,此为默认形态)",
|
|
@@ -81,18 +92,19 @@
|
|
|
81
92
|
"batch_disabled_opacity": "opacity"
|
|
82
93
|
},
|
|
83
94
|
"anchors": [
|
|
84
|
-
{ "kind": "class", "layer": "
|
|
95
|
+
{ "kind": "class", "layer": "inner", "target": ".vts-action-bar" },
|
|
85
96
|
{ "kind": "class", "layer": "inner", "target": ".vts-action-bar .el-button" },
|
|
86
97
|
{ "kind": "css_var", "target": "--action-bar-gap" },
|
|
87
98
|
{ "kind": "css_var", "target": "--action-bar-padding-y" }
|
|
88
99
|
],
|
|
89
100
|
"preconditions": [
|
|
90
|
-
"
|
|
91
|
-
"
|
|
101
|
+
"挂载点唯一合法位置 = ReTableBar 内部工具栏行(出厂已挂 .vts-action-bar)。禁止把 .vts-action-bar 挂到 ReTableBar 根节点:根节点是「工具栏行 + 表格 + 分页」的纵向复合容器,而 .vts-action-bar 是 flex-direction: row —— 挂根节点会让工具栏与表格并排、表格被挤压、tableHeight 实测失准(已发生的事故,勿复发)。",
|
|
102
|
+
"本条目 sid 锚点只能落在 ReTableBar 根节点(页面透传 attrs 到根),样式落点是内层工具栏行 —— anchors 的 layer 必须区分 host / inner,verify 抽取按 anchors.target 而非 sid 所在节点。",
|
|
103
|
+
"gap / padding 的 CSS 变量必须在项目样式中存在消费者(var() 引用),只定义不消费 = 死通道。--action-bar-padding-y 供 padding-block,最多两个值(如 20px 8px),给三个值整条声明即失效。"
|
|
92
104
|
],
|
|
93
105
|
"priority": {
|
|
94
106
|
"strategy": "scope_qualified",
|
|
95
|
-
"reason": "
|
|
107
|
+
"reason": "出厂 .vts-action-bar 类位 1,作用域限定(html body .vts-table-area .vts-action-bar)即可覆盖;但不得把样式写到 ReTableBar 根节点上。"
|
|
96
108
|
},
|
|
97
109
|
"$note": "设计意图(list-page §4/§11.25-11.36):flex 两端对齐、pad 20px 20px 8px、左侧批量(未选中置灰 opacity 0.4 + not-allowed)、右侧工具三件套缺一不可。分工:本条目管容器布局与置灰;批量删除红色按钮本体走 component.button.danger。demo 噪音按钮去留属业务层,交付说明申报后由项目侧业务闭环移除"
|
|
98
110
|
},
|
|
@@ -119,7 +131,13 @@
|
|
|
119
131
|
"divider_height": "height",
|
|
120
132
|
"divider_margin_x": "margin-inline",
|
|
121
133
|
"more_arrow_size": "font-size",
|
|
122
|
-
"more_arrow_gap": "gap"
|
|
134
|
+
"more_arrow_gap": "gap",
|
|
135
|
+
"vertical_align": "vertical-align",
|
|
136
|
+
"font_size": "font-size",
|
|
137
|
+
"gap": "gap",
|
|
138
|
+
"bg": "background-color",
|
|
139
|
+
"box_shadow": "box-shadow",
|
|
140
|
+
"radius": "border-radius"
|
|
123
141
|
},
|
|
124
142
|
"anchors": [
|
|
125
143
|
{ "kind": "class", "layer": "host", "target": ".vts-table-area .el-table__cell:has(.re-table-operate)" },
|
|
@@ -151,7 +169,9 @@
|
|
|
151
169
|
"font_size": "font-size",
|
|
152
170
|
"text_align": "text-align",
|
|
153
171
|
"border_bottom": "border-bottom",
|
|
154
|
-
"nowrap": "white-space"
|
|
172
|
+
"nowrap": "white-space",
|
|
173
|
+
"gap": "gap",
|
|
174
|
+
"icon_size": "font-size"
|
|
155
175
|
},
|
|
156
176
|
"anchors": [
|
|
157
177
|
{ "kind": "class", "layer": "host", "target": ".vts-table-area .el-table__header th.el-table__cell" },
|
|
@@ -297,7 +317,9 @@
|
|
|
297
317
|
"header_text": "--el-table-header-text-color",
|
|
298
318
|
"row_hover_bg": "--el-table-row-hover-bg-color"
|
|
299
319
|
},
|
|
300
|
-
"custom_style_map": {
|
|
320
|
+
"custom_style_map": {
|
|
321
|
+
"bg_color": "background-color"
|
|
322
|
+
}
|
|
301
323
|
},
|
|
302
324
|
"admin.content.pagination": {
|
|
303
325
|
"type": "component",
|
|
@@ -311,7 +333,14 @@
|
|
|
311
333
|
"active_bg": "--pagination-active-bg",
|
|
312
334
|
"active_color": "--pagination-active-color"
|
|
313
335
|
},
|
|
314
|
-
"custom_style_map": {
|
|
336
|
+
"custom_style_map": {
|
|
337
|
+
"margin_bottom": "margin-bottom",
|
|
338
|
+
"padding_y": "padding-block",
|
|
339
|
+
"gap": "gap",
|
|
340
|
+
"text_color": "color",
|
|
341
|
+
"font_size": "font-size",
|
|
342
|
+
"border_color": "border-color"
|
|
343
|
+
}
|
|
315
344
|
},
|
|
316
345
|
"admin.content.empty_state": {
|
|
317
346
|
"type": "element",
|
|
@@ -54,11 +54,11 @@
|
|
|
54
54
|
"file": "src/layout/components/lay-sidebar/NavVertical.vue",
|
|
55
55
|
"style_scope": ".sidebar-container",
|
|
56
56
|
"forms": {
|
|
57
|
-
"pill": "
|
|
58
|
-
"indicator_left": "左侧竖条指示:先在本作用域覆写 --vts-theme-menu-active-bg: transparent 关胶囊,再于设计层新建 ::after 竖条(left:0)消费 --vts-theme-menu-active-before",
|
|
59
|
-
"indicator_right": "右侧竖条指示:同上关胶囊后 ::after 挂 right:0
|
|
60
|
-
"indicator_underline": "底部横线指示:关胶囊后 ::after 挂 bottom:0(宽取 100% 或指定宽度,厚取 indicator_thickness
|
|
61
|
-
"none": "
|
|
57
|
+
"pill": "整块胶囊底色高亮(sidebar.scss 消费 --vts-theme-menu-active-bg,带 !important)。suppress 必含 right_indicator_legacy——出厂 element-plus.scss 的 .el-menu-item.is-active{border-right:var(--menu-active-border-right)} 是活通道,不收口会出现左右两根竖条并存",
|
|
58
|
+
"indicator_left": "左侧竖条指示:先在本作用域覆写 --vts-theme-menu-active-bg: transparent 关胶囊,再于设计层新建 ::after 竖条(left:0)消费 --vts-theme-menu-active-before。suppress 必含 right_indicator_legacy",
|
|
59
|
+
"indicator_right": "右侧竖条指示:同上关胶囊后 ::after 挂 right:0。出厂右竖条通道 --menu-active-border-right(element-plus.scss 消费、design-tokens.scss 定义为 3px solid 品牌色)是活通道,可复用也可收口后自建,二选一必须显式声明",
|
|
60
|
+
"indicator_underline": "底部横线指示:关胶囊后 ::after 挂 bottom:0(宽取 100% 或指定宽度,厚取 indicator_thickness)。suppress 必含 right_indicator_legacy",
|
|
61
|
+
"none": "无指示:胶囊与竖条均关闭,仅文字变色。suppress 必含 right_indicator_legacy"
|
|
62
62
|
},
|
|
63
63
|
"css_vars": {
|
|
64
64
|
"menu_bg": "--vts-theme-menu-bg",
|
|
@@ -69,13 +69,18 @@
|
|
|
69
69
|
"sub_menu_active_text": "--vts-theme-sub-menu-active-text",
|
|
70
70
|
"menu_active_bg": "--vts-theme-menu-active-bg",
|
|
71
71
|
"menu_active_indicator": "--vts-theme-menu-active-before",
|
|
72
|
+
"right_indicator_legacy": "--menu-active-border-right",
|
|
72
73
|
"sidebar_border": "--vts-sidebar-border-color",
|
|
73
74
|
"item_height": "--el-menu-item-height"
|
|
74
75
|
},
|
|
75
76
|
"custom_style_map": {
|
|
76
77
|
"active_indicator_width": "width",
|
|
77
78
|
"active_indicator_thickness": "height",
|
|
78
|
-
"active_indicator_style": "border-radius"
|
|
79
|
+
"active_indicator_style": "border-radius",
|
|
80
|
+
"padding_y": "padding-block",
|
|
81
|
+
"font_size": "font-size",
|
|
82
|
+
"font_weight": "font-weight",
|
|
83
|
+
"text_color": "color"
|
|
79
84
|
},
|
|
80
85
|
"anchors": [
|
|
81
86
|
{ "kind": "class", "layer": "host", "target": ".sidebar-container .el-menu-item" },
|
|
@@ -132,7 +137,9 @@
|
|
|
132
137
|
},
|
|
133
138
|
"custom_style_map": {
|
|
134
139
|
"bg": "background-color",
|
|
135
|
-
"box_shadow": "box-shadow"
|
|
140
|
+
"box_shadow": "box-shadow",
|
|
141
|
+
"gap": "gap",
|
|
142
|
+
"border_color": "border-color"
|
|
136
143
|
}
|
|
137
144
|
},
|
|
138
145
|
"admin.layout.header.logo_area": {
|
|
@@ -190,7 +197,8 @@
|
|
|
190
197
|
"custom_style_map": {
|
|
191
198
|
"icon_size": "font-size",
|
|
192
199
|
"gap": "gap",
|
|
193
|
-
"text_font_size": "font-size"
|
|
200
|
+
"text_font_size": "font-size",
|
|
201
|
+
"text_color": "color"
|
|
194
202
|
},
|
|
195
203
|
"$note": "inline_switch 并排切换形态:下拉项平铺为触发器旁切换组,按 v-if 保形切换增量插入,不删原代码"
|
|
196
204
|
},
|
|
@@ -227,7 +235,8 @@
|
|
|
227
235
|
"hover_bg": "--el-fill-color-light"
|
|
228
236
|
},
|
|
229
237
|
"custom_style_map": {
|
|
230
|
-
"icon_size": "font-size"
|
|
238
|
+
"icon_size": "font-size",
|
|
239
|
+
"width": "width"
|
|
231
240
|
}
|
|
232
241
|
},
|
|
233
242
|
"admin.layout.header.setting_button": {
|
|
@@ -241,7 +250,9 @@
|
|
|
241
250
|
},
|
|
242
251
|
"custom_style_map": {
|
|
243
252
|
"icon_size": "font-size",
|
|
244
|
-
"width": "width"
|
|
253
|
+
"width": "width",
|
|
254
|
+
"hover_bg": "background-color",
|
|
255
|
+
"text_color": "color"
|
|
245
256
|
},
|
|
246
257
|
"$note": "存在性收口默认对象:效果图未出现该按钮时,变更集以 visible:false 声明 → 落地为设计层文件内 .navbar .set-icon { display:none }(禁止删出厂代码行、禁止直接改 lay-navbar/index.vue 表达「这张图不要按钮」)。反向:设计需要该按钮时不声明即可(出厂已常显)。同一 DOM(含 v-tippy 提示)通用,图标/尺寸经本条目 style 字段动态覆盖。"
|
|
247
258
|
},
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "
|
|
2
|
+
"$comment": " 三声明维度正例(apply_via / layer / structure_ops)+ coverage 覆盖率记账。预期:match exit 0;输出含「结构施工 structure_ops」「覆写优先级 priority」「inner 层」「覆盖率 coverage」且覆盖率校验通过(C = A、gaps 为空)。",
|
|
3
3
|
"schema": "design.changeset/1.0",
|
|
4
4
|
"changeset_version": "1.0.0",
|
|
5
5
|
"mapping_version": "1.0.0",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"covered": 3,
|
|
60
60
|
"gaps": []
|
|
61
61
|
},
|
|
62
|
-
"notes": "本夹具只用于回归
|
|
62
|
+
"notes": "本夹具只用于回归 三个声明维度的解析与输出,不是真实设计交付件。"
|
|
63
63
|
}
|
package/parser/index.js
CHANGED
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
* node parser/index.js match --batch <dir> # 项目级批量匹配目录下全部变更集
|
|
19
19
|
* node parser/index.js list [--scene admin] [--verbose] # 列出全部语义 ID(--verbose 含字段与形态)
|
|
20
20
|
* node parser/index.js query <semantic.id> # 查询单个 ID 映射详情
|
|
21
|
-
* node parser/index.js audit --project <dir> [<cs…>] # 挂载点存在性 +
|
|
22
|
-
* node parser/index.js verify --oracle <o> --actual <a> # 渲染态逐点验收:computed style 期望 vs 实测 diff
|
|
23
|
-
* node parser/index.js registry <registry.json> # 登记表通道核验:登记项 sid / dims
|
|
21
|
+
* node parser/index.js audit --project <dir> [<cs…>] # 挂载点存在性 + 死通道静态审计()
|
|
22
|
+
* node parser/index.js verify --oracle <o> --actual <a> # 渲染态逐点验收:computed style 期望 vs 实测 diff()
|
|
23
|
+
* node parser/index.js registry <registry.json> # 登记表通道核验:登记项 sid / dims 是否在词典有落点()
|
|
24
24
|
* node parser/watch.js # 开发态监听 mapping/ 自动重编译(§3.4.3)
|
|
25
25
|
*/
|
|
26
26
|
|
|
@@ -41,20 +41,20 @@ const QUALITATIVE_RE = /^(中等|加粗|常规|细|粗|小圆角|全圆角|直
|
|
|
41
41
|
const NUMERIC_VALUE_RE = /^\d+(\.\d+)?(px|rem|em|%|vh|vw|pt)$/i;
|
|
42
42
|
/** 复合样式字面量:含空格的多段值(如 1px solid #F0F0F0)按已消歧处理(hex 已被禁词校验限定位置) */
|
|
43
43
|
const COMPOSITE_VALUE_RE = /\s/;
|
|
44
|
-
/**
|
|
44
|
+
/** 落点层级枚举(与词典 validator 的 LAYER_ENUM 一致) */
|
|
45
45
|
const LAYER_VALUES = ["host", "inner"];
|
|
46
46
|
/** 语义 ID 严格格式(apply_via 锚点名须符合) */
|
|
47
47
|
const ID_RE_STRICT = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*){1,3}$/;
|
|
48
48
|
|
|
49
|
-
/**
|
|
49
|
+
/** audit:审计时跳过的目录(依赖 / 产物 / 缓存) */
|
|
50
50
|
const AUDIT_SKIP_DIRS = new Set(["node_modules", ".git", "dist", "build", ".output", ".vite", ".nuxt", "coverage", "public"]);
|
|
51
|
-
/**
|
|
51
|
+
/** audit:「模板 / 脚本」扩展名:命中 = 结构挂载 */
|
|
52
52
|
const STRUCT_EXT = new Set([".vue", ".html", ".htm", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
53
|
-
/**
|
|
53
|
+
/** audit:「样式」扩展名:只命中样式 = 仅样式定义、无结构挂载 */
|
|
54
54
|
const STYLE_EXT = new Set([".scss", ".sass", ".css", ".less", ".styl"]);
|
|
55
|
-
/**
|
|
55
|
+
/** audit:设计层文件特征(只命中设计层 = 无实际挂载) */
|
|
56
56
|
const DESIGN_LAYER_RE = /design-shell|design-layer|design\.scss/i;
|
|
57
|
-
/**
|
|
57
|
+
/** audit:组件库运行时渲染的裸类名(无 el- 前缀,但不由业务源码挂载) */
|
|
58
58
|
const BUILTIN_BARE_CLASSES = new Set(["cell", "cell-group", "row", "header", "body", "caret-wrapper", "sort-caret", "ascending", "descending", "expanded-cell", "el-tooltip", "text", "value", "label"]);
|
|
59
59
|
|
|
60
60
|
main();
|
|
@@ -103,9 +103,9 @@ function printHelp() {
|
|
|
103
103
|
node parser/index.js match --batch <dir> 项目级批量匹配:目录下全部变更集 + 跨文件汇总
|
|
104
104
|
node parser/index.js audit --project <dir> [<cs.json…>] 挂载点存在性 + 死通道静态审计(需目标项目源码)
|
|
105
105
|
node parser/index.js verify --oracle <o.json> --actual <a.json> [--sids a,b]
|
|
106
|
-
渲染态逐点验收:computed style 期望 vs 实测 diff
|
|
106
|
+
渲染态逐点验收:computed style 期望 vs 实测 diff()
|
|
107
107
|
node parser/index.js registry <registry.json> [--verbose]
|
|
108
|
-
登记表通道核验:登记项 sid 是否在词典、dims
|
|
108
|
+
登记表通道核验:登记项 sid 是否在词典、dims 是否有落点()
|
|
109
109
|
node parser/index.js list [--scene admin] [--verbose] 列出全部语义 ID(--verbose 含字段与形态,供下发词汇约束)
|
|
110
110
|
node parser/index.js query <semantic.id> 查询单个 ID 的映射详情
|
|
111
111
|
node parser/watch.js 开发态监听 mapping/ 变更自动重编译
|
|
@@ -331,7 +331,7 @@ function matchOne(file, dataset, batchSummary, opts = {}) {
|
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
// oracle
|
|
334
|
+
// oracle 验收基线(:设计侧给的效果图 + 待比对点位;项目侧落地后跑 verify 逐点 diff)
|
|
335
335
|
checkOracle(changeset, plan, valueDict);
|
|
336
336
|
checkCoverage(changeset);
|
|
337
337
|
// 登记表覆盖率(子项级细闸):以登记表为权威、当场重算 A/C,设计侧自报的 coverage 不参与
|
|
@@ -430,7 +430,7 @@ function checkBannedWords(changeset) {
|
|
|
430
430
|
scan(`${label}.form`, c.form);
|
|
431
431
|
if (c.id)
|
|
432
432
|
scan(`${label}.id`, c.id);
|
|
433
|
-
//
|
|
433
|
+
// 三个声明维度:禁词扫描 + 结构校验(apply_via / layer / structure_ops)
|
|
434
434
|
if (c.apply_via !== undefined && c.apply_via !== null)
|
|
435
435
|
scan(`${label}.apply_via`, c.apply_via);
|
|
436
436
|
if (typeof c.layer === "string")
|
|
@@ -525,7 +525,7 @@ function printStyleTranslation(entry, change, idLabel, fieldPending, valueDict)
|
|
|
525
525
|
lines.push(` . ${field}: ${valueLabel} → var 覆盖 ${entry.css_vars[field]}(@ ${entry.style_scope})`);
|
|
526
526
|
}
|
|
527
527
|
else if (entry.custom_style_map && entry.custom_style_map[field]) {
|
|
528
|
-
//
|
|
528
|
+
// :按变更集 layer 指认落点(host 宿主盒 / inner 内层文本盒),从词典 anchors 取真实选择器
|
|
529
529
|
const spot = resolveAnchorTarget(entry, field, layerOf(change, field));
|
|
530
530
|
const layerLabel = spot.layer ? ` · ${spot.layer} 层` : "";
|
|
531
531
|
lines.push(` . ${field}: ${valueLabel} → 自定义 ${entry.custom_style_map[field]}(@ ${spot.target}${layerLabel})`);
|
|
@@ -547,7 +547,7 @@ function printStyleTranslation(entry, change, idLabel, fieldPending, valueDict)
|
|
|
547
547
|
}
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
-
// ----
|
|
550
|
+
// ---- · 落点 / 结构施工 / 优先级 解析 ----
|
|
551
551
|
|
|
552
552
|
/** 取字段的落点层级:change.layer 支持字符串(整条生效)或对象(按字段指认) */
|
|
553
553
|
function layerOf(change, field) {
|
|
@@ -623,7 +623,7 @@ function printApplyPlan(entry, change, idLabel, index) {
|
|
|
623
623
|
}
|
|
624
624
|
|
|
625
625
|
/**
|
|
626
|
-
* 覆写优先级 →
|
|
626
|
+
* 覆写优先级 → 落地写法要求()
|
|
627
627
|
* 该维度不是「提示」,是硬要求:写错写法 = 规则写了也不生效(同权重被组件 scoped 后注入覆盖,或被出厂 !important 压制)。
|
|
628
628
|
*/
|
|
629
629
|
function priorityRequirement(strategy) {
|
|
@@ -640,7 +640,7 @@ function priorityRequirement(strategy) {
|
|
|
640
640
|
}
|
|
641
641
|
|
|
642
642
|
/**
|
|
643
|
-
* oracle
|
|
643
|
+
* oracle 验收基线校验()
|
|
644
644
|
* 两类事故都出在「基线本身不可用」,而不是落地写法:
|
|
645
645
|
* ① 主题错配:效果图是 A 主题、变更集是 B 主题 → 逐点比对必然全红(搬错基线)。
|
|
646
646
|
* ② 覆盖度缺口:效果图里有、changes[] 却未声明的点位 → 永远不可能被还原(欠声明);
|
|
@@ -777,7 +777,7 @@ function registrySids(item) {
|
|
|
777
777
|
const GLOBAL_PSEUDO_ID = "global";
|
|
778
778
|
|
|
779
779
|
/**
|
|
780
|
-
*
|
|
780
|
+
* 登记表覆盖率(子项级细闸,)
|
|
781
781
|
* 组级台账(restore-checklist)只能防「整组忘光」;组内子项是否被静默丢失,必须由登记表
|
|
782
782
|
* (规范里每条带样式结论的子项 → 一条登记项)来计数。这里以登记表为权威**当场重算**:
|
|
783
783
|
* 适用 A = always 子项 ∪ 效果图已标注同名 data-sid 的子项
|
|
@@ -869,7 +869,7 @@ function checkRegistryCoverage(changeset, plan, opts = {}) {
|
|
|
869
869
|
}
|
|
870
870
|
|
|
871
871
|
/**
|
|
872
|
-
*
|
|
872
|
+
* 登记表通道核验()
|
|
873
873
|
* 与 match 的覆盖率校验互补:不需要变更集,直接拿登记表对词典,回答一件事——
|
|
874
874
|
* 「这张登记表里的必登项,有多少在项目侧真有承载字段」。这是 1:1 对接的**通道缺口清单**:
|
|
875
875
|
* · sid 词典无此 ID 且未标 pending → 硬缺口(登记表引用了不存在的点位,exit 1)
|
|
@@ -1062,7 +1062,7 @@ function checkApplyFields(change, label, violations) {
|
|
|
1062
1062
|
}
|
|
1063
1063
|
}
|
|
1064
1064
|
|
|
1065
|
-
// ---- audit:挂载点存在性 +
|
|
1065
|
+
// ---- audit:挂载点存在性 + 死通道(,静态审计,需目标项目源码) ----
|
|
1066
1066
|
// 本节的模块级常量(AUDIT_SKIP_DIRS / STRUCT_EXT / STYLE_EXT / DESIGN_LAYER_RE /
|
|
1067
1067
|
// BUILTIN_BARE_CLASSES)已在文件顶部声明——模块级常量必须在 main() 调用前初始化,勿下移。
|
|
1068
1068
|
|
|
@@ -1267,7 +1267,7 @@ function cmdAudit(args, dataset) {
|
|
|
1267
1267
|
}
|
|
1268
1268
|
}
|
|
1269
1269
|
|
|
1270
|
-
// ---- verify:渲染态逐点验收(
|
|
1270
|
+
// ---- verify:渲染态逐点验收( 补丁 3 · 闭环验收回路) ----
|
|
1271
1271
|
/**
|
|
1272
1272
|
* 比对两份 computed style 转储:oracle(效果图期望)vs actual(项目实测)。
|
|
1273
1273
|
* 转储格式:{ "<语义ID>": { "<css属性>": "<值>", ... }, ... }
|
|
@@ -1495,7 +1495,7 @@ function cmdList(args, dataset) {
|
|
|
1495
1495
|
console.log(` style 字段:${fields.join(" ")}`);
|
|
1496
1496
|
if (forms.length > 0)
|
|
1497
1497
|
console.log(` form 形态:${forms.join(" / ")}`);
|
|
1498
|
-
//
|
|
1498
|
+
// :落点层级与覆写优先级(设计侧声明 layer / 项目侧选提权策略时可见)
|
|
1499
1499
|
const anchors = Array.isArray(e.anchors) ? e.anchors : [];
|
|
1500
1500
|
const layers = [...new Set(anchors.filter(a => a.kind === "class" && a.layer).map(a => a.layer))];
|
|
1501
1501
|
if (layers.length > 0 || (e.priority && e.priority.strategy))
|
package/parser/regression.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* G match 旧协议兼容 → exit 0 且输出含 ⚠ 告警
|
|
18
18
|
* H match 整页场景还原样例 → exit 0 且输出含 #245BFF(壳层+内容区全模块 L1)
|
|
19
19
|
* I build --dry 产物链自检 → exit 0 且输出含 dry-run
|
|
20
|
-
* J match
|
|
20
|
+
* J match 三声明维度 → exit 0 且输出含「结构施工 structure_ops」
|
|
21
21
|
* K audit 挂载点 / 死通道审计 → exit 1(夹具项目故意存在挂载点缺失 / 死通道)
|
|
22
22
|
* L verify 渲染态逐点验收 → exit 1 且三类归因各计其数(夹具含故意缺口)
|
|
23
23
|
* M match 登记表覆盖率细闸 → exit 1(夹具故意欠声明两条恒存在子项)
|
|
@@ -112,7 +112,7 @@ const steps = [
|
|
|
112
112
|
},
|
|
113
113
|
{
|
|
114
114
|
key: "J",
|
|
115
|
-
name: "match
|
|
115
|
+
name: "match 三声明维度 + coverage 覆盖率(apply_via / layer / structure_ops / coverage)",
|
|
116
116
|
script: INDEX,
|
|
117
117
|
args: ["match", path.join(FIXTURES, "changeset-v32-fields.json")],
|
|
118
118
|
expect: { code: 0, includes: ["结构施工 structure_ops", "验收基线 oracle", "覆盖率 coverage"] },
|
package/parser/validator.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* 1. 字段完整性(必须字段存在且类型正确)
|
|
6
6
|
* 2. 枚举合法性(type/forms 值域)
|
|
7
7
|
* 3. 层级一致性(children 引用的 ID 必须存在于同级或同场景映射集)
|
|
8
|
-
* 4.
|
|
8
|
+
* 4. 三字段结构:anchors(kind/layer 枚举 + target 必填)、
|
|
9
9
|
* preconditions(非空字符串数组)、priority(strategy 枚举)
|
|
10
10
|
*
|
|
11
11
|
* 说明:selector / anchors.target 的「挂载点存在性」需要在**目标项目源码**里查证,
|
|
@@ -101,7 +101,7 @@ export function validateMappingDataset(dataset) {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
// anchors(
|
|
104
|
+
// anchors( §3.2):条目可承载的全部通道,含落点层级 layer
|
|
105
105
|
if (entry.anchors !== undefined) {
|
|
106
106
|
if (!Array.isArray(entry.anchors)) {
|
|
107
107
|
errors.push(`[${file}] ${id}.anchors 必须为数组`);
|
|
@@ -130,7 +130,7 @@ export function validateMappingDataset(dataset) {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
// preconditions(
|
|
133
|
+
// preconditions( §3.2):几何 / 取值成立的宿主前提,非空字符串数组
|
|
134
134
|
if (entry.preconditions !== undefined) {
|
|
135
135
|
if (!Array.isArray(entry.preconditions) || entry.preconditions.length === 0) {
|
|
136
136
|
errors.push(`[${file}] ${id}.preconditions 必须为非空字符串数组`);
|
|
@@ -143,7 +143,7 @@ export function validateMappingDataset(dataset) {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
// priority(
|
|
146
|
+
// priority( §4.6.4):覆写优先级策略
|
|
147
147
|
if (entry.priority !== undefined) {
|
|
148
148
|
if (typeof entry.priority !== "object" || entry.priority === null) {
|
|
149
149
|
errors.push(`[${file}] ${id}.priority 必须为对象`);
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "design.changeset/1.0",
|
|
3
|
+
"changeset_version": "1.0.0",
|
|
4
|
+
"mapping_version": "1.0.0",
|
|
5
|
+
"scene": "admin",
|
|
6
|
+
"layout_type": "vertical",
|
|
7
|
+
"global": {
|
|
8
|
+
"brand_primary": "钴蓝-5"
|
|
9
|
+
},
|
|
10
|
+
"changes": [
|
|
11
|
+
{
|
|
12
|
+
"id": "admin.layout.sidebar",
|
|
13
|
+
"style": {
|
|
14
|
+
"width": "208px",
|
|
15
|
+
"collapsed_width": "64px",
|
|
16
|
+
"bg": "#001529"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "admin.layout.sidebar.logo_area",
|
|
21
|
+
"style": {
|
|
22
|
+
"height": "54px",
|
|
23
|
+
"title_font_size": "16px",
|
|
24
|
+
"title_font_weight": "中等",
|
|
25
|
+
"title_color": "#FFFFFF"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "admin.layout.sidebar.menu",
|
|
30
|
+
"form": "pill",
|
|
31
|
+
"style": {
|
|
32
|
+
"padding_y": "8px",
|
|
33
|
+
"item_height": "40px",
|
|
34
|
+
"font_size": "14px",
|
|
35
|
+
"font_weight": "常规",
|
|
36
|
+
"text_color": "rgba(255,255,255,0.65)",
|
|
37
|
+
"menu_hover_bg": "rgba(255,255,255,0.08)",
|
|
38
|
+
"menu_active_bg": "钴蓝-5",
|
|
39
|
+
"menu_active_indicator": "钴蓝-5"
|
|
40
|
+
},
|
|
41
|
+
"priority": { "strategy": "deep_qualified" }
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "admin.layout.sidebar.collapse_trigger",
|
|
45
|
+
"visible": false
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "admin.layout.header",
|
|
49
|
+
"style": {
|
|
50
|
+
"height": "54px",
|
|
51
|
+
"padding_x": "24px",
|
|
52
|
+
"bg": "#FFFFFF",
|
|
53
|
+
"border_color": "#F0F0F0"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "admin.layout.header.collapse_trigger",
|
|
58
|
+
"form": "header_inline",
|
|
59
|
+
"style": {
|
|
60
|
+
"btn_width": "40px",
|
|
61
|
+
"btn_height": "40px",
|
|
62
|
+
"icon_size": "16px",
|
|
63
|
+
"border_radius": "6px"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "admin.layout.header.logo_area",
|
|
68
|
+
"visible": false
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "admin.layout.header.breadcrumb",
|
|
72
|
+
"visible": false,
|
|
73
|
+
"priority": { "strategy": "deep_qualified" }
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "admin.layout.header.lang_switch",
|
|
77
|
+
"form": "inline_switch",
|
|
78
|
+
"style": {
|
|
79
|
+
"gap": "2px",
|
|
80
|
+
"icon_size": "16px",
|
|
81
|
+
"text_color": "#000000A6"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "admin.layout.header.fullscreen",
|
|
86
|
+
"style": {
|
|
87
|
+
"icon_size": "16px",
|
|
88
|
+
"width": "32px"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "admin.layout.header.setting_button",
|
|
93
|
+
"style": {
|
|
94
|
+
"icon_size": "16px",
|
|
95
|
+
"hover_bg": "#FAFAFA",
|
|
96
|
+
"text_color": "#000000A6"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "admin.layout.header.user_profile",
|
|
101
|
+
"form": "greeting_avatar_name",
|
|
102
|
+
"style": {
|
|
103
|
+
"avatar_width": "28px",
|
|
104
|
+
"avatar_height": "28px",
|
|
105
|
+
"avatar_radius": "9999px",
|
|
106
|
+
"name_font_size": "14px",
|
|
107
|
+
"name_font_weight": "中等",
|
|
108
|
+
"greeting_font_size": "14px",
|
|
109
|
+
"gap": "12px",
|
|
110
|
+
"text_color": "#000000E6",
|
|
111
|
+
"hover_bg": "#FAFAFA"
|
|
112
|
+
},
|
|
113
|
+
"structure_ops": [{ "op": "add_node", "node": "问候区" }]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"id": "admin.layout.tabs",
|
|
117
|
+
"form": "flat",
|
|
118
|
+
"style": {
|
|
119
|
+
"height": "40px",
|
|
120
|
+
"bg": "#FFFFFF",
|
|
121
|
+
"border_bottom": "1px solid #F0F0F0",
|
|
122
|
+
"padding_inline": "0px"
|
|
123
|
+
},
|
|
124
|
+
"priority": { "strategy": "deep_qualified" }
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "admin.layout.tabs.home_tab",
|
|
128
|
+
"form": "icon_only",
|
|
129
|
+
"style": {
|
|
130
|
+
"width": "40px",
|
|
131
|
+
"height": "40px",
|
|
132
|
+
"icon_size": "16px",
|
|
133
|
+
"icon_color": "钴蓝-5"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "admin.layout.tabs.item",
|
|
138
|
+
"form": "text_only",
|
|
139
|
+
"style": {
|
|
140
|
+
"card_height": "40px",
|
|
141
|
+
"padding_x": "12px",
|
|
142
|
+
"title_gap": "6px",
|
|
143
|
+
"close_size": "12px",
|
|
144
|
+
"close_opacity": "0.45",
|
|
145
|
+
"close_hover_color": "#FF4D4F",
|
|
146
|
+
"divider_color": "#F0F0F0"
|
|
147
|
+
},
|
|
148
|
+
"priority": { "strategy": "deep_qualified" }
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"id": "admin.layout.tabs.item_active",
|
|
152
|
+
"form": "text_color_only",
|
|
153
|
+
"style": {
|
|
154
|
+
"text_color": "钴蓝-5",
|
|
155
|
+
"font_weight": "中等"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"id": "admin.layout.tabs.divider",
|
|
160
|
+
"style": {
|
|
161
|
+
"width": "1px",
|
|
162
|
+
"height": "100%",
|
|
163
|
+
"bg": "#F0F0F0",
|
|
164
|
+
"opacity": "1"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"id": "admin.layout.tabs.context_menu",
|
|
169
|
+
"style": {
|
|
170
|
+
"width": "120px",
|
|
171
|
+
"border_color": "#F0F0F0",
|
|
172
|
+
"radius": "6px"
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"id": "admin.content.container",
|
|
177
|
+
"form": "fixed"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": "admin.layout.content",
|
|
181
|
+
"style": {
|
|
182
|
+
"padding": "24px"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"id": "component.card.base",
|
|
187
|
+
"style": {
|
|
188
|
+
"bg_color": "#FFFFFF",
|
|
189
|
+
"radius": "8px",
|
|
190
|
+
"border_color": "transparent",
|
|
191
|
+
"box_shadow": "0 2px 8px rgba(0,0,0,0.06)",
|
|
192
|
+
"padding_x": "0px",
|
|
193
|
+
"padding_y": "0px"
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"id": "admin.content.page_header",
|
|
198
|
+
"style": {
|
|
199
|
+
"margin_bottom": "1px solid #F0F0F0",
|
|
200
|
+
"title_size": "20px",
|
|
201
|
+
"title_weight": "加粗",
|
|
202
|
+
"desc_size": "14px",
|
|
203
|
+
"desc_color": "#000000A6",
|
|
204
|
+
"actions_gap": "8px",
|
|
205
|
+
"padding_x": "20px",
|
|
206
|
+
"padding_y": "20px"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "admin.content.filter_area",
|
|
211
|
+
"style": {
|
|
212
|
+
"radius": "6px",
|
|
213
|
+
"padding_y": "20px",
|
|
214
|
+
"padding_x": "20px",
|
|
215
|
+
"margin_bottom": "1px solid #F0F0F0",
|
|
216
|
+
"bg": "#FFFFFF",
|
|
217
|
+
"border_color": "#F0F0F0",
|
|
218
|
+
"font_size": "14px",
|
|
219
|
+
"text_color": "#000000E6",
|
|
220
|
+
"text_align": "右对齐",
|
|
221
|
+
"icon_size": "16px",
|
|
222
|
+
"gap": "20px"
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "admin.content.table.operation_bar",
|
|
227
|
+
"style": {
|
|
228
|
+
"gap": "8px",
|
|
229
|
+
"padding_y": "20px 20px 8px",
|
|
230
|
+
"btn_height": "32px",
|
|
231
|
+
"btn_radius": "6px",
|
|
232
|
+
"btn_font_size": "14px",
|
|
233
|
+
"font_size": "14px",
|
|
234
|
+
"font_weight": "常规",
|
|
235
|
+
"text_color": "#000000E6"
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"id": "admin.content.table.area",
|
|
240
|
+
"style": {
|
|
241
|
+
"radius": "8px",
|
|
242
|
+
"header_bg": "#FAFAFA",
|
|
243
|
+
"header_text": "#000000E6",
|
|
244
|
+
"row_hover_bg": "#FAFAFA",
|
|
245
|
+
"bg_color": "#FFFFFF"
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"id": "admin.content.table.header_cell",
|
|
250
|
+
"layer": { "padding": "host", "text_align": "inner" },
|
|
251
|
+
"style": {
|
|
252
|
+
"height": "48px",
|
|
253
|
+
"padding": "16px",
|
|
254
|
+
"bg": "#FAFAFA",
|
|
255
|
+
"font_size": "14px",
|
|
256
|
+
"font_weight": "中等",
|
|
257
|
+
"text_color": "#000000E6",
|
|
258
|
+
"text_align": "左对齐",
|
|
259
|
+
"border_bottom": "1px solid #F0F0F0",
|
|
260
|
+
"nowrap": "禁止换行",
|
|
261
|
+
"gap": "8px",
|
|
262
|
+
"icon_size": "16px"
|
|
263
|
+
},
|
|
264
|
+
"priority": { "strategy": "self_plus_important" }
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"id": "admin.content.table.cell",
|
|
268
|
+
"layer": "host",
|
|
269
|
+
"style": {
|
|
270
|
+
"padding": "16px",
|
|
271
|
+
"height": "55px",
|
|
272
|
+
"font_size": "14px",
|
|
273
|
+
"font_weight": "常规",
|
|
274
|
+
"text_color": "#000000E6",
|
|
275
|
+
"border_bottom": "1px solid #F0F0F0",
|
|
276
|
+
"vertical_align": "居中",
|
|
277
|
+
"nowrap": "禁止换行"
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"id": "admin.content.table.cell_status",
|
|
282
|
+
"form": "filled",
|
|
283
|
+
"style": {
|
|
284
|
+
"bg": "#F6FFED",
|
|
285
|
+
"border_color": "#D9F7BE",
|
|
286
|
+
"text_color": "#52C41A",
|
|
287
|
+
"font_size": "12px",
|
|
288
|
+
"radius": "6px",
|
|
289
|
+
"icon_size": "16px"
|
|
290
|
+
},
|
|
291
|
+
"structure_ops": [{ "op": "render_branch", "node": "状态列" }]
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
"id": "admin.content.table.cell_amount",
|
|
295
|
+
"layer": "inner",
|
|
296
|
+
"style": {
|
|
297
|
+
"align": "右对齐"
|
|
298
|
+
},
|
|
299
|
+
"structure_ops": [{ "op": "bind_source", "node": "金额列", "source": "列类名" }]
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"id": "admin.content.table.operation_column",
|
|
303
|
+
"style": {
|
|
304
|
+
"link_color": "钴蓝-5",
|
|
305
|
+
"danger_color": "#FF4D4F",
|
|
306
|
+
"divider_color": "#F0F0F0",
|
|
307
|
+
"align": "居中",
|
|
308
|
+
"min_width": "160px",
|
|
309
|
+
"column_width": "160px",
|
|
310
|
+
"nowrap": "禁止换行",
|
|
311
|
+
"bg": "#FFFFFF",
|
|
312
|
+
"box_shadow": "-2px 0 4px rgba(0,0,0,0.06)",
|
|
313
|
+
"font_size": "14px",
|
|
314
|
+
"gap": "8px",
|
|
315
|
+
"radius": "6px",
|
|
316
|
+
"vertical_align": "居中"
|
|
317
|
+
},
|
|
318
|
+
"structure_ops": [
|
|
319
|
+
{ "op": "render_branch", "node": "操作列图标" },
|
|
320
|
+
{ "op": "add_node", "node": "操作列分隔线" }
|
|
321
|
+
]
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"id": "admin.content.pagination",
|
|
325
|
+
"style": {
|
|
326
|
+
"font_size": "14px",
|
|
327
|
+
"text_color": "#000000A6",
|
|
328
|
+
"gap": "8px",
|
|
329
|
+
"margin_bottom": "20px",
|
|
330
|
+
"padding_y": "8px 20px",
|
|
331
|
+
"active_bg": "钴蓝-5",
|
|
332
|
+
"active_color": "#FFFFFF",
|
|
333
|
+
"border_color": "#D9D9D9",
|
|
334
|
+
"hover_color": "钴蓝-5"
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"id": "admin.content.empty_state",
|
|
339
|
+
"style": {
|
|
340
|
+
"font_size": "14px",
|
|
341
|
+
"text_color": "#000000A6",
|
|
342
|
+
"icon_size": "40px",
|
|
343
|
+
"padding": "40px"
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"id": "component.button.primary",
|
|
348
|
+
"style": {
|
|
349
|
+
"bg_color": "钴蓝-5",
|
|
350
|
+
"text_color": "#FFFFFF",
|
|
351
|
+
"border_color": "钴蓝-5",
|
|
352
|
+
"font_weight": "常规",
|
|
353
|
+
"padding_x": "15px",
|
|
354
|
+
"height": "32px",
|
|
355
|
+
"radius": "6px"
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"id": "component.button.default",
|
|
360
|
+
"style": {
|
|
361
|
+
"bg_color": "#FFFFFF",
|
|
362
|
+
"text_color": "#000000E6",
|
|
363
|
+
"border_color": "#D9D9D9",
|
|
364
|
+
"font_weight": "常规",
|
|
365
|
+
"padding_x": "15px",
|
|
366
|
+
"height": "32px",
|
|
367
|
+
"radius": "6px"
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"id": "component.button.danger",
|
|
372
|
+
"style": {
|
|
373
|
+
"bg_color": "#FF4D4F",
|
|
374
|
+
"text_color": "#FFFFFF",
|
|
375
|
+
"border_color": "#FF4D4F",
|
|
376
|
+
"font_weight": "常规",
|
|
377
|
+
"padding_x": "12px",
|
|
378
|
+
"height": "32px",
|
|
379
|
+
"radius": "6px"
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"id": "component.tag.status",
|
|
384
|
+
"form": "filled",
|
|
385
|
+
"style": {
|
|
386
|
+
"bg_color": "#F6FFED",
|
|
387
|
+
"text_color": "#52C41A",
|
|
388
|
+
"border_color": "#D9F7BE",
|
|
389
|
+
"font_size": "12px",
|
|
390
|
+
"radius": "6px",
|
|
391
|
+
"icon_size": "16px"
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"id": "component.input.base",
|
|
396
|
+
"style": {
|
|
397
|
+
"bg_color": "#FFFFFF",
|
|
398
|
+
"text_color": "#000000E6",
|
|
399
|
+
"border_color": "#D9D9D9",
|
|
400
|
+
"radius": "6px",
|
|
401
|
+
"height": "32px",
|
|
402
|
+
"font_size": "14px",
|
|
403
|
+
"icon_size": "16px",
|
|
404
|
+
"padding_x": "12px"
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"id": "component.pagination.base",
|
|
409
|
+
"style": {
|
|
410
|
+
"height": "32px",
|
|
411
|
+
"gap": "8px",
|
|
412
|
+
"radius": "6px",
|
|
413
|
+
"active_bg": "钴蓝-5",
|
|
414
|
+
"active_color": "#FFFFFF",
|
|
415
|
+
"border_color": "#D9D9D9",
|
|
416
|
+
"text_color": "#000000E6",
|
|
417
|
+
"hover_color": "钴蓝-5",
|
|
418
|
+
"icon_size": "16px"
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
],
|
|
422
|
+
"oracle": {
|
|
423
|
+
"mockup": "project-ui-design/references/page-specs/styles/default/scenes/admin/mockups/list-page/运单管理-钴蓝.html",
|
|
424
|
+
"sids": [
|
|
425
|
+
"admin.layout.sidebar",
|
|
426
|
+
"admin.layout.sidebar.logo_area",
|
|
427
|
+
"admin.layout.sidebar.menu",
|
|
428
|
+
"admin.layout.header",
|
|
429
|
+
"admin.layout.header.collapse_trigger",
|
|
430
|
+
"admin.layout.header.lang_switch",
|
|
431
|
+
"admin.layout.header.fullscreen",
|
|
432
|
+
"admin.layout.header.setting_button",
|
|
433
|
+
"admin.layout.header.user_profile",
|
|
434
|
+
"admin.layout.tabs",
|
|
435
|
+
"admin.layout.tabs.home_tab",
|
|
436
|
+
"admin.layout.tabs.item",
|
|
437
|
+
"admin.layout.tabs.item_active",
|
|
438
|
+
"admin.layout.tabs.divider",
|
|
439
|
+
"admin.layout.content",
|
|
440
|
+
"admin.content.container",
|
|
441
|
+
"component.card.base",
|
|
442
|
+
"admin.content.page_header",
|
|
443
|
+
"admin.content.filter_area",
|
|
444
|
+
"admin.content.table.operation_bar",
|
|
445
|
+
"admin.content.table.area",
|
|
446
|
+
"admin.content.table.header_cell",
|
|
447
|
+
"admin.content.table.cell",
|
|
448
|
+
"admin.content.table.cell_status",
|
|
449
|
+
"admin.content.table.cell_amount",
|
|
450
|
+
"admin.content.table.operation_column",
|
|
451
|
+
"admin.content.pagination",
|
|
452
|
+
"component.button.primary",
|
|
453
|
+
"component.button.default",
|
|
454
|
+
"component.button.danger",
|
|
455
|
+
"component.tag.status",
|
|
456
|
+
"component.input.base",
|
|
457
|
+
"component.pagination.base"
|
|
458
|
+
]
|
|
459
|
+
},
|
|
460
|
+
"coverage": {
|
|
461
|
+
"registry": "project-ui-design/references/page-specs/styles/default/scenes/admin/restore-registry.json",
|
|
462
|
+
"registrable": 186,
|
|
463
|
+
"applicable": 186,
|
|
464
|
+
"covered": 186,
|
|
465
|
+
"gaps": []
|
|
466
|
+
},
|
|
467
|
+
"notes": "钴蓝主题 admin 列表页完整还原变更集(首版,待 verify 验收)。值优先取效果图精确字面量;官方主色走语义值 钴蓝-5。侧栏为深色 #001529(钴蓝主题壳层约定)。cell_thumb 列本页未出现故未声明;sidebar.collapse_trigger / header.logo_area 按出厂中性收口(visible:false)。"
|
|
468
|
+
}
|
|
@@ -55,6 +55,7 @@ lint / type-check **过了也不能放过**下列项。发现即改代码,禁
|
|
|
55
55
|
| 设计变更集落地(`design-apply`) | 声明已落地但节点无对应锚点(`anchor.kind` 目标不存在:类未绑 / 变量无消费者 / 属性未挂) | 先补锚点(属「补通道」申报);锚点缺失即为挂载点缺口,禁止用更宽选择器蒙混 |
|
|
56
56
|
| 同上 | `apply_via` 为 `class_name` / `attribute` / `slot_content` / `data_source` 之一,却只写了 CSS 而没改结构/绑定 | 按 `structure_ops` 施工(改模板 / 绑 `class-name` / 改 formatter / 挂 `data-*`),CSS 换不掉数据驱动点位 |
|
|
57
57
|
| 同上 | 全局覆写与组件 `scoped` 同权重生效失败(收口 `visible:false` / opacity / 几何覆盖不生效) | 按 `priority` 声明提权(`scope_qualified` / `self_plus_important` / `deep_qualified`),不得靠「后置加载」赌注入顺序 |
|
|
58
|
+
| 同上 | 容器语义类挂错节点:把「行/栏」语义类挂到**纵向复合容器**根节点(如把 `.vts-action-bar`(`flex-direction: row`)挂到 `ReTableBar` 根节点,而根节点是「工具栏行 + 表格 + 分页」) | 只能挂到该语义真正对应的那一层(工具栏行在 `ReTableBar` 组件内部);挂错会让兄弟节点并排、几何与 `tableHeight` 实测失准。修法是**移动挂载点**,不是给根节点补 `flex-direction: column` 打补丁 |
|
|
58
59
|
| 同上 | 词典 `selector` / `css_vars` 指向的选择器在真实 DOM 不存在(死通道 / 死令牌) | 跑 `node parser/index.js audit` 复核;死令牌双删、死通道补消费者挂载点 |
|
|
59
60
|
| 同上 | 变更集带登记表时 `C < A`(有规范子项未落进 `changes[]` / `visible` / `pending`)——组级台账过了但组内子项被静默丢失 | 跑 `node parser/index.js match --registry`;缺口逐条点名回流设计侧,**禁止采信自报的 `coverage` 数字**(parser 当场重算) |
|
|
60
61
|
|
|
@@ -153,7 +154,8 @@ lint / type-check **过了也不能放过**下列项。发现即改代码,禁
|
|
|
153
154
|
- [ ] **映射通道活性**:本轮用到的词典条目,其 `selector` / `css_vars` 在真实 DOM 可命中、CSS 变量有消费者(已跑 `audit` 或逐条核对,无死通道 / 死令牌)
|
|
154
155
|
- [ ] **锚点契约**:变更集 `anchor` 声明的锚点存在;`layer=inner` 的点位已解析到内层文本盒(`.cell` / 文本节点宿主),未错落在宿主盒上
|
|
155
156
|
- [ ] **结构施工**:`apply_via` 非 `style_override` 的点位已按 `structure_ops` 改结构/绑定(`class-name` / formatter / `data-*` / 渲染分支),未只用 CSS 冒充落地;申报了结构增量施工
|
|
156
|
-
- [ ]
|
|
157
|
+
- [ ] **出厂形态互斥收口(`suppress` 兑现)**:变更集每条带 `form` 的点位,其 `suppress` 清单逐通道收口完毕(优先令牌重映射),交付说明给出「通道 → 收口方式」对照;漏一条 = 出厂旧装饰残留(右竖条 / 旧激活底色块 / hover 才显关闭钮等都属此类)
|
|
158
|
+
- [ ] **覆写提权 / 同权重失效检查**:`priority` 声明的每条规则都**真数过权重**——写出特异度三元组 `(a,b,c)` **逐位比较(先 `b` 后 `c`)**:对手为组件 `<style scoped>` 时本条 `b` 必须严格更高(**平手即判失效**并提权);对手带 `!important` 时本条必须同样 `!important`;**`html` / `body` 只加 `c` 位,对手 `b` 更高时无效**(如出厂 `body[layout] .sidebar-container .el-menu-item` 为 `b=3`,本层 `html body .sidebar-container .el-menu-item` 只有 `b=2` → 一律失效,须靠**加祖先类**把 `b` 抬平)。**出厂用 `var(--vts-theme-*)` 间接设属性时,先走「令牌重映射」**(在令牌宿主作用域重声明令牌)而不是抢属性。收口(`display:none` 等)与几何覆盖必须实测生效,未被组件 `scoped` / 出厂全局规则反压
|
|
157
159
|
- [ ] **模板源码注释中性**:对模板文件的改动中,注释只描述「这段代码做什么」;语义 ID / 协议步骤号 / 缺口·自举·申报等面向 AI 的纪律条款不得写入模板源码注释(一律留在技能侧文档)
|
|
158
160
|
|
|
159
161
|
### 渲染态验收(变更集含 `oracle` / 效果图有 `data-sid` 时强制)
|
|
@@ -71,9 +71,9 @@ parser match(确定性翻译)→ 施工坐标 → AI 按坐标改代码 →
|
|
|
71
71
|
"position": "right", // 可选:相对方位(left/right/top/bottom)
|
|
72
72
|
"form": "card", // 可选:形态切换(见条目 forms 枚举)
|
|
73
73
|
"style": { "menu_bg": "钴蓝-9" }, // 可选:抽象样式字段(词典 css_vars/custom_style_map key;值 = 语义名或 hex)
|
|
74
|
-
"apply_via": "admin.layout.sidebar.menu", //
|
|
75
|
-
"layer": { "menu_text": "host" }, //
|
|
76
|
-
"structure_ops": [ //
|
|
74
|
+
"apply_via": "admin.layout.sidebar.menu", // 可选:本声明引用的锚点来源条目(缺省 = 自身;值 = 语义 ID,不是选择器)
|
|
75
|
+
"layer": { "menu_text": "host" }, // 可选:落点层级(host 宿主盒 / inner 内层文本盒);可为字符串(整条生效)或「字段 → 层级」对象
|
|
76
|
+
"structure_ops": [ // 可选:结构施工声明(数据 / 结构驱动点位必须给,只写 CSS = 无效声明)
|
|
77
77
|
{ "op": "render_branch", "node": "status_tag", "source": "row.status" }
|
|
78
78
|
]
|
|
79
79
|
}
|
|
@@ -84,7 +84,7 @@ parser match(确定性翻译)→ 施工坐标 → AI 按坐标改代码 →
|
|
|
84
84
|
}
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
**
|
|
87
|
+
** 三个声明维度**(补齐「由哪个通道落地 / 被压时怎么赢 / 需要改结构时落在哪」):
|
|
88
88
|
|
|
89
89
|
| 字段 | 作用 | 值域 |
|
|
90
90
|
|---|---|---|
|
|
@@ -135,7 +135,7 @@ node parser/index.js match --batch <changesets-dir>
|
|
|
135
135
|
|
|
136
136
|
`缺口清单` 只承载第二类,且必须给出点位 ID + 缺失字段名。
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
**转换计划新增四类输出()**:每条 L1/L2 点位除样式指令外,还会输出——
|
|
139
139
|
|
|
140
140
|
| 输出 | 含义 | 施工含义 |
|
|
141
141
|
|---|---|---|
|
|
@@ -148,7 +148,7 @@ node parser/index.js match --batch <changesets-dir>
|
|
|
148
148
|
**验收基线输出**:转换计划末尾另打印 `=== 验收基线 oracle ===`(效果图路径 + 待比对点位)与 `=== 覆盖率 coverage ===`(登记项 R / 适用 A / 已兑现 C)。有 `oracle` → 落地后必须跑第 6 步 `verify`;缺 `oracle` / `coverage` → 输出提示,把「补基线 / 补登记覆盖率」回流设计侧(场景还原应给)。
|
|
149
149
|
**覆盖率校验**:`coverage.covered` 必须等于 `coverage.applicable`、`gaps` 为空,否则打印缺口清单——`C < A` 即**欠声明**(有规范子项未落进 `changes[]`/`visible`/`pending`),属设计侧交付不完整,必须回流,不得在项目侧"猜着补"。
|
|
150
150
|
|
|
151
|
-
### 第 1 步附加 ·
|
|
151
|
+
### 第 1 步附加 · 挂载点审计(,静态查三类隐性缺口)
|
|
152
152
|
|
|
153
153
|
```bash
|
|
154
154
|
node parser/index.js audit --project <目标项目根目录> [<changeset.json…>]
|
|
@@ -164,7 +164,7 @@ node parser/index.js audit --project <目标项目根目录> [<changeset.json…
|
|
|
164
164
|
|
|
165
165
|
审计报错 = **能力缺口**:当场按 `structure_ops` 补挂载 / 补消费者,交付说明单列申报;不得以「词典没建」为由跳过。审计通过 ≠ 还原达标——**静态审计查不出「值对了、位置不对」**,那要靠第 6 步渲染态验收。
|
|
166
166
|
|
|
167
|
-
### 第 1 步附加(之二)· 登记表覆盖率(子项级细闸 ·
|
|
167
|
+
### 第 1 步附加(之二)· 登记表覆盖率(子项级细闸 · )
|
|
168
168
|
|
|
169
169
|
组级台账(`restore-checklist`)只能防「整组忘光」;**组内子项**是否被静默丢失,用登记表计数。
|
|
170
170
|
|
|
@@ -213,7 +213,7 @@ node parser/index.js registry <restore-registry.json> [--verbose] # 只
|
|
|
213
213
|
- 设计要求换掉出厂卡片容器(去卡片、改通栏、改内部排布)→ **照做,不打折**:页面根声明 `data-content-mode`,把 `data-fill` **平移**到新容器及其「体」层,视觉全落设计层文件。此路径下 `tableHeight` 几何实测照常成立。
|
|
214
214
|
- **双向禁止**:① 以「保高度」为由拒绝改容器/内边距/去卡片(= 放弃设计还原);② 为凑还原效果改写壳层结构层规则、或在视觉层重写/压掉 `[data-fill]` / `.main-content[data-content-mode]`(= 高度链断裂,返工项)。
|
|
215
215
|
|
|
216
|
-
#### 第 2 步附加 · 结构施工(structure_ops
|
|
216
|
+
#### 第 2 步附加 · 结构施工(structure_ops)与优先级策略()
|
|
217
217
|
|
|
218
218
|
**A. 结构施工 `structure_ops`(数据 / 结构驱动点位)**——有些点位**换不掉也写不出来**,因为呈现由数据源或模板结构决定。变更集给出 `structure_ops` 时必须照做,**只写 CSS = 无效声明**:
|
|
219
219
|
|
|
@@ -231,8 +231,15 @@ node parser/index.js registry <restore-registry.json> [--verbose] # 只
|
|
|
231
231
|
|
|
232
232
|
- 变更集给了 `layer` → 严格按 `layer` 从条目 `anchors` 取对应选择器(parser 已在转换计划里给出 `@ … · host/inner 层`)。
|
|
233
233
|
- 变更集**没给** `layer`、但条目 `preconditions` 指出必须落内层(如 EP 表头 `white-space`)→ 按 `preconditions` 落 inner 层,并在交付说明注明「设计侧未给 layer,按条目前置条件处理」。
|
|
234
|
+
- **内层盒属性族强制校验**:`white-space` / `text-overflow` / `overflow` / `word-break` / `text-align` / `line-height` / `vertical-align` 这组属性**只在内层文本盒生效**——逐字段核对 `layer`;未指认且条目前置条件也没说 → **退回设计侧补声明**,禁止默认落 host(历史缺口:表头「禁止换行」落 host 被内层默认 `normal` 吃掉 → 表头竖排、行高撑大、列内容被压)。
|
|
234
235
|
- 常规分工:高度 / 背景 / padding 落 host;文本换行、省略、对齐落 inner。
|
|
235
236
|
|
|
237
|
+
**B2. 出厂形态互斥收口 `suppress`(治「新形态上了、旧形态残留」)**——条目带 `suppress` 时,逐通道执行收口,**收口优先走令牌重映射**(在令牌宿主作用域重声明令牌,零权重战争),令牌不存在才写属性:
|
|
238
|
+
|
|
239
|
+
- 每条通道收口后必须在交付说明列出「通道名 → 收口方式 → 落点」,漏一条 = 出厂旧装饰残留。
|
|
240
|
+
- 实例:侧栏 `form=pill` → `suppress: ["右指示条通道"]` → 在侧栏作用域把出厂右竖条令牌重映射为 `none`(出厂 `.el-menu-item.is-active { border-right: var(--…) }` 与 `design-tokens` 的 `3px solid` 令牌都无需改动)。
|
|
241
|
+
- 页签 `form=flat` 属**多通道收口**:透明化激活底色块 + 去圆角间距 + 关闭钮常显 + 贯穿分割线 + 首页页签仅图标——必须逐通道列出并收口,漏任何一条 = 「整个样式和设计不一样」。
|
|
242
|
+
|
|
236
243
|
**C. 覆写优先级 `priority`(禁止逐点硬堆 `!important`)**——条目 `priority.strategy` 给出本点位该怎么赢:
|
|
237
244
|
|
|
238
245
|
| 策略 | 施工口径 |
|
|
@@ -278,6 +285,34 @@ node parser/index.js registry <restore-registry.json> [--verbose] # 只
|
|
|
278
285
|
|
|
279
286
|
每写一条新规则前,先按第 1 步输出的 `▸ 覆写优先级 priority` 判定对手类型与取胜方式(见下节)。
|
|
280
287
|
|
|
288
|
+
#### 特异度必须**逐位比较**(`html` / `body` 抬不动「类位」)
|
|
289
|
+
|
|
290
|
+
特异度写成三元组 `(a, b, c)`:`a` = id,`b` = **类 / 属性选择器 / 伪类**,`c` = 类型选择器 / 伪元素。比较顺序是**先比 `a` → 再比 `b` → 最后比 `c`**,`b` 位为 0 时 `c` 再大也没用。
|
|
291
|
+
|
|
292
|
+
- `html` / `body` 是**类型选择器**,只加 `c` 位。对手 `b` 位更高时,加 `html body` **完全无效**。
|
|
293
|
+
- 对手是组件 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` 都赢不了。
|
|
294
|
+
- 正确的抬法是**加类**:在祖先链上补稳定的语义类(如 `.el-menu`)把 `b` 抬到与对手相等,再靠 `c`(`html body`)胜出。
|
|
295
|
+
|
|
296
|
+
> **实例(已发生的回归)**:`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`)→ 菜单文字改用出厂令牌的**浅色主题值(黑)**落在设计强制的深色侧栏上 → **整栏菜单字全部消失**。规则没写错,是权重没算对。
|
|
297
|
+
|
|
298
|
+
#### 改通道(令牌)优先于抢属性
|
|
299
|
+
|
|
300
|
+
出厂用**语义令牌间接**设置属性时(`color: var(--vts-theme-menu-text)`、`background: var(--vts-theme-menu-bg)`…),**不要写同名属性去抢**,而是**在令牌宿主作用域重映射令牌**:
|
|
301
|
+
|
|
302
|
+
```scss
|
|
303
|
+
html body .sidebar-container { /* 令牌宿主 = 该令牌被消费的元素所在作用域 */
|
|
304
|
+
--vts-theme-menu-text: rgb(255 255 255 / 65%);
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
判据:**令牌在哪个元素上被声明,就在那个作用域重映射**。自定义属性按继承解析,出厂规则自己会消费新值 ⇒ **零权重战争**,也不受对手 `!important` 影响。适用范围:`--vts-theme-*` 全族。
|
|
309
|
+
|
|
310
|
+
只有在「出厂没有该令牌」或「令牌语义与设计不符(如胶囊几何 `inset`/`radius`)」时才回到抢属性,并按上一条逐位比较。
|
|
311
|
+
|
|
312
|
+
**统一顺序:① 先找令牌通道 → ② 无通道才抢属性(逐位比特异度)→ ③ 都不行才 `!important` + 注释对手。**
|
|
313
|
+
|
|
314
|
+
> 上例的正解就是①:在设计层把 `--vts-theme-menu-text/bg/hover/active-bg` 在 `.sidebar-container` 上重映射,出厂规则自己就画出白色的字与蓝色胶囊。
|
|
315
|
+
|
|
281
316
|
写入纪律:
|
|
282
317
|
|
|
283
318
|
- 每条规则带来源标注(`/* <语义 ID> · <变更条目> */`),换设计时整段可替换;
|
|
@@ -286,13 +321,13 @@ node parser/index.js registry <restore-registry.json> [--verbose] # 只
|
|
|
286
321
|
- 出厂 `--vts-theme-menu-active-before` 默认 `transparent` 且无消费者 → 声明 `form=indicator_*` 时必须在此文件内**同时**落地「关胶囊令牌 `menu_active_bg: transparent`」与「新建 `::after` 消费者」,缺一即未施工成功。
|
|
287
322
|
- **自举(项目被还原到出厂时必做,幂等)**:文件不存在 → 新建(仅保留文件头纪律注释,无任何设计结论)+ 在 `src/styles/index.scss` **末位**补 `@use 'design-shell';`(必须末位,靠后置压出厂)。此动作属「补通道」,交付说明单列申报。**文件缺失时径直把设计规则写进 `element-plus.scss` / `sidebar.scss` / `theme.scss` = 污染出厂文件,禁止**(这也是「设计还原度为零」的常见成因:规则无处可落)。
|
|
288
323
|
|
|
289
|
-
### 第 3 步附加(之二)· 覆写优先级消费(
|
|
324
|
+
### 第 3 步附加(之二)· 覆写优先级消费( 硬步骤)
|
|
290
325
|
|
|
291
326
|
第 1 步输出的 `▸ 覆写优先级 priority` **不是提示,是落地写法的硬要求**。每落一条规则前先按策略决定写法;写法错了,规则就是「写了不生效」。历史缺口「面包屑 `visible:false` 写了 `display:none` 却照旧显示」「页签关闭钮 `opacity` 写了却仍要 hover 才显」全部源于此——两条规则本身都没写错,是**赢了才是硬道理**这一步没人做。
|
|
292
327
|
|
|
293
328
|
| `priority.strategy` | 对手 | 必须的写法 | 自检判据 |
|
|
294
329
|
|---|---|---|---|
|
|
295
|
-
| `scope_qualified` |
|
|
330
|
+
| `scope_qualified` | 无,或出厂**全局样式**(`sidebar.scss` / `element-plus.scss` / `theme.scss`,注意它们也在 `index.scss` 的 `@use` 链里、可能带 `!important` 且 `b` 位更高) | 按词典 selector 原样落;**逐位比过对手**(先 b 后 c);出厂用 `var(--vts-theme-*)` 时优先重映射令牌 | 若实测仍被覆盖 → 升格按 `deep_qualified` 处理 |
|
|
296
331
|
| `deep_qualified` | 组件 `<style scoped>`(平手 + 后注入) | **禁止裸类名**。≥3 层作用域限定(如 `html .a .b`)或叠加属性/伪类;仍平手才对本条补 `!important` | 写前自问:这条与组件 scoped 谁特异度高?**平手即错** |
|
|
297
332
|
| `self_plus_important` | 出厂规则带 `!important` | 本条必须 `!important` + 注释写明「对手带 `!important`」;能改走通道变量时优先改通道 | 只抬特异度无效,别白费 |
|
|
298
333
|
|
|
@@ -341,12 +376,13 @@ html .navbar .navbar-breadcrumb-wrap {
|
|
|
341
376
|
- 表头 / 行 / 分页都在视口内,仅表格体内滚动,无外层滚动条、无拉伸 / 塌陷 / 双滚动条,`tableHeight > 0`;
|
|
342
377
|
- **结构层 diff 为空**:`lay-content/index.vue` 的 `.main-content[data-content-mode]` 与 `element-plus.scss` 的 `[data-fill]` 未被改动;同时确认没有「为保高度而放弃设计还原」(出厂卡片 / 内边距 / 内部排布原样未动而变更集声明了改动)——两个方向任一命中即返工
|
|
343
378
|
- [ ] **映射通道活性检查(杂必查)**:样式落地引用的每个 CSS 变量必须在项目样式中**存在消费者**(`变量名` 有 `var(--xxx)` 引用点);只定义不消费的变量 = 通道死路,翻译再准也不生效(menu_active_indicator 曾因 --vts-theme-menu-active-before 无消费者而「映射了却没效果」)。施工时 grep 核对,无消费者时改走消费者存在的作用域或补挂载点并申报。
|
|
344
|
-
- [ ]
|
|
379
|
+
- [ ] **结构施工兑现检查(structure_ops 逐条对账,与红线同级)**:变更集 `structure_ops[]` 的**每一条 op** 都必须在交付说明给出「op → 落在哪个文件 / 哪个节点 / 怎么落的」;`add_node` 必须真的新增了元素或渲染分支(模板 diff 可验),`bind_source` 必须真的改了绑定(`class-name` / `align` / `formatter`)。出现「声明了 op、代码里找不到对应改动」= 交付不完整,禁止只改 CSS 冒充结构施工(历史缺口:操作列分割线 `add_node` 声明了但从未施工 → 按钮间竖线一直缺失)
|
|
380
|
+
- [ ] **同权重失效检查( · 专查「写了不生效」)**:逐条核对设计层新增规则是否真能取胜——① 对手是组件 `<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`)→ 整栏菜单文字用浅色主题的黑色落在深色侧栏上、字全部消失**
|
|
345
381
|
- [ ] **oracle 基线可用性检查**:变更集带 `oracle` 时——① `oracle.mockup` 必须与**本次主题、本次页面**一致(禁止复用异主题效果图:主题错配会让逐点比对必然全红);② `oracle.sids` 与 `changes[]` **双向闭合**:效果图里有、changes[] 未声明 = **欠声明**(该点位永远不可能被还原);changes[] 已声明、效果图无 sid = **无基线**(落地后无法机器验收)。两类出现即回流设计侧补齐,**不得直接开工**(`parser match` 已自动报出)
|
|
346
382
|
- [ ] **dark.scss 暗色同步**:新增视觉规则在 `html.dark` 有对应覆盖
|
|
347
383
|
- [ ] **缺口清单只含意图缺口**:清单每一项都必须是「设计侧未给值 / 值非法」且已注明「回流设计侧补齐」;能力缺口(词典缺 ID / 缺字段枚举 / 缺 form)不得出现在清单里——出现即把可落地项搁置
|
|
348
384
|
- [ ] **台账逐行兑现对账(对账闸门)**:把设计侧交付的提取台账逐行过一遍,每行必须有落地结论——已落地(写明落在哪个文件/选择器)或已入缺口清单(写明缺失字段)。存在「台账有行、落地无结论」的行 = 交付不完整,与红线同级
|
|
349
|
-
- [ ]
|
|
385
|
+
- [ ] **登记表覆盖率对账(子项级细闸,)**:带登记表交付时必须跑 `match --registry`——`C = A` 且无缺口才可交付;同时确认无「效果图标注缺口」(`always:true` 子项在效果图上都有同名 `data-sid`)。**禁止采信设计侧自报的 `coverage` 数字**(parser 会当场重算,自报数不参与);缺口逐条点名回流设计侧
|
|
350
386
|
- [ ] **零搁置交付**:最终回复不含「待确认」类停顿项;交付说明的「补映射 / 补通道 / 缺口回流」三段齐全(无内容写「无」)
|
|
351
387
|
- [ ] `node parser/index.js build --dry` 通过(mapping 若有临时新增)
|
|
352
388
|
|
|
@@ -408,7 +444,7 @@ node parser/index.js match parser/fixtures/changeset-neg3.json # F. 负例3
|
|
|
408
444
|
node parser/index.js match parser/fixtures/changeset-legacy.json # G. 旧协议:exit 0 + layout 键/schema 历史值两条告警
|
|
409
445
|
node parser/index.js match parser/fixtures/changeset-fullpage-restore.json # H. 整页场景还原样例:exit 0;壳层+内容区全模块 L1 命中;数值字面量(40px 等)透传无 ⚠
|
|
410
446
|
node parser/index.js build --dry # I. 产物链自检
|
|
411
|
-
node parser/index.js match parser/fixtures/changeset-v32-fields.json # J.
|
|
447
|
+
node parser/index.js match parser/fixtures/changeset-v32-fields.json # J. 声明维:exit 0;输出「结构施工 structure_ops」与 layer / apply_via
|
|
412
448
|
node parser/index.js audit --project parser/fixtures/fake-project parser/fixtures/changeset-v32-fields.json # K. 静态审计:夹具项目存在挂载点缺失/死通道 → exit 1
|
|
413
449
|
node parser/index.js verify --oracle parser/fixtures/verify/oracle.json --actual parser/fixtures/verify/actual.json # L. 渲染态验收:夹具含三类故意缺口 → exit 1;归因计数 选择器落空1/权重被压1/语境错位2
|
|
414
450
|
node parser/index.js match --registry parser/fixtures/registry-sample.json parser/fixtures/changeset-registry-gap.json # M. 登记表覆盖率细闸:夹具欠声明 2 条恒存在子项 → exit 1
|