dsh-visualkit 0.0.1 → 0.0.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/CHANGELOG.md +14 -0
- package/README.md +20 -4
- package/data/assets/illustrations/openpeeps/LICENSE +1 -1
- package/lib/contrast-render.js +213 -213
- package/lib/detect.js +701 -701
- package/lib/diff.js +153 -153
- package/lib/icon-render.js +107 -107
- package/lib/index.js +1289 -1289
- package/lib/layouts/image.js +1010 -1010
- package/lib/layouts/source.js +1961 -1961
- package/lib/render-html.js +255 -255
- package/lib/rules.js +267 -267
- package/lib/style.js +688 -688
- package/lib/svg.js +729 -729
- package/lib/taste.js +219 -219
- package/package.json +4 -4
package/lib/rules.js
CHANGED
|
@@ -1,267 +1,267 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* rules.js — 「AI 味」规则表:约束(design_style 的禁用清单)与检测(ui_taste 的指标)
|
|
3
|
-
* 共用同一份定义。
|
|
4
|
-
*
|
|
5
|
-
* 为什么同源:设计的核心矛盾是「规则改了但检测没改」——两边各写一份必然漂移,
|
|
6
|
-
* 模型拿到的约束和验收标准就会打架。这里每条规则只有一处定义。
|
|
7
|
-
*
|
|
8
|
-
* ── scope 分层(2026-11-07 第二次修订)──────────────────────────
|
|
9
|
-
* 上一版把「通用质量」和「风格偏好」混成一层,风格规则占 41% 权重,导致约束本身
|
|
10
|
-
* 变成新的众数(四个预设只因强调色/字体不同才区分开)。现按证据分三层:
|
|
11
|
-
*
|
|
12
|
-
* quality 跨任何风格都成立的底线(字号要有层级、间距有节奏、交互态完整、
|
|
13
|
-
* 留白有分层、图标是真 SVG)。打破它不是"风格选择",是缺陷。
|
|
14
|
-
* style 仅代表一种审美取向(禁紫渐变 / 小圆角 / 禁毛玻璃 / 禁渐变文字 /
|
|
15
|
-
* 居中式首屏)。品牌或题材有理由时**应当允许越界**,故可降权、可声明豁免。
|
|
16
|
-
* content 内容真实度(假大数 / 占位文案)。
|
|
17
|
-
*
|
|
18
|
-
* profile 决定各层的计分系数,见 PROFILES——同一次检测在不同 profile 下
|
|
19
|
-
* 得到不同分数,但检测事实(hits / fix)完全一致。
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
const RULES = [
|
|
23
|
-
{
|
|
24
|
-
id: "emoji-icon",
|
|
25
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
26
|
-
fingerprint: true,
|
|
27
|
-
label: "emoji 当图标",
|
|
28
|
-
scope: "quality",
|
|
29
|
-
weight: 14,
|
|
30
|
-
ban: "不要用 emoji 做图标,用 icon (action=find|emit) 取真 SVG",
|
|
31
|
-
fix: "把 emoji 换成 SVG 图标:icon (action=find) 选型 → icon (action=emit, target=raw) 出码"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
id: "type-flat",
|
|
35
|
-
label: "字号塌缩(有档位无跳变)",
|
|
36
|
-
scope: "quality",
|
|
37
|
-
weight: 12,
|
|
38
|
-
ban: "字号最多 4 档,且标题/正文之间必须有 ≥1.6× 跳变",
|
|
39
|
-
// 与 layout_check S1 同源判断:这里不重复实现,只把更细的查看入口写出来,
|
|
40
|
-
// 否则两个工具各报一次同一个问题,用户会困惑该听哪个。
|
|
41
|
-
fix: "把字号收敛到 4 档,并让最大档至少是正文的 1.6 倍(如正文 14 → 标题 24/28);逐档明细与 file:line 用 layout_check action=ui(S1)查看"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
id: "spacing-offgrid",
|
|
45
|
-
label: "间距不在 4px 网格",
|
|
46
|
-
scope: "quality",
|
|
47
|
-
weight: 8,
|
|
48
|
-
ban: "间距落在 4px 网格(4/8/12/16/24/32;2px 仅用于对齐微调)",
|
|
49
|
-
fix: "把间距对齐到 4px 网格:4/8/12/16/24/32,删掉 5/6/7/10/14 这类手调值(2px 微调可保留)"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
id: "no-states",
|
|
53
|
-
label: "交互态缺失",
|
|
54
|
-
scope: "quality",
|
|
55
|
-
weight: 6,
|
|
56
|
-
ban: "可点的元素必须有 hover / focus-visible / disabled 三态",
|
|
57
|
-
fix: "给按钮/链接/表格行补 :hover、:focus-visible、:disabled;键盘可达是底线"
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
id: "card-uniform",
|
|
61
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
62
|
-
fingerprint: true,
|
|
63
|
-
label: "同构三件套卡片",
|
|
64
|
-
scope: "quality",
|
|
65
|
-
weight: 4,
|
|
66
|
-
ban: "不要整页都是 icon+标题+描述的同构卡片网格",
|
|
67
|
-
fix: "让卡片承载不同信息量:主卡放结论,次卡放数据,边栏放记录;不要一律三件套"
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: "no-breath",
|
|
71
|
-
label: "留白无分层",
|
|
72
|
-
scope: "quality",
|
|
73
|
-
weight: 4,
|
|
74
|
-
ban: "页面级的留白要明显大于控件内部留白(至少 3:1)",
|
|
75
|
-
fix: "拉开两种 padding:页面级 32–48px,控件内部 6–10px;现在两者挤在同一量级"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
id: "purple-gradient",
|
|
79
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
80
|
-
fingerprint: true,
|
|
81
|
-
label: "紫/蓝紫渐变",
|
|
82
|
-
scope: "style",
|
|
83
|
-
weight: 12,
|
|
84
|
-
ban: "默认避免紫/indigo/violet 渐变(AI 最强指纹);品牌主色确需时在 .design-intent.json 声明豁免",
|
|
85
|
-
fix: "渐变改成同色相或干脆去掉:单一强调色 + 中性底色;需要层次就用明度差,不要换色相"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
id: "radius-blob",
|
|
89
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
90
|
-
fingerprint: true,
|
|
91
|
-
label: "大圆角滥用",
|
|
92
|
-
scope: "style",
|
|
93
|
-
weight: 10,
|
|
94
|
-
ban: "数据密集型界面圆角 ≤8px,不要全站 rounded-xl/2xl(消费类产品可放宽)",
|
|
95
|
-
fix: "圆角降到 ≤8px(数据密集型界面 2–4px);不要给所有容器同一个大圆角"
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
id: "hue-sprawl",
|
|
99
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
100
|
-
fingerprint: true,
|
|
101
|
-
label: "色相家族过多",
|
|
102
|
-
scope: "style",
|
|
103
|
-
weight: 8,
|
|
104
|
-
ban: "强调色只允许 1 个家族,语义色(成功/警告/危险)不与强调色混用",
|
|
105
|
-
fix: "把色相收到 1 个强调家族 + 1 套语义色;其余用中性灰阶拉开层次"
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
id: "shadow-glow",
|
|
109
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
110
|
-
fingerprint: true,
|
|
111
|
-
label: "发光/软阴影",
|
|
112
|
-
scope: "style",
|
|
113
|
-
weight: 8,
|
|
114
|
-
ban: "默认不要发光阴影和彩色投影,最多 1 层中性投影",
|
|
115
|
-
fix: "去掉 0 0 Npx 发光与彩色投影;需要浮起就用 1 层中性阴影或直接靠描边/底色区分"
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
id: "glassmorphism",
|
|
119
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
120
|
-
fingerprint: true,
|
|
121
|
-
label: "毛玻璃/半透明白",
|
|
122
|
-
scope: "style",
|
|
123
|
-
weight: 8,
|
|
124
|
-
ban: "默认不要毛玻璃(backdrop-filter)和大面积半透明白",
|
|
125
|
-
fix: "去掉 backdrop-filter;面板用实色 + 1px 描边,需要层次用底色明度差"
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
id: "gradient-text",
|
|
129
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
130
|
-
fingerprint: true,
|
|
131
|
-
label: "渐变文字",
|
|
132
|
-
scope: "style",
|
|
133
|
-
weight: 7,
|
|
134
|
-
ban: "不要渐变文字(background-clip:text)",
|
|
135
|
-
fix: "标题用实色 + 字重/字号制造层级;渐变文字在深色背景上对比度还会不达标"
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
id: "centered-hero",
|
|
139
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
140
|
-
fingerprint: true,
|
|
141
|
-
label: "居中 hero + CTA",
|
|
142
|
-
scope: "style",
|
|
143
|
-
weight: 3,
|
|
144
|
-
ban: "产品界面默认不要「居中大标题 + 副标题 + 按钮」的营销首屏(官网落地页可以)",
|
|
145
|
-
fix: "改成信息型首屏:一个真实结论句 + 关键指标 + 元数据(谁/何时/范围),而不是营销口号"
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
id: "fake-stat",
|
|
149
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
150
|
-
fingerprint: true,
|
|
151
|
-
label: "假大数/占位文案",
|
|
152
|
-
scope: "content",
|
|
153
|
-
weight: 6,
|
|
154
|
-
ban: "不要 128K+/99.9% 这类不可算的假大数,也不要 Lorem/敬请期待",
|
|
155
|
-
fix: "换成真能算的数字(18,432 行 / 47 分钟)或明确标注为示例数据,不要用 K+/99.9% 充场面"
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
id: "nest-boxes",
|
|
159
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
160
|
-
fingerprint: true,
|
|
161
|
-
label: "容器过度嵌套(框里再套框)",
|
|
162
|
-
scope: "style",
|
|
163
|
-
weight: 12,
|
|
164
|
-
ban: "卡片里不要再画一层带圆角的框:靠间距和底色区分层级,不要靠套娃",
|
|
165
|
-
fix: "把内层那圈 border-radius + 边框去掉,用 padding 与背景色差表达层级;确实要分组时用一条细分隔或留白,而不是再套一个框"
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
id: "divider-sprawl",
|
|
169
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
170
|
-
fingerprint: true,
|
|
171
|
-
label: "分割线泛滥",
|
|
172
|
-
scope: "style",
|
|
173
|
-
weight: 10,
|
|
174
|
-
ban: "不要每个区块之间都画一条线:先用间距分组,线只在间距做不到时用",
|
|
175
|
-
fix: "删掉多数 border-top/bottom 与 <hr>,把区块间距调到 24/32px 让留白完成分组;只保留真正的分组边界(如两张不同性质的表之间)"
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
id: "big-black-tight",
|
|
179
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
180
|
-
fingerprint: true,
|
|
181
|
-
label: "标题又大又黑又挤(≥30px / 700+ / 行高 ≤1.25)",
|
|
182
|
-
scope: "style",
|
|
183
|
-
weight: 14,
|
|
184
|
-
ban: "标题不要靠「更大更黑」硬撑层次:字号降下来、行高放开、用留白与字距做气口",
|
|
185
|
-
fix: "标题字号收到正文的 1.6–2×(正文 16 → 标题 28–32 已足够),font-weight 降到 600,line-height 提到 1.2–1.3"
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
id: "dead-button",
|
|
189
|
-
label: "按钮看着能点却没有结果",
|
|
190
|
-
scope: "quality",
|
|
191
|
-
weight: 16,
|
|
192
|
-
ban: "按钮必须有行为:submit、点击绑定、或明确的 data-action;摆着不响的按钮比没有按钮更伤",
|
|
193
|
-
fix: "给按钮接上真实行为(提交/跳转/打开面板),暂时做不到就渲染成 disabled 或去掉——先确认是不是挂在外层事件委托上,避免误判"
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
id: "ai-copy",
|
|
197
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
198
|
-
fingerprint: true,
|
|
199
|
-
label: "AI 套路文案",
|
|
200
|
-
scope: "content",
|
|
201
|
-
weight: 8,
|
|
202
|
-
ban: "CTA 不要用 → 箭头、“立即/一键/轻松/极致/解锁/赋能/助力”、“XX之旅”,也不要用无缝/闭环/抓手这类黑话",
|
|
203
|
-
// 实测来源:自己做的 7 种风格 UI 里给按钮写了“立即同步 →”,
|
|
204
|
-
// 而当时的规则一条都没抓到——工具在提倡反 AI 味,却查不出自己身上的 AI 味。
|
|
205
|
-
fix: "写成具体动作:把“立即同步 →”改成“同步”/“推送到远端”;删掉箭头与咏叹调形容词,动词+宾语就够"
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
id: "icon-tile-uniform",
|
|
209
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
210
|
-
fingerprint: true,
|
|
211
|
-
label: "图标色块一律",
|
|
212
|
-
scope: "style",
|
|
213
|
-
weight: 7,
|
|
214
|
-
ban: "不要给每个卡片的图标都套同尺寸同色的圆角块(渐变方块尤甚)——这是模板卡片的长相",
|
|
215
|
-
// 实测来源(2026-11-08):写一个当代 AI 首页样本,最显眼的 AI 感就是
|
|
216
|
-
// 三个特性卡里各一个 48px 同款渐变圆角块,而 19 条规则一条都没抓到。
|
|
217
|
-
fix: "选一种:图标直接放在留白里靠对齐建立秩序 / 只给主卡一个色块 / 色块随语义换色(成功·警示·中性)"
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
id: "eyebrow-spam",
|
|
221
|
-
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
222
|
-
fingerprint: true,
|
|
223
|
-
label: "小标签逐段开场",
|
|
224
|
-
scope: "style",
|
|
225
|
-
weight: 5,
|
|
226
|
-
ban: "不要每个区块都拿一个小号大字距标签(eyebrow/kicker)当开场,四段以上尤其明显",
|
|
227
|
-
// 保留 0–1 个是正常编辑手法(用来说明栏目归属),四段以上就是模板句式。
|
|
228
|
-
fix: "只留 1 个说明栏目归属,其余靠标题自身的层级与留白分段;小标签不宜承担分段责任"
|
|
229
|
-
}
|
|
230
|
-
];
|
|
231
|
-
|
|
232
|
-
/** 规则 id → 规则对象(ui_taste 的 ignore 参数与报告渲染共用)。 */
|
|
233
|
-
const RULE_BY_ID = new Map(RULES.map((rule) => [rule.id, rule]));
|
|
234
|
-
|
|
235
|
-
const TOTAL_WEIGHT = RULES.reduce((sum, rule) => sum + rule.weight, 0);
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* 检测档位:同一次检测,不同 profile 下各层的计分系数不同。
|
|
239
|
-
*
|
|
240
|
-
* strict 全规则满权重——适合"确认这就是 AI 默认产物"的诊断场景。
|
|
241
|
-
* balanced 默认。风格层降到 0.4:品牌/题材有理由的风格选择不应被判死刑,
|
|
242
|
-
* 但仍然能被看见。这是在"反同质化"与"仍能发现塌缩"之间的折中。
|
|
243
|
-
* structure 只查质量与内容(风格权重 0)——给已有明确视觉方向的团队用,
|
|
244
|
-
* 避免这套规则反过来把他们的品牌风格判成问题。
|
|
245
|
-
*/
|
|
246
|
-
const PROFILES = {
|
|
247
|
-
strict: { label: "全规则", quality: 1, style: 1, content: 1 },
|
|
248
|
-
balanced: { label: "默认(风格层降权)", quality: 1, style: 0.4, content: 0.8 },
|
|
249
|
-
structure: { label: "只查结构", quality: 1, style: 0, content: 0.5 }
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* 分数分级(balanced 口径)。
|
|
254
|
-
* 阈值按实测校准:模型无约束输出 75、第三方 AI 插件 UI 54、受约束手写 2-5。
|
|
255
|
-
*
|
|
256
|
-
* **口径纪律**:分数是诊断工具,不是 KPI。只在 ai-tinged / ai-default 区间
|
|
257
|
-
* 提示返工;clean 区间(≤15)不再"优化"——继续压分会把设计往安全区推,反而
|
|
258
|
-
* 制造同质化(Goodhart)。报告里会显式说明这一点。
|
|
259
|
-
*/
|
|
260
|
-
function gradeOf(score) {
|
|
261
|
-
if (score <= 15) return "clean";
|
|
262
|
-
if (score <= 30) return "acceptable";
|
|
263
|
-
if (score <= 50) return "ai-tinged";
|
|
264
|
-
return "ai-default";
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export { PROFILES, RULES, RULE_BY_ID, TOTAL_WEIGHT, gradeOf };
|
|
1
|
+
/**
|
|
2
|
+
* rules.js — 「AI 味」规则表:约束(design_style 的禁用清单)与检测(ui_taste 的指标)
|
|
3
|
+
* 共用同一份定义。
|
|
4
|
+
*
|
|
5
|
+
* 为什么同源:设计的核心矛盾是「规则改了但检测没改」——两边各写一份必然漂移,
|
|
6
|
+
* 模型拿到的约束和验收标准就会打架。这里每条规则只有一处定义。
|
|
7
|
+
*
|
|
8
|
+
* ── scope 分层(2026-11-07 第二次修订)──────────────────────────
|
|
9
|
+
* 上一版把「通用质量」和「风格偏好」混成一层,风格规则占 41% 权重,导致约束本身
|
|
10
|
+
* 变成新的众数(四个预设只因强调色/字体不同才区分开)。现按证据分三层:
|
|
11
|
+
*
|
|
12
|
+
* quality 跨任何风格都成立的底线(字号要有层级、间距有节奏、交互态完整、
|
|
13
|
+
* 留白有分层、图标是真 SVG)。打破它不是"风格选择",是缺陷。
|
|
14
|
+
* style 仅代表一种审美取向(禁紫渐变 / 小圆角 / 禁毛玻璃 / 禁渐变文字 /
|
|
15
|
+
* 居中式首屏)。品牌或题材有理由时**应当允许越界**,故可降权、可声明豁免。
|
|
16
|
+
* content 内容真实度(假大数 / 占位文案)。
|
|
17
|
+
*
|
|
18
|
+
* profile 决定各层的计分系数,见 PROFILES——同一次检测在不同 profile 下
|
|
19
|
+
* 得到不同分数,但检测事实(hits / fix)完全一致。
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const RULES = [
|
|
23
|
+
{
|
|
24
|
+
id: "emoji-icon",
|
|
25
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
26
|
+
fingerprint: true,
|
|
27
|
+
label: "emoji 当图标",
|
|
28
|
+
scope: "quality",
|
|
29
|
+
weight: 14,
|
|
30
|
+
ban: "不要用 emoji 做图标,用 icon (action=find|emit) 取真 SVG",
|
|
31
|
+
fix: "把 emoji 换成 SVG 图标:icon (action=find) 选型 → icon (action=emit, target=raw) 出码"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "type-flat",
|
|
35
|
+
label: "字号塌缩(有档位无跳变)",
|
|
36
|
+
scope: "quality",
|
|
37
|
+
weight: 12,
|
|
38
|
+
ban: "字号最多 4 档,且标题/正文之间必须有 ≥1.6× 跳变",
|
|
39
|
+
// 与 layout_check S1 同源判断:这里不重复实现,只把更细的查看入口写出来,
|
|
40
|
+
// 否则两个工具各报一次同一个问题,用户会困惑该听哪个。
|
|
41
|
+
fix: "把字号收敛到 4 档,并让最大档至少是正文的 1.6 倍(如正文 14 → 标题 24/28);逐档明细与 file:line 用 layout_check action=ui(S1)查看"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "spacing-offgrid",
|
|
45
|
+
label: "间距不在 4px 网格",
|
|
46
|
+
scope: "quality",
|
|
47
|
+
weight: 8,
|
|
48
|
+
ban: "间距落在 4px 网格(4/8/12/16/24/32;2px 仅用于对齐微调)",
|
|
49
|
+
fix: "把间距对齐到 4px 网格:4/8/12/16/24/32,删掉 5/6/7/10/14 这类手调值(2px 微调可保留)"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "no-states",
|
|
53
|
+
label: "交互态缺失",
|
|
54
|
+
scope: "quality",
|
|
55
|
+
weight: 6,
|
|
56
|
+
ban: "可点的元素必须有 hover / focus-visible / disabled 三态",
|
|
57
|
+
fix: "给按钮/链接/表格行补 :hover、:focus-visible、:disabled;键盘可达是底线"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "card-uniform",
|
|
61
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
62
|
+
fingerprint: true,
|
|
63
|
+
label: "同构三件套卡片",
|
|
64
|
+
scope: "quality",
|
|
65
|
+
weight: 4,
|
|
66
|
+
ban: "不要整页都是 icon+标题+描述的同构卡片网格",
|
|
67
|
+
fix: "让卡片承载不同信息量:主卡放结论,次卡放数据,边栏放记录;不要一律三件套"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "no-breath",
|
|
71
|
+
label: "留白无分层",
|
|
72
|
+
scope: "quality",
|
|
73
|
+
weight: 4,
|
|
74
|
+
ban: "页面级的留白要明显大于控件内部留白(至少 3:1)",
|
|
75
|
+
fix: "拉开两种 padding:页面级 32–48px,控件内部 6–10px;现在两者挤在同一量级"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "purple-gradient",
|
|
79
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
80
|
+
fingerprint: true,
|
|
81
|
+
label: "紫/蓝紫渐变",
|
|
82
|
+
scope: "style",
|
|
83
|
+
weight: 12,
|
|
84
|
+
ban: "默认避免紫/indigo/violet 渐变(AI 最强指纹);品牌主色确需时在 .design-intent.json 声明豁免",
|
|
85
|
+
fix: "渐变改成同色相或干脆去掉:单一强调色 + 中性底色;需要层次就用明度差,不要换色相"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "radius-blob",
|
|
89
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
90
|
+
fingerprint: true,
|
|
91
|
+
label: "大圆角滥用",
|
|
92
|
+
scope: "style",
|
|
93
|
+
weight: 10,
|
|
94
|
+
ban: "数据密集型界面圆角 ≤8px,不要全站 rounded-xl/2xl(消费类产品可放宽)",
|
|
95
|
+
fix: "圆角降到 ≤8px(数据密集型界面 2–4px);不要给所有容器同一个大圆角"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: "hue-sprawl",
|
|
99
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
100
|
+
fingerprint: true,
|
|
101
|
+
label: "色相家族过多",
|
|
102
|
+
scope: "style",
|
|
103
|
+
weight: 8,
|
|
104
|
+
ban: "强调色只允许 1 个家族,语义色(成功/警告/危险)不与强调色混用",
|
|
105
|
+
fix: "把色相收到 1 个强调家族 + 1 套语义色;其余用中性灰阶拉开层次"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "shadow-glow",
|
|
109
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
110
|
+
fingerprint: true,
|
|
111
|
+
label: "发光/软阴影",
|
|
112
|
+
scope: "style",
|
|
113
|
+
weight: 8,
|
|
114
|
+
ban: "默认不要发光阴影和彩色投影,最多 1 层中性投影",
|
|
115
|
+
fix: "去掉 0 0 Npx 发光与彩色投影;需要浮起就用 1 层中性阴影或直接靠描边/底色区分"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "glassmorphism",
|
|
119
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
120
|
+
fingerprint: true,
|
|
121
|
+
label: "毛玻璃/半透明白",
|
|
122
|
+
scope: "style",
|
|
123
|
+
weight: 8,
|
|
124
|
+
ban: "默认不要毛玻璃(backdrop-filter)和大面积半透明白",
|
|
125
|
+
fix: "去掉 backdrop-filter;面板用实色 + 1px 描边,需要层次用底色明度差"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: "gradient-text",
|
|
129
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
130
|
+
fingerprint: true,
|
|
131
|
+
label: "渐变文字",
|
|
132
|
+
scope: "style",
|
|
133
|
+
weight: 7,
|
|
134
|
+
ban: "不要渐变文字(background-clip:text)",
|
|
135
|
+
fix: "标题用实色 + 字重/字号制造层级;渐变文字在深色背景上对比度还会不达标"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "centered-hero",
|
|
139
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
140
|
+
fingerprint: true,
|
|
141
|
+
label: "居中 hero + CTA",
|
|
142
|
+
scope: "style",
|
|
143
|
+
weight: 3,
|
|
144
|
+
ban: "产品界面默认不要「居中大标题 + 副标题 + 按钮」的营销首屏(官网落地页可以)",
|
|
145
|
+
fix: "改成信息型首屏:一个真实结论句 + 关键指标 + 元数据(谁/何时/范围),而不是营销口号"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "fake-stat",
|
|
149
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
150
|
+
fingerprint: true,
|
|
151
|
+
label: "假大数/占位文案",
|
|
152
|
+
scope: "content",
|
|
153
|
+
weight: 6,
|
|
154
|
+
ban: "不要 128K+/99.9% 这类不可算的假大数,也不要 Lorem/敬请期待",
|
|
155
|
+
fix: "换成真能算的数字(18,432 行 / 47 分钟)或明确标注为示例数据,不要用 K+/99.9% 充场面"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: "nest-boxes",
|
|
159
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
160
|
+
fingerprint: true,
|
|
161
|
+
label: "容器过度嵌套(框里再套框)",
|
|
162
|
+
scope: "style",
|
|
163
|
+
weight: 12,
|
|
164
|
+
ban: "卡片里不要再画一层带圆角的框:靠间距和底色区分层级,不要靠套娃",
|
|
165
|
+
fix: "把内层那圈 border-radius + 边框去掉,用 padding 与背景色差表达层级;确实要分组时用一条细分隔或留白,而不是再套一个框"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
id: "divider-sprawl",
|
|
169
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
170
|
+
fingerprint: true,
|
|
171
|
+
label: "分割线泛滥",
|
|
172
|
+
scope: "style",
|
|
173
|
+
weight: 10,
|
|
174
|
+
ban: "不要每个区块之间都画一条线:先用间距分组,线只在间距做不到时用",
|
|
175
|
+
fix: "删掉多数 border-top/bottom 与 <hr>,把区块间距调到 24/32px 让留白完成分组;只保留真正的分组边界(如两张不同性质的表之间)"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: "big-black-tight",
|
|
179
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
180
|
+
fingerprint: true,
|
|
181
|
+
label: "标题又大又黑又挤(≥30px / 700+ / 行高 ≤1.25)",
|
|
182
|
+
scope: "style",
|
|
183
|
+
weight: 14,
|
|
184
|
+
ban: "标题不要靠「更大更黑」硬撑层次:字号降下来、行高放开、用留白与字距做气口",
|
|
185
|
+
fix: "标题字号收到正文的 1.6–2×(正文 16 → 标题 28–32 已足够),font-weight 降到 600,line-height 提到 1.2–1.3"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: "dead-button",
|
|
189
|
+
label: "按钮看着能点却没有结果",
|
|
190
|
+
scope: "quality",
|
|
191
|
+
weight: 16,
|
|
192
|
+
ban: "按钮必须有行为:submit、点击绑定、或明确的 data-action;摆着不响的按钮比没有按钮更伤",
|
|
193
|
+
fix: "给按钮接上真实行为(提交/跳转/打开面板),暂时做不到就渲染成 disabled 或去掉——先确认是不是挂在外层事件委托上,避免误判"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: "ai-copy",
|
|
197
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
198
|
+
fingerprint: true,
|
|
199
|
+
label: "AI 套路文案",
|
|
200
|
+
scope: "content",
|
|
201
|
+
weight: 8,
|
|
202
|
+
ban: "CTA 不要用 → 箭头、“立即/一键/轻松/极致/解锁/赋能/助力”、“XX之旅”,也不要用无缝/闭环/抓手这类黑话",
|
|
203
|
+
// 实测来源:自己做的 7 种风格 UI 里给按钮写了“立即同步 →”,
|
|
204
|
+
// 而当时的规则一条都没抓到——工具在提倡反 AI 味,却查不出自己身上的 AI 味。
|
|
205
|
+
fix: "写成具体动作:把“立即同步 →”改成“同步”/“推送到远端”;删掉箭头与咏叹调形容词,动词+宾语就够"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
id: "icon-tile-uniform",
|
|
209
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
210
|
+
fingerprint: true,
|
|
211
|
+
label: "图标色块一律",
|
|
212
|
+
scope: "style",
|
|
213
|
+
weight: 7,
|
|
214
|
+
ban: "不要给每个卡片的图标都套同尺寸同色的圆角块(渐变方块尤甚)——这是模板卡片的长相",
|
|
215
|
+
// 实测来源(2026-11-08):写一个当代 AI 首页样本,最显眼的 AI 感就是
|
|
216
|
+
// 三个特性卡里各一个 48px 同款渐变圆角块,而 19 条规则一条都没抓到。
|
|
217
|
+
fix: "选一种:图标直接放在留白里靠对齐建立秩序 / 只给主卡一个色块 / 色块随语义换色(成功·警示·中性)"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: "eyebrow-spam",
|
|
221
|
+
// 参与「成组出现」判定:这一项属于风格默认选择,不是通用质量缺陷
|
|
222
|
+
fingerprint: true,
|
|
223
|
+
label: "小标签逐段开场",
|
|
224
|
+
scope: "style",
|
|
225
|
+
weight: 5,
|
|
226
|
+
ban: "不要每个区块都拿一个小号大字距标签(eyebrow/kicker)当开场,四段以上尤其明显",
|
|
227
|
+
// 保留 0–1 个是正常编辑手法(用来说明栏目归属),四段以上就是模板句式。
|
|
228
|
+
fix: "只留 1 个说明栏目归属,其余靠标题自身的层级与留白分段;小标签不宜承担分段责任"
|
|
229
|
+
}
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
/** 规则 id → 规则对象(ui_taste 的 ignore 参数与报告渲染共用)。 */
|
|
233
|
+
const RULE_BY_ID = new Map(RULES.map((rule) => [rule.id, rule]));
|
|
234
|
+
|
|
235
|
+
const TOTAL_WEIGHT = RULES.reduce((sum, rule) => sum + rule.weight, 0);
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* 检测档位:同一次检测,不同 profile 下各层的计分系数不同。
|
|
239
|
+
*
|
|
240
|
+
* strict 全规则满权重——适合"确认这就是 AI 默认产物"的诊断场景。
|
|
241
|
+
* balanced 默认。风格层降到 0.4:品牌/题材有理由的风格选择不应被判死刑,
|
|
242
|
+
* 但仍然能被看见。这是在"反同质化"与"仍能发现塌缩"之间的折中。
|
|
243
|
+
* structure 只查质量与内容(风格权重 0)——给已有明确视觉方向的团队用,
|
|
244
|
+
* 避免这套规则反过来把他们的品牌风格判成问题。
|
|
245
|
+
*/
|
|
246
|
+
const PROFILES = {
|
|
247
|
+
strict: { label: "全规则", quality: 1, style: 1, content: 1 },
|
|
248
|
+
balanced: { label: "默认(风格层降权)", quality: 1, style: 0.4, content: 0.8 },
|
|
249
|
+
structure: { label: "只查结构", quality: 1, style: 0, content: 0.5 }
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* 分数分级(balanced 口径)。
|
|
254
|
+
* 阈值按实测校准:模型无约束输出 75、第三方 AI 插件 UI 54、受约束手写 2-5。
|
|
255
|
+
*
|
|
256
|
+
* **口径纪律**:分数是诊断工具,不是 KPI。只在 ai-tinged / ai-default 区间
|
|
257
|
+
* 提示返工;clean 区间(≤15)不再"优化"——继续压分会把设计往安全区推,反而
|
|
258
|
+
* 制造同质化(Goodhart)。报告里会显式说明这一点。
|
|
259
|
+
*/
|
|
260
|
+
function gradeOf(score) {
|
|
261
|
+
if (score <= 15) return "clean";
|
|
262
|
+
if (score <= 30) return "acceptable";
|
|
263
|
+
if (score <= 50) return "ai-tinged";
|
|
264
|
+
return "ai-default";
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export { PROFILES, RULES, RULE_BY_ID, TOTAL_WEIGHT, gradeOf };
|