@morya-ui/setup 0.3.2 → 0.3.4
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 +103 -103
- package/bin/morya-ui-setup.js +14 -14
- package/catalog/skills.json +46 -46
- package/package.json +5 -3
- package/src/cli.mjs +335 -335
- package/src/copy-template.mjs +78 -78
- package/src/fs-utils.mjs +24 -24
- package/src/install.mjs +63 -63
- package/src/mcp.mjs +50 -50
- package/src/package-json.mjs +30 -30
- package/src/skills.mjs +223 -223
- package/src/styles.mjs +119 -119
- package/template/.agents/skills/morya-ui-pages/SKILL.md +184 -162
- package/template/.agents/skills/morya-ui-pages/evals/evals.json +89 -71
- package/template/.agents/skills/morya-ui-pages/references/component-index.md +99 -98
- package/template/.agents/skills/morya-ui-pages/references/decision-recipes.md +1591 -0
- package/template/.agents/skills/morya-ui-pages/references/design-system.md +101 -100
- package/template/.agents/skills/morya-ui-pages/references/feedback.md +68 -66
- package/template/.agents/skills/morya-ui-pages/references/optional-companions.md +107 -34
- package/template/.agents/skills/morya-ui-pages/references/page-layouts.md +141 -119
- package/template/.agents/skills/morya-ui-pages/references/review-checklist.md +64 -61
- package/template/.agents/skills/morya-ui-pages/references/style-presets.md +73 -0
- package/template/.agents/skills/morya-ui-pages/references/surfaces.md +91 -89
- package/template/.agents/skills/morya-ui-pages/references/visual-craft.md +221 -196
- package/template/.cursor/rules/coding-style.mdc +41 -41
- package/template/.cursor/rules/component-usage.mdc +41 -41
- package/template/.cursor/rules/design-system.mdc +17 -17
- package/template/.cursor/rules/page-layout.mdc +97 -78
- package/template/DESIGN.md +59 -59
- package/template/scripts/check-raw-colors.mjs +74 -74
- package/LICENSE +0 -21
|
@@ -0,0 +1,1591 @@
|
|
|
1
|
+
# Decision recipes (scenario → component → key API)
|
|
2
|
+
|
|
3
|
+
Generated from `packages/ui-mcp/src/decisions.ts`. **Do not hand-edit** this file — run:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pnpm --filter @morya-ui/mcp generate:recipes
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
MCP: `recommend_component` (list / read by `decision` / query). Full prop manuals still come from `get_component` + `validate_usage`.
|
|
10
|
+
|
|
11
|
+
This file is the **offline** mirror for agents without MCP.
|
|
12
|
+
|
|
13
|
+
## `form-surface-choice` — 新建/编辑用弹窗还是独立表单页
|
|
14
|
+
|
|
15
|
+
> 表单是从列表触发的短录入,还是多分组/长流程的独立配置?
|
|
16
|
+
|
|
17
|
+
### Dialog
|
|
18
|
+
|
|
19
|
+
**When**
|
|
20
|
+
|
|
21
|
+
- 从列表/工具栏打开新建或编辑
|
|
22
|
+
- 字段大约 ≤8 个、单段表单
|
|
23
|
+
- 希望保存后仍停留在列表上下文
|
|
24
|
+
|
|
25
|
+
**Avoid when**
|
|
26
|
+
|
|
27
|
+
- 多步骤向导
|
|
28
|
+
- 多分组长配置页
|
|
29
|
+
|
|
30
|
+
**Recipe · props**
|
|
31
|
+
|
|
32
|
+
- v-model / modelValue 控制开关(不要用 visible)
|
|
33
|
+
- header 或 title 设弹窗标题
|
|
34
|
+
- width 约 32rem 适配短表单(见 form-in-dialog 黄金样例)
|
|
35
|
+
- 表单字段用 fluid;主按钮 severity="primary"
|
|
36
|
+
|
|
37
|
+
**Recipe · slots**
|
|
38
|
+
|
|
39
|
+
- #footer 放取消/保存
|
|
40
|
+
- 默认插槽放 MForm + MFormItem
|
|
41
|
+
|
|
42
|
+
**Recipe · events**
|
|
43
|
+
|
|
44
|
+
- @close 重置表单模型
|
|
45
|
+
- 保存可用按钮 @click,或 MForm @submit + type="submit"
|
|
46
|
+
|
|
47
|
+
**Anti-patterns**
|
|
48
|
+
|
|
49
|
+
- 用普通 Dialog 手写删除确认 → MConfirmDialog
|
|
50
|
+
- 长多分组配置塞进 Dialog → Form 页或 Drawer
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Drawer
|
|
54
|
+
|
|
55
|
+
**When**
|
|
56
|
+
|
|
57
|
+
- 表单比 Dialog 更长但仍需对照列表
|
|
58
|
+
- 详情+编辑侧滑
|
|
59
|
+
|
|
60
|
+
**Avoid when**
|
|
61
|
+
|
|
62
|
+
- 字段极少的确认式录入
|
|
63
|
+
|
|
64
|
+
**Recipe · props**
|
|
65
|
+
|
|
66
|
+
- v-model / modelValue 控制开关
|
|
67
|
+
- position 常用 right;较长表单可加大 size
|
|
68
|
+
- header 标明新建/编辑对象
|
|
69
|
+
- 字段 fluid;底栏操作对齐 #footer
|
|
70
|
+
|
|
71
|
+
**Recipe · slots**
|
|
72
|
+
|
|
73
|
+
- #footer 取消/保存
|
|
74
|
+
- 默认插槽 MForm
|
|
75
|
+
|
|
76
|
+
**Recipe · events**
|
|
77
|
+
|
|
78
|
+
- @close 清理草稿
|
|
79
|
+
|
|
80
|
+
**Anti-patterns**
|
|
81
|
+
|
|
82
|
+
- 极短 2–3 字段也用 Drawer → Dialog
|
|
83
|
+
- 危险删除只用 Drawer 无确认 → MConfirmDialog
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
### Form
|
|
87
|
+
|
|
88
|
+
**When**
|
|
89
|
+
|
|
90
|
+
- 用户明确要求独立表单页
|
|
91
|
+
- 多分组、长校验、离开需确认的配置流
|
|
92
|
+
|
|
93
|
+
**Avoid when**
|
|
94
|
+
|
|
95
|
+
- 列表上的常规短 CRUD
|
|
96
|
+
|
|
97
|
+
**Recipe · props**
|
|
98
|
+
|
|
99
|
+
- MPageContent width="narrow"
|
|
100
|
+
- MPageSection variant="form" 包表单主体
|
|
101
|
+
- MPageSection variant="actions" 放底栏按钮
|
|
102
|
+
- 字段 v-model + fluid;校验用 invalid / errorMessage
|
|
103
|
+
|
|
104
|
+
**Recipe · slots**
|
|
105
|
+
|
|
106
|
+
- 默认插槽:MFormItem 字段
|
|
107
|
+
|
|
108
|
+
**Recipe · events**
|
|
109
|
+
|
|
110
|
+
- MForm @submit(或 @submit.prevent)
|
|
111
|
+
- 提交按钮 type="submit" + severity="primary"
|
|
112
|
+
|
|
113
|
+
**Anti-patterns**
|
|
114
|
+
|
|
115
|
+
- 列表短 CRUD 开独立路由 → form-in-dialog
|
|
116
|
+
- 表单外再套装饰性 MCard → 用 PageSection form
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## `overlay-choice` — 如何选择浮层组件
|
|
122
|
+
|
|
123
|
+
> 这是确认、短任务、上下文操作,还是需要保留页面上下文的编辑?
|
|
124
|
+
|
|
125
|
+
### Dialog
|
|
126
|
+
|
|
127
|
+
**When**
|
|
128
|
+
|
|
129
|
+
- 需要用户聚焦完成一项短到中等任务
|
|
130
|
+
- 列表页上的新建/编辑短表单(约 ≤8 个字段)
|
|
131
|
+
- 内容不适合直接放在页面流中
|
|
132
|
+
|
|
133
|
+
**Avoid when**
|
|
134
|
+
|
|
135
|
+
- 内容接近完整多分组页面
|
|
136
|
+
- 用户需要持续查看底层页面上下文且表单很长
|
|
137
|
+
- 只是危险操作确认
|
|
138
|
+
|
|
139
|
+
**Recipe · props**
|
|
140
|
+
|
|
141
|
+
- v-model 控制可见
|
|
142
|
+
- header / title
|
|
143
|
+
- modal 默认阻塞;任务型内容放默认插槽
|
|
144
|
+
- 危险确认不要用 Dialog 冒充 → ConfirmDialog
|
|
145
|
+
|
|
146
|
+
**Recipe · slots**
|
|
147
|
+
|
|
148
|
+
- #footer 主/次操作
|
|
149
|
+
|
|
150
|
+
**Recipe · events**
|
|
151
|
+
|
|
152
|
+
- @close / @update:modelValue
|
|
153
|
+
|
|
154
|
+
**Anti-patterns**
|
|
155
|
+
|
|
156
|
+
- Dialog + 手写「确定删除」→ MConfirmDialog
|
|
157
|
+
- v-model:visible → v-model / modelValue
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
### Drawer
|
|
161
|
+
|
|
162
|
+
**When**
|
|
163
|
+
|
|
164
|
+
- 需要侧边编辑或查看详情
|
|
165
|
+
- 需要保留底层列表或工作区上下文
|
|
166
|
+
- 内容比普通确认框更长
|
|
167
|
+
|
|
168
|
+
**Avoid when**
|
|
169
|
+
|
|
170
|
+
- 只是简单确认
|
|
171
|
+
- 操作必须阻塞用户直到明确确认
|
|
172
|
+
|
|
173
|
+
**Recipe · props**
|
|
174
|
+
|
|
175
|
+
- v-model
|
|
176
|
+
- position="right"(常用)
|
|
177
|
+
- header 说明侧栏任务
|
|
178
|
+
|
|
179
|
+
**Recipe · slots**
|
|
180
|
+
|
|
181
|
+
- #footer 操作区
|
|
182
|
+
|
|
183
|
+
**Recipe · events**
|
|
184
|
+
|
|
185
|
+
- @close
|
|
186
|
+
|
|
187
|
+
**Anti-patterns**
|
|
188
|
+
|
|
189
|
+
- 简单 Yes/No 确认用 Drawer → ConfirmDialog / ConfirmPopup
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
### Popover
|
|
193
|
+
|
|
194
|
+
**When**
|
|
195
|
+
|
|
196
|
+
- 轻量上下文操作或补充信息
|
|
197
|
+
- 不需要阻塞页面
|
|
198
|
+
- 内容与触发元素强相关
|
|
199
|
+
|
|
200
|
+
**Avoid when**
|
|
201
|
+
|
|
202
|
+
- 需要复杂表单或危险操作确认
|
|
203
|
+
|
|
204
|
+
**Recipe · props**
|
|
205
|
+
|
|
206
|
+
- v-model 或触发器控制显示
|
|
207
|
+
- placement 相对触发元素
|
|
208
|
+
- 内容保持短小
|
|
209
|
+
|
|
210
|
+
**Recipe · slots**
|
|
211
|
+
|
|
212
|
+
- 默认插槽:轻量内容
|
|
213
|
+
|
|
214
|
+
**Anti-patterns**
|
|
215
|
+
|
|
216
|
+
- 复杂表单塞进 Popover → Dialog / Drawer
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
### Tooltip
|
|
220
|
+
|
|
221
|
+
**When**
|
|
222
|
+
|
|
223
|
+
- 只展示简短说明
|
|
224
|
+
- 用户悬停或聚焦控件时需要补充提示
|
|
225
|
+
|
|
226
|
+
**Avoid when**
|
|
227
|
+
|
|
228
|
+
- 信息是必需内容
|
|
229
|
+
- 需要放置交互控件
|
|
230
|
+
|
|
231
|
+
**Recipe · props**
|
|
232
|
+
|
|
233
|
+
- content 或默认插槽短文案
|
|
234
|
+
- placement
|
|
235
|
+
- 包裹触发元素
|
|
236
|
+
|
|
237
|
+
**Anti-patterns**
|
|
238
|
+
|
|
239
|
+
- Tooltip 里放按钮/表单 → Popover / Dialog
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## `data-display-choice` — 如何选择数据展示组件
|
|
245
|
+
|
|
246
|
+
> 用户需要比较行列数据、浏览卡片,还是查看树状层级?
|
|
247
|
+
|
|
248
|
+
### Table
|
|
249
|
+
|
|
250
|
+
**When**
|
|
251
|
+
|
|
252
|
+
- 数据有稳定列结构
|
|
253
|
+
- 用户需要排序、筛选、批量或行操作
|
|
254
|
+
- 需要高密度比较多条记录
|
|
255
|
+
|
|
256
|
+
**Avoid when**
|
|
257
|
+
|
|
258
|
+
- 每条数据结构差异很大
|
|
259
|
+
- 移动端无法承载横向列结构
|
|
260
|
+
|
|
261
|
+
**Recipe · props**
|
|
262
|
+
|
|
263
|
+
- columns + rows(没有 data prop)
|
|
264
|
+
- row-key 默认 id;不稳定时显式指定
|
|
265
|
+
- 全视口主列表可 MPageContent fill + MTable fill;嵌入/短页跳过
|
|
266
|
+
- 分页:paginator + rows-per-page 或 v-model:page
|
|
267
|
+
- 行选择:selectionMode + v-model:selection
|
|
268
|
+
|
|
269
|
+
**Recipe · slots**
|
|
270
|
+
|
|
271
|
+
- #cell-{key} 自定义单元格
|
|
272
|
+
- #empty 放 MEmpty
|
|
273
|
+
|
|
274
|
+
**Anti-patterns**
|
|
275
|
+
|
|
276
|
+
- :data → :rows
|
|
277
|
+
- 手写 <table> → MTable
|
|
278
|
+
- 嵌入表硬套 fill → 去掉 fill
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
### DataView
|
|
282
|
+
|
|
283
|
+
**When**
|
|
284
|
+
|
|
285
|
+
- 数据适合卡片或自定义列表项
|
|
286
|
+
- 视觉浏览比列对齐更重要
|
|
287
|
+
- 同一数据需要切换多种展示布局
|
|
288
|
+
|
|
289
|
+
**Avoid when**
|
|
290
|
+
|
|
291
|
+
- 用户必须精确比较字段
|
|
292
|
+
- 需要复杂列级排序或固定列
|
|
293
|
+
|
|
294
|
+
**Recipe · props**
|
|
295
|
+
|
|
296
|
+
- value / 数据源按文档绑定
|
|
297
|
+
- layout 切换列表/网格等
|
|
298
|
+
- 分页与空态按文档配置
|
|
299
|
+
|
|
300
|
+
**Recipe · slots**
|
|
301
|
+
|
|
302
|
+
- #list / #grid 等项模板
|
|
303
|
+
|
|
304
|
+
**Anti-patterns**
|
|
305
|
+
|
|
306
|
+
- 需要列对齐比较仍用 DataView → Table
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
### TreeTable
|
|
310
|
+
|
|
311
|
+
**When**
|
|
312
|
+
|
|
313
|
+
- 数据同时具有表格列和父子层级
|
|
314
|
+
- 用户需要展开、收起层级节点
|
|
315
|
+
|
|
316
|
+
**Avoid when**
|
|
317
|
+
|
|
318
|
+
- 数据没有真实层级关系
|
|
319
|
+
- 普通 Table 已能表达关系
|
|
320
|
+
|
|
321
|
+
**Recipe · props**
|
|
322
|
+
|
|
323
|
+
- columns + 带 children 的行数据
|
|
324
|
+
- 展开相关 prop 按文档(expandedKeys 等)
|
|
325
|
+
- row-key 稳定
|
|
326
|
+
|
|
327
|
+
**Recipe · slots**
|
|
328
|
+
|
|
329
|
+
- #cell-{key}
|
|
330
|
+
|
|
331
|
+
**Anti-patterns**
|
|
332
|
+
|
|
333
|
+
- 无层级硬用 TreeTable → Table
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
### Tree
|
|
337
|
+
|
|
338
|
+
**When**
|
|
339
|
+
|
|
340
|
+
- 主要任务是浏览或选择层级节点
|
|
341
|
+
- 节点信息不需要多列比较
|
|
342
|
+
|
|
343
|
+
**Avoid when**
|
|
344
|
+
|
|
345
|
+
- 每行需要展示多个可比较字段
|
|
346
|
+
|
|
347
|
+
**Recipe · props**
|
|
348
|
+
|
|
349
|
+
- :value / value 树节点数据
|
|
350
|
+
- selectionMode 单选/多选
|
|
351
|
+
- v-model:selectionKeys 或文档等价绑定
|
|
352
|
+
|
|
353
|
+
**Anti-patterns**
|
|
354
|
+
|
|
355
|
+
- 表单里选组织树 → 优先 TreeSelect
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## `selection-choice` — 如何选择选择器
|
|
361
|
+
|
|
362
|
+
> 选项是平面少量、层级结构、多选标签,还是需要输入搜索?
|
|
363
|
+
|
|
364
|
+
### Select
|
|
365
|
+
|
|
366
|
+
**When**
|
|
367
|
+
|
|
368
|
+
- 平面选项数量中等
|
|
369
|
+
- 需要单选或多选
|
|
370
|
+
- 表单字段需要明确选项集合
|
|
371
|
+
|
|
372
|
+
**Avoid when**
|
|
373
|
+
|
|
374
|
+
- 选项有明显层级
|
|
375
|
+
- 用户需要输入自由文本并搜索建议
|
|
376
|
+
|
|
377
|
+
**Recipe · props**
|
|
378
|
+
|
|
379
|
+
- v-model
|
|
380
|
+
- :options 选项数组
|
|
381
|
+
- 表单内 fluid;可 clearable(或 showClear)
|
|
382
|
+
- 多选按文档 multiple
|
|
383
|
+
|
|
384
|
+
**Recipe · events**
|
|
385
|
+
|
|
386
|
+
- @change / @update:modelValue
|
|
387
|
+
|
|
388
|
+
**Anti-patterns**
|
|
389
|
+
|
|
390
|
+
- MDropdown 当枚举选择 → MSelect
|
|
391
|
+
- 层级数据用 Select → TreeSelect / CascadeSelect
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
### TreeSelect
|
|
395
|
+
|
|
396
|
+
**When**
|
|
397
|
+
|
|
398
|
+
- 选项有父子层级
|
|
399
|
+
- 用户需要按组织、分类或资源树选择
|
|
400
|
+
|
|
401
|
+
**Avoid when**
|
|
402
|
+
|
|
403
|
+
- 选项只是简单平面枚举
|
|
404
|
+
|
|
405
|
+
**Recipe · props**
|
|
406
|
+
|
|
407
|
+
- v-model
|
|
408
|
+
- :options 树形数据
|
|
409
|
+
- fluid;selectionMode 按需
|
|
410
|
+
|
|
411
|
+
**Anti-patterns**
|
|
412
|
+
|
|
413
|
+
- 平面枚举用 TreeSelect → Select
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
### AutoComplete
|
|
417
|
+
|
|
418
|
+
**When**
|
|
419
|
+
|
|
420
|
+
- 用户需要输入关键词搜索建议
|
|
421
|
+
- 候选项很多或来自远程接口
|
|
422
|
+
- 输入值本身也有意义
|
|
423
|
+
|
|
424
|
+
**Avoid when**
|
|
425
|
+
|
|
426
|
+
- 用户只能从固定枚举中选择
|
|
427
|
+
- 不应该允许自由输入
|
|
428
|
+
|
|
429
|
+
**Recipe · props**
|
|
430
|
+
|
|
431
|
+
- v-model
|
|
432
|
+
- suggestions / 远程加载按文档
|
|
433
|
+
- fluid
|
|
434
|
+
|
|
435
|
+
**Recipe · events**
|
|
436
|
+
|
|
437
|
+
- @complete 拉取建议
|
|
438
|
+
|
|
439
|
+
**Anti-patterns**
|
|
440
|
+
|
|
441
|
+
- 固定枚举却允许自由输入 → Select
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
### SelectButton
|
|
445
|
+
|
|
446
|
+
**When**
|
|
447
|
+
|
|
448
|
+
- 选项很少且需要全部露出
|
|
449
|
+
- 单选或多选都适合按钮组
|
|
450
|
+
|
|
451
|
+
**Avoid when**
|
|
452
|
+
|
|
453
|
+
- 选项超过大约 5 个
|
|
454
|
+
- 选项很长或来自远程搜索
|
|
455
|
+
|
|
456
|
+
**Recipe · props**
|
|
457
|
+
|
|
458
|
+
- v-model
|
|
459
|
+
- :options
|
|
460
|
+
- 选项文案保持短
|
|
461
|
+
|
|
462
|
+
**Anti-patterns**
|
|
463
|
+
|
|
464
|
+
- >5 个选项仍用 SelectButton → Select
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
### Radio
|
|
468
|
+
|
|
469
|
+
**When**
|
|
470
|
+
|
|
471
|
+
- 少量互斥选项需要和表单文案一起阅读
|
|
472
|
+
- 一次只能选一个
|
|
473
|
+
|
|
474
|
+
**Avoid when**
|
|
475
|
+
|
|
476
|
+
- 多选
|
|
477
|
+
- 选项很多需要收进弹出层
|
|
478
|
+
|
|
479
|
+
**Recipe · props**
|
|
480
|
+
|
|
481
|
+
- MRadioGroup v-model
|
|
482
|
+
- 各 MRadio value
|
|
483
|
+
- 与 MFormItem 一起用
|
|
484
|
+
|
|
485
|
+
**Anti-patterns**
|
|
486
|
+
|
|
487
|
+
- 多选需求用 Radio → Checkbox / Select multiple
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
### Listbox
|
|
491
|
+
|
|
492
|
+
**When**
|
|
493
|
+
|
|
494
|
+
- 选项需要始终以列表展示
|
|
495
|
+
- 可筛选,但不希望收成下拉框
|
|
496
|
+
|
|
497
|
+
**Avoid when**
|
|
498
|
+
|
|
499
|
+
- 页面空间紧、只需要一个闭合的选择框
|
|
500
|
+
|
|
501
|
+
**Recipe · props**
|
|
502
|
+
|
|
503
|
+
- v-model
|
|
504
|
+
- :options
|
|
505
|
+
- filter 按需开启
|
|
506
|
+
|
|
507
|
+
**Anti-patterns**
|
|
508
|
+
|
|
509
|
+
- 空间紧仍用 Listbox → Select
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
### CascadeSelect
|
|
513
|
+
|
|
514
|
+
**When**
|
|
515
|
+
|
|
516
|
+
- 值要按多级分栏逐级点选
|
|
517
|
+
- 层级是路径而不是可勾选的树
|
|
518
|
+
|
|
519
|
+
**Avoid when**
|
|
520
|
+
|
|
521
|
+
- 需要勾选树节点或搜索整棵树
|
|
522
|
+
|
|
523
|
+
**Recipe · props**
|
|
524
|
+
|
|
525
|
+
- v-model
|
|
526
|
+
- :options 级联数据
|
|
527
|
+
- fluid
|
|
528
|
+
|
|
529
|
+
**Anti-patterns**
|
|
530
|
+
|
|
531
|
+
- 可勾选树节点用 CascadeSelect → TreeSelect
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## `surface-choice` — 如何选择内容容器
|
|
537
|
+
|
|
538
|
+
> 内容是否需要独立的视觉表面、标题和边界?
|
|
539
|
+
|
|
540
|
+
### Card
|
|
541
|
+
|
|
542
|
+
**When**
|
|
543
|
+
|
|
544
|
+
- 内容是页面中的独立业务区块
|
|
545
|
+
- 需要标题、副标题、页脚或 hover 表面
|
|
546
|
+
- 需要清晰的边界和内边距
|
|
547
|
+
|
|
548
|
+
**Avoid when**
|
|
549
|
+
|
|
550
|
+
- 页面已有过多嵌套表面
|
|
551
|
+
- 内容只是简单分组
|
|
552
|
+
- 列表表格外层
|
|
553
|
+
|
|
554
|
+
**Recipe · props**
|
|
555
|
+
|
|
556
|
+
- title / subtitle 按需
|
|
557
|
+
- shadow="always"|"hover"|"never"
|
|
558
|
+
- 仪表盘图表区可用 shadow="always"
|
|
559
|
+
|
|
560
|
+
**Recipe · slots**
|
|
561
|
+
|
|
562
|
+
- #header / #footer / #title 按需
|
|
563
|
+
- 默认插槽正文
|
|
564
|
+
|
|
565
|
+
**Anti-patterns**
|
|
566
|
+
|
|
567
|
+
- MPageFilters / MTable 外再套 MCard → 去掉外层 Card
|
|
568
|
+
- 表单主体用 Card 叠 PageSection form → 只用 PageSection
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
### Panel
|
|
572
|
+
|
|
573
|
+
**When**
|
|
574
|
+
|
|
575
|
+
- 需要可折叠或强调一个较长内容区块
|
|
576
|
+
- 内容具有明确的面板标题
|
|
577
|
+
|
|
578
|
+
**Avoid when**
|
|
579
|
+
|
|
580
|
+
- 只需要普通内容容器
|
|
581
|
+
- 标题和边界会增加视觉噪音
|
|
582
|
+
|
|
583
|
+
**Recipe · props**
|
|
584
|
+
|
|
585
|
+
- header 面板标题
|
|
586
|
+
- toggleable 可折叠时开启
|
|
587
|
+
- collapsed / v-model:collapsed 按文档
|
|
588
|
+
|
|
589
|
+
**Anti-patterns**
|
|
590
|
+
|
|
591
|
+
- 装饰性折叠用不必要的 Panel → Card 或纯布局
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
### Fieldset
|
|
595
|
+
|
|
596
|
+
**When**
|
|
597
|
+
|
|
598
|
+
- 需要语义化分组相关表单字段
|
|
599
|
+
- 分组标题对理解表单很重要
|
|
600
|
+
|
|
601
|
+
**Avoid when**
|
|
602
|
+
|
|
603
|
+
- 内容不是表单字段
|
|
604
|
+
- 只是为了增加装饰边框
|
|
605
|
+
|
|
606
|
+
**Recipe · props**
|
|
607
|
+
|
|
608
|
+
- legend / 标题文案
|
|
609
|
+
- 内放 MFormItem 字段
|
|
610
|
+
- 勿用于非表单装饰框
|
|
611
|
+
|
|
612
|
+
**Anti-patterns**
|
|
613
|
+
|
|
614
|
+
- 非表单内容用 Fieldset → Card / PageSection
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## `layout-spacing-choice` — 如何选择页面间距组件
|
|
620
|
+
|
|
621
|
+
> 控件组、页面区块、栅格之间需要哪种间距与对齐方式?
|
|
622
|
+
|
|
623
|
+
### PageContent
|
|
624
|
+
|
|
625
|
+
**When**
|
|
626
|
+
|
|
627
|
+
- 页面主内容区需要统一的 padding 和垂直 gap
|
|
628
|
+
- 列表/表单/仪表盘区块纵向堆叠
|
|
629
|
+
|
|
630
|
+
**Avoid when**
|
|
631
|
+
|
|
632
|
+
- 只是两个按钮之间的水平间距
|
|
633
|
+
|
|
634
|
+
**Recipe · props**
|
|
635
|
+
|
|
636
|
+
- 默认包裹列表/表单主列
|
|
637
|
+
- 表单页 width="narrow"
|
|
638
|
+
- bands 默认即可;勿再套多余 padding 容器
|
|
639
|
+
|
|
640
|
+
**Anti-patterns**
|
|
641
|
+
|
|
642
|
+
- 按钮间距用 PageContent → Space / Flex
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
### Flex
|
|
646
|
+
|
|
647
|
+
**When**
|
|
648
|
+
|
|
649
|
+
- 同一行控件需要 gap 和对齐
|
|
650
|
+
- 工具栏内操作组、筛选控件组
|
|
651
|
+
|
|
652
|
+
**Avoid when**
|
|
653
|
+
|
|
654
|
+
- 整个页面区块的 padding 和垂直 rhythm
|
|
655
|
+
|
|
656
|
+
**Recipe · props**
|
|
657
|
+
|
|
658
|
+
- gap / align / justify 按需(或等价 class/prop)
|
|
659
|
+
- 筛选行、工具栏内组优先 Flex
|
|
660
|
+
- 不要用 Flex 代替 PageContent 的页面 padding
|
|
661
|
+
|
|
662
|
+
**Anti-patterns**
|
|
663
|
+
|
|
664
|
+
- 整页垂直节奏用 Flex → PageContent
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
### Space
|
|
668
|
+
|
|
669
|
+
**When**
|
|
670
|
+
|
|
671
|
+
- 简单 wrap 控件组且不需要 justify 语义
|
|
672
|
+
- 表格行内操作按钮组
|
|
673
|
+
|
|
674
|
+
**Avoid when**
|
|
675
|
+
|
|
676
|
+
- 页面级标题与主操作两端对齐
|
|
677
|
+
|
|
678
|
+
**Recipe · props**
|
|
679
|
+
|
|
680
|
+
- 包裹 MButton 组
|
|
681
|
+
- 行内操作常用 size="small" text 按钮
|
|
682
|
+
- Dialog #footer 内可用 Space + justify-content:flex-end
|
|
683
|
+
|
|
684
|
+
**Anti-patterns**
|
|
685
|
+
|
|
686
|
+
- 标题与主按钮两端对齐只用 Space → PageToolbar / Flex justify
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
### Grid
|
|
690
|
+
|
|
691
|
+
**When**
|
|
692
|
+
|
|
693
|
+
- KPI 卡片、仪表盘双栏、响应式列布局
|
|
694
|
+
|
|
695
|
+
**Avoid when**
|
|
696
|
+
|
|
697
|
+
- 单个筛选行或表单字段列
|
|
698
|
+
|
|
699
|
+
**Recipe · props**
|
|
700
|
+
|
|
701
|
+
- 列数用文档 columns / 响应式配置
|
|
702
|
+
- KPI:Grid + MPageStat
|
|
703
|
+
- gap 走 token,勿写裸 px
|
|
704
|
+
|
|
705
|
+
**Anti-patterns**
|
|
706
|
+
|
|
707
|
+
- 筛选行用 Grid → Flex / PageFilters
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
## `page-section-choice` — 如何选择页面区块组件
|
|
713
|
+
|
|
714
|
+
> 这是筛选区、标题区、表单表面、KPI 还是图表占位?
|
|
715
|
+
|
|
716
|
+
### PageFilters
|
|
717
|
+
|
|
718
|
+
**When**
|
|
719
|
+
|
|
720
|
+
- 列表页或搜索页的筛选/查询区域
|
|
721
|
+
- 需要统一浅色背景与边框
|
|
722
|
+
|
|
723
|
+
**Avoid when**
|
|
724
|
+
|
|
725
|
+
- 普通表单字段分组
|
|
726
|
+
- KPI 指标展示
|
|
727
|
+
|
|
728
|
+
**Recipe · props**
|
|
729
|
+
|
|
730
|
+
- 内放 MInput / MSelect 等筛选控件
|
|
731
|
+
- 可 collapsible + #advanced
|
|
732
|
+
- 不要外包 MCard
|
|
733
|
+
|
|
734
|
+
**Recipe · slots**
|
|
735
|
+
|
|
736
|
+
- #advanced 高级筛选
|
|
737
|
+
|
|
738
|
+
**Anti-patterns**
|
|
739
|
+
|
|
740
|
+
- 表单字段组用 PageFilters → PageSection form / Fieldset
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
### PageToolbar
|
|
744
|
+
|
|
745
|
+
**When**
|
|
746
|
+
|
|
747
|
+
- 页面标题 + 右侧主操作
|
|
748
|
+
- 列表页新建按钮区域
|
|
749
|
+
|
|
750
|
+
**Avoid when**
|
|
751
|
+
|
|
752
|
+
- 带长描述的表单引导区
|
|
753
|
+
|
|
754
|
+
**Recipe · props**
|
|
755
|
+
|
|
756
|
+
- 左侧标题、右侧主按钮
|
|
757
|
+
- 主按钮 severity="primary";全页仅一个主按钮
|
|
758
|
+
- 批量操作条也可放工具栏区
|
|
759
|
+
|
|
760
|
+
**Recipe · slots**
|
|
761
|
+
|
|
762
|
+
- #actions 右侧操作
|
|
763
|
+
|
|
764
|
+
**Anti-patterns**
|
|
765
|
+
|
|
766
|
+
- 需要长描述仍用 Toolbar → PageHeader
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
### PageHeader
|
|
770
|
+
|
|
771
|
+
**When**
|
|
772
|
+
|
|
773
|
+
- 页面标题 + 描述文案
|
|
774
|
+
- 表单页/详情页引导
|
|
775
|
+
|
|
776
|
+
**Avoid when**
|
|
777
|
+
|
|
778
|
+
- 只有标题和单个主按钮的列表工具栏
|
|
779
|
+
|
|
780
|
+
**Recipe · props**
|
|
781
|
+
|
|
782
|
+
- title + description
|
|
783
|
+
- 详情可用 #breadcrumb / #tags(放 MStatus)
|
|
784
|
+
- 列表页仅标题+新建时优先 PageToolbar
|
|
785
|
+
|
|
786
|
+
**Recipe · slots**
|
|
787
|
+
|
|
788
|
+
- #breadcrumb
|
|
789
|
+
- #tags / #actions
|
|
790
|
+
|
|
791
|
+
**Anti-patterns**
|
|
792
|
+
|
|
793
|
+
- 纯列表标题+新建仍用 Header → PageToolbar
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
### PageSection
|
|
797
|
+
|
|
798
|
+
**When**
|
|
799
|
+
|
|
800
|
+
- 表单主体表面 (variant="form")
|
|
801
|
+
- 底栏操作区 (variant="actions")
|
|
802
|
+
|
|
803
|
+
**Avoid when**
|
|
804
|
+
|
|
805
|
+
- 列表页筛选区
|
|
806
|
+
- KPI 卡片
|
|
807
|
+
|
|
808
|
+
**Recipe · props**
|
|
809
|
+
|
|
810
|
+
- variant="form" 表单主体
|
|
811
|
+
- variant="actions" 底栏
|
|
812
|
+
- 可选 title 分组
|
|
813
|
+
|
|
814
|
+
**Anti-patterns**
|
|
815
|
+
|
|
816
|
+
- variant="form" 外再套 MCard → 双边框
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
### PageStat
|
|
820
|
+
|
|
821
|
+
**When**
|
|
822
|
+
|
|
823
|
+
- 仪表盘 KPI 单指标卡
|
|
824
|
+
- 需要 label/value/trend/icon 结构
|
|
825
|
+
|
|
826
|
+
**Avoid when**
|
|
827
|
+
|
|
828
|
+
- 普通内容分组
|
|
829
|
+
- 表格或表单
|
|
830
|
+
|
|
831
|
+
**Recipe · props**
|
|
832
|
+
|
|
833
|
+
- label + value
|
|
834
|
+
- trend / trendSeverity / trendDirection 按需
|
|
835
|
+
- loading 骨架;layout card|plain
|
|
836
|
+
|
|
837
|
+
**Anti-patterns**
|
|
838
|
+
|
|
839
|
+
- 普通段落用 PageStat → 文案或 Card
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
### PagePlaceholder
|
|
843
|
+
|
|
844
|
+
**When**
|
|
845
|
+
|
|
846
|
+
- 图表、地图或媒体区域尚未接入
|
|
847
|
+
- 需要 dashed 占位表面
|
|
848
|
+
|
|
849
|
+
**Avoid when**
|
|
850
|
+
|
|
851
|
+
- 真实数据表格或表单
|
|
852
|
+
|
|
853
|
+
**Recipe · props**
|
|
854
|
+
|
|
855
|
+
- description 说明待接入内容
|
|
856
|
+
- 可配合 MEmpty 于 Card 内(仪表盘图表区)
|
|
857
|
+
- minHeight 避免占位塌缩
|
|
858
|
+
|
|
859
|
+
**Anti-patterns**
|
|
860
|
+
|
|
861
|
+
- 真实表格用 Placeholder → MTable
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
## `page-scroll-choice` — 页面滚动如何选择
|
|
867
|
+
|
|
868
|
+
> 这是整页滚动、组件内置滚动,还是业务手写的局部滚动区?
|
|
869
|
+
|
|
870
|
+
### MLayout fillViewport
|
|
871
|
+
|
|
872
|
+
**When**
|
|
873
|
+
|
|
874
|
+
- 整页后台列表/表单/仪表盘
|
|
875
|
+
- 需要 Header + Content + 可选 Sider 的应用骨架
|
|
876
|
+
- 页面主滚动应随 Layout 主题化
|
|
877
|
+
|
|
878
|
+
**Avoid when**
|
|
879
|
+
|
|
880
|
+
- 单个卡片内部的小块内容
|
|
881
|
+
- 需要业务自行控制滚动的 Dialog/Drawer 内容
|
|
882
|
+
|
|
883
|
+
**Recipe · props**
|
|
884
|
+
|
|
885
|
+
- MLayout fill-viewport(或 :fill-viewport="true")
|
|
886
|
+
- 内容放 MLayoutContent
|
|
887
|
+
- 是否再 fill 表格:见下方「MPageContent fill + MTable fill」判断
|
|
888
|
+
- 侧栏用 MLayoutSider + MMenu,不是随便一个 Drawer
|
|
889
|
+
|
|
890
|
+
**Anti-patterns**
|
|
891
|
+
|
|
892
|
+
- 在 Layout 外再包一层 100vh 滚动 → 去掉
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
### MPageContent fill + MTable fill
|
|
896
|
+
|
|
897
|
+
**When**
|
|
898
|
+
|
|
899
|
+
- 全视口后台列表,页面主任务就是浏览一张表
|
|
900
|
+
- 内容高度表格会留下大块空白、分页悬在中间不好看
|
|
901
|
+
- 希望只有表体滚动、分页贴在页面最下方
|
|
902
|
+
|
|
903
|
+
**Avoid when**
|
|
904
|
+
|
|
905
|
+
- 仪表盘/详情里的嵌入小表
|
|
906
|
+
- 内容本身很短、内容高度即可
|
|
907
|
+
- 整页应作为文档滚动(长筛选+说明+表格)
|
|
908
|
+
- Dialog / Drawer 内表格
|
|
909
|
+
|
|
910
|
+
**Recipe · props**
|
|
911
|
+
|
|
912
|
+
- 先判断是否适合 fill,再写 MPageContent fill + MTable fill
|
|
913
|
+
- paginator 或同级 MPagination
|
|
914
|
+
- 适合时不要手写 min-height / calc
|
|
915
|
+
|
|
916
|
+
**Anti-patterns**
|
|
917
|
+
|
|
918
|
+
- 嵌入/短页硬套 fill → 去掉
|
|
919
|
+
- 适合 fill 却手写 calc → 改用 fill
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
### MScrollbar
|
|
923
|
+
|
|
924
|
+
**When**
|
|
925
|
+
|
|
926
|
+
- 业务自行限高的卡片正文、侧栏、日志列表,且希望主题化滚动条
|
|
927
|
+
- Dialog / Drawer 等内容区需要主题滚动时由业务显式包一层
|
|
928
|
+
- 组件未内置滚动、又需要统一滚动外观时
|
|
929
|
+
|
|
930
|
+
**Avoid when**
|
|
931
|
+
|
|
932
|
+
- Dialog / Drawer / Popover / Splitter 等用户内容插槽被组件库强行包滚动
|
|
933
|
+
- Textarea 等原生控件自身的滚动
|
|
934
|
+
- MTable / MLayoutContent / Select 弹出层等已内置滚动的区域
|
|
935
|
+
|
|
936
|
+
**Recipe · props**
|
|
937
|
+
|
|
938
|
+
- 显式限高后包裹内容
|
|
939
|
+
- 只包业务自有滚动区
|
|
940
|
+
- 不要叠两层滚动
|
|
941
|
+
|
|
942
|
+
**Anti-patterns**
|
|
943
|
+
|
|
944
|
+
- MTable 外包 MScrollbar → 去掉外层
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
### Built-in (no extra wrapper)
|
|
948
|
+
|
|
949
|
+
**When**
|
|
950
|
+
|
|
951
|
+
- MLayout、MTable、MVirtualScroller、菜单/下拉面板等已内置 MScrollbar
|
|
952
|
+
- 浮层菜单与子菜单(Dropdown/ContextMenu/TieredMenu/Menu flyout)
|
|
953
|
+
|
|
954
|
+
**Avoid when**
|
|
955
|
+
|
|
956
|
+
- 在已内置滚动的组件外再包一层滚动容器
|
|
957
|
+
|
|
958
|
+
**Recipe · props**
|
|
959
|
+
|
|
960
|
+
- 信任组件内置滚动,不再包一层
|
|
961
|
+
- Table / LayoutContent 直接用
|
|
962
|
+
- 菜单/Select 弹出层也不要外包滚动
|
|
963
|
+
|
|
964
|
+
**Anti-patterns**
|
|
965
|
+
|
|
966
|
+
- 双重滚动条 → 去掉业务包装层
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
---
|
|
970
|
+
|
|
971
|
+
## `surface-nesting-choice` — 如何避免双边框与多余容器
|
|
972
|
+
|
|
973
|
+
> 内容是否已经被 Page 组件或 Table 提供了边界?
|
|
974
|
+
|
|
975
|
+
### PageContent + MTable
|
|
976
|
+
|
|
977
|
+
**When**
|
|
978
|
+
|
|
979
|
+
- 列表页数据表格
|
|
980
|
+
- MPageFilters 已提供筛选区边界
|
|
981
|
+
|
|
982
|
+
**Avoid when**
|
|
983
|
+
|
|
984
|
+
- 需要独立卡片标题的内容模块
|
|
985
|
+
|
|
986
|
+
**Recipe · props**
|
|
987
|
+
|
|
988
|
+
- MPageContent > MPageFilters + MTable
|
|
989
|
+
- 表格直接放 PageContent,不套 Card
|
|
990
|
+
- 高度:全视口主列表再考虑 fill;嵌入/短页跳过
|
|
991
|
+
- 空态用 Table #empty + MEmpty
|
|
992
|
+
|
|
993
|
+
**Anti-patterns**
|
|
994
|
+
|
|
995
|
+
- Table 外包 MCard → 去掉 Card
|
|
996
|
+
- 嵌入表硬套 fill → 去掉 fill
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
### MCard
|
|
1000
|
+
|
|
1001
|
+
**When**
|
|
1002
|
+
|
|
1003
|
+
- 仪表盘中的图表区/明细区
|
|
1004
|
+
- 需要 card 标题的内容模块
|
|
1005
|
+
|
|
1006
|
+
**Avoid when**
|
|
1007
|
+
|
|
1008
|
+
- 列表页表格外层
|
|
1009
|
+
- 筛选区外层
|
|
1010
|
+
|
|
1011
|
+
**Recipe · props**
|
|
1012
|
+
|
|
1013
|
+
- title + 正文;图表待接入可用 MEmpty
|
|
1014
|
+
- shadow 按仪表盘需要选择
|
|
1015
|
+
- 仅用于需要独立标题的模块
|
|
1016
|
+
|
|
1017
|
+
**Anti-patterns**
|
|
1018
|
+
|
|
1019
|
+
- 列表筛选区套 Card → PageFilters 自带边界
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
### PageSection
|
|
1023
|
+
|
|
1024
|
+
**When**
|
|
1025
|
+
|
|
1026
|
+
- 表单页主体或 actions 底栏
|
|
1027
|
+
- 需要统一 form surface
|
|
1028
|
+
|
|
1029
|
+
**Avoid when**
|
|
1030
|
+
|
|
1031
|
+
- 再套 MCard variant form 导致双边框
|
|
1032
|
+
|
|
1033
|
+
**Recipe · props**
|
|
1034
|
+
|
|
1035
|
+
- variant="form" / variant="actions"
|
|
1036
|
+
- 不要再外包 MCard
|
|
1037
|
+
- 表单字段放 form 段,按钮放 actions 段
|
|
1038
|
+
|
|
1039
|
+
**Anti-patterns**
|
|
1040
|
+
|
|
1041
|
+
- PageSection form + MCard → 只留 PageSection
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
---
|
|
1045
|
+
|
|
1046
|
+
## `loading-choice` — 如何选择加载反馈
|
|
1047
|
+
|
|
1048
|
+
> 这是区域或全屏等待、已知布局的占位、可量化进度,还是只需要阻止交互?
|
|
1049
|
+
|
|
1050
|
+
### Loading
|
|
1051
|
+
|
|
1052
|
+
**When**
|
|
1053
|
+
|
|
1054
|
+
- 一块区域或整页正在等待,用户暂时不能操作这块内容
|
|
1055
|
+
- 需要加载文案、多种动效,或用 v-loading / loading.service 盖住已有节点
|
|
1056
|
+
- 全屏提交、保存、跳转前的短暂等待
|
|
1057
|
+
|
|
1058
|
+
**Avoid when**
|
|
1059
|
+
|
|
1060
|
+
- 布局已知、希望用占位块避免跳动
|
|
1061
|
+
- 进度可以量化
|
|
1062
|
+
- 只是按钮自己的 loading 状态
|
|
1063
|
+
|
|
1064
|
+
**Recipe · props**
|
|
1065
|
+
|
|
1066
|
+
- 包裹内容:MLoading :loading="…" 或 v-loading
|
|
1067
|
+
- 全屏:fullscreen / loading.service
|
|
1068
|
+
- 按钮等待用 Button loading,不要盖整表
|
|
1069
|
+
|
|
1070
|
+
**Anti-patterns**
|
|
1071
|
+
|
|
1072
|
+
- 区域遮罩用 ProgressSpinner → Loading / v-loading
|
|
1073
|
+
- 按钮转圈用整页 Loading → Button :loading
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
### Skeleton
|
|
1077
|
+
|
|
1078
|
+
**When**
|
|
1079
|
+
|
|
1080
|
+
- 内容结构已知,用占位块表示即将出现的卡片、文本或列表
|
|
1081
|
+
- 仪表盘或详情初次进入
|
|
1082
|
+
|
|
1083
|
+
**Avoid when**
|
|
1084
|
+
|
|
1085
|
+
- 需要明确的“正在加载”遮罩
|
|
1086
|
+
- 进度可量化
|
|
1087
|
+
|
|
1088
|
+
**Recipe · props**
|
|
1089
|
+
|
|
1090
|
+
- shape rectangle|circle;text + repeat 模拟多行
|
|
1091
|
+
- width / height 贴近最终布局
|
|
1092
|
+
- PageStat 可用自带 loading
|
|
1093
|
+
|
|
1094
|
+
**Anti-patterns**
|
|
1095
|
+
|
|
1096
|
+
- 未知时长又要文案遮罩 → Loading
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
### ProgressBar
|
|
1100
|
+
|
|
1101
|
+
**When**
|
|
1102
|
+
|
|
1103
|
+
- 进度有百分比或可估算完成度
|
|
1104
|
+
- 上传、导入等长任务
|
|
1105
|
+
|
|
1106
|
+
**Avoid when**
|
|
1107
|
+
|
|
1108
|
+
- 不知道还要等多久
|
|
1109
|
+
- 只是挡住一块区域
|
|
1110
|
+
|
|
1111
|
+
**Recipe · props**
|
|
1112
|
+
|
|
1113
|
+
- value 0–100(或文档等价)
|
|
1114
|
+
- 显示百分比文案
|
|
1115
|
+
- 上传/导入长任务优先
|
|
1116
|
+
|
|
1117
|
+
**Anti-patterns**
|
|
1118
|
+
|
|
1119
|
+
- 未知进度用 ProgressBar → Loading
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
### ProgressSpinner
|
|
1123
|
+
|
|
1124
|
+
**When**
|
|
1125
|
+
|
|
1126
|
+
- 行内或控件旁需要一个很小的转圈,不盖住内容
|
|
1127
|
+
|
|
1128
|
+
**Avoid when**
|
|
1129
|
+
|
|
1130
|
+
- 区域遮罩、全屏等待或带文案的加载态
|
|
1131
|
+
|
|
1132
|
+
**Recipe · props**
|
|
1133
|
+
|
|
1134
|
+
- 仅作行内指示
|
|
1135
|
+
- 尺寸保持小
|
|
1136
|
+
- 不要盖住整块区域
|
|
1137
|
+
|
|
1138
|
+
**Anti-patterns**
|
|
1139
|
+
|
|
1140
|
+
- 当页面遮罩用 Spinner → Loading
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
### BlockUI
|
|
1144
|
+
|
|
1145
|
+
**When**
|
|
1146
|
+
|
|
1147
|
+
- 只需要阻止点击,不需要表达“正在加载”
|
|
1148
|
+
|
|
1149
|
+
**Avoid when**
|
|
1150
|
+
|
|
1151
|
+
- 用户需要知道正在等待结果
|
|
1152
|
+
|
|
1153
|
+
**Recipe · props**
|
|
1154
|
+
|
|
1155
|
+
- blocked 控制遮罩
|
|
1156
|
+
- 包裹需要禁用的区域
|
|
1157
|
+
- 无加载文案时用,有文案改 Loading
|
|
1158
|
+
|
|
1159
|
+
**Anti-patterns**
|
|
1160
|
+
|
|
1161
|
+
- 需要“加载中”文案仍用 BlockUI → Loading
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
---
|
|
1165
|
+
|
|
1166
|
+
## `status-label-choice` — 如何选择状态与标签
|
|
1167
|
+
|
|
1168
|
+
> 这是行内业务状态、分类标签、可移除实体,还是挂在控件上的数量?
|
|
1169
|
+
|
|
1170
|
+
### Status
|
|
1171
|
+
|
|
1172
|
+
**When**
|
|
1173
|
+
|
|
1174
|
+
- 表格单元格或标题旁的业务状态
|
|
1175
|
+
- 需要圆点或语义图标加短文案
|
|
1176
|
+
|
|
1177
|
+
**Avoid when**
|
|
1178
|
+
|
|
1179
|
+
- 可关闭的分类标签
|
|
1180
|
+
- 挂在按钮上的数字
|
|
1181
|
+
|
|
1182
|
+
**Recipe · props**
|
|
1183
|
+
|
|
1184
|
+
- label + severity
|
|
1185
|
+
- variant 默认 dot;可用 tag|text
|
|
1186
|
+
- 表格状态列优先 MStatus,不要一排实心 Tag
|
|
1187
|
+
|
|
1188
|
+
**Anti-patterns**
|
|
1189
|
+
|
|
1190
|
+
- 可关闭分类用 Status → Tag closable
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
### Tag
|
|
1194
|
+
|
|
1195
|
+
**When**
|
|
1196
|
+
|
|
1197
|
+
- 分类、筛选结果或可关闭标签
|
|
1198
|
+
- 需要比 Status 更像芯片的表面
|
|
1199
|
+
|
|
1200
|
+
**Avoid when**
|
|
1201
|
+
|
|
1202
|
+
- 只是一行里的轻量状态
|
|
1203
|
+
- 带图片且代表一个可移除实体
|
|
1204
|
+
|
|
1205
|
+
**Recipe · props**
|
|
1206
|
+
|
|
1207
|
+
- value 或默认插槽文案
|
|
1208
|
+
- severity;closable + @close
|
|
1209
|
+
- rounded / bordered 按需
|
|
1210
|
+
|
|
1211
|
+
**Recipe · events**
|
|
1212
|
+
|
|
1213
|
+
- @close
|
|
1214
|
+
|
|
1215
|
+
**Anti-patterns**
|
|
1216
|
+
|
|
1217
|
+
- 行内启用/停用状态用 Tag → Status
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
### Chip
|
|
1221
|
+
|
|
1222
|
+
**When**
|
|
1223
|
+
|
|
1224
|
+
- 短实体信息,可带图标、图片和移除
|
|
1225
|
+
|
|
1226
|
+
**Avoid when**
|
|
1227
|
+
|
|
1228
|
+
- 纯状态色点
|
|
1229
|
+
- 只是分类色块
|
|
1230
|
+
|
|
1231
|
+
**Recipe · props**
|
|
1232
|
+
|
|
1233
|
+
- label;icon 或 image
|
|
1234
|
+
- removable + @remove
|
|
1235
|
+
- severity 按需
|
|
1236
|
+
|
|
1237
|
+
**Recipe · events**
|
|
1238
|
+
|
|
1239
|
+
- @remove
|
|
1240
|
+
|
|
1241
|
+
**Anti-patterns**
|
|
1242
|
+
|
|
1243
|
+
- 纯状态点用 Chip → Status
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
### Badge
|
|
1247
|
+
|
|
1248
|
+
**When**
|
|
1249
|
+
|
|
1250
|
+
- 角标数量或圆点,附着在按钮、头像等控件上
|
|
1251
|
+
|
|
1252
|
+
**Avoid when**
|
|
1253
|
+
|
|
1254
|
+
- 独立成行的状态文案
|
|
1255
|
+
|
|
1256
|
+
**Recipe · props**
|
|
1257
|
+
|
|
1258
|
+
- value 数量;省略则圆点
|
|
1259
|
+
- severity;max 封顶
|
|
1260
|
+
- 默认插槽包裹宿主控件
|
|
1261
|
+
|
|
1262
|
+
**Recipe · slots**
|
|
1263
|
+
|
|
1264
|
+
- 默认插槽:被角标包裹的控件
|
|
1265
|
+
|
|
1266
|
+
**Anti-patterns**
|
|
1267
|
+
|
|
1268
|
+
- 独立状态文案用 Badge → Status / Tag
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
---
|
|
1272
|
+
|
|
1273
|
+
## `empty-result-choice` — 空态还是结果页
|
|
1274
|
+
|
|
1275
|
+
> 这是没有数据,还是流程已经结束的成功、失败或 HTTP 状态?
|
|
1276
|
+
|
|
1277
|
+
### Empty
|
|
1278
|
+
|
|
1279
|
+
**When**
|
|
1280
|
+
|
|
1281
|
+
- 列表没有行
|
|
1282
|
+
- 筛选没有命中
|
|
1283
|
+
- 首次使用,需要引导创建
|
|
1284
|
+
|
|
1285
|
+
**Avoid when**
|
|
1286
|
+
|
|
1287
|
+
- 接口失败
|
|
1288
|
+
- 无权限
|
|
1289
|
+
- 页面不存在
|
|
1290
|
+
- 提交成功回执
|
|
1291
|
+
|
|
1292
|
+
**Recipe · props**
|
|
1293
|
+
|
|
1294
|
+
- title + description
|
|
1295
|
+
- icon 或 illustration 按需(默认即可)
|
|
1296
|
+
- 表格内放在 #empty
|
|
1297
|
+
|
|
1298
|
+
**Recipe · slots**
|
|
1299
|
+
|
|
1300
|
+
- #extra 放下一步按钮(创建…)
|
|
1301
|
+
|
|
1302
|
+
**Anti-patterns**
|
|
1303
|
+
|
|
1304
|
+
- 403/404 用 Empty → Result
|
|
1305
|
+
- #action → #extra
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
### Result
|
|
1309
|
+
|
|
1310
|
+
**When**
|
|
1311
|
+
|
|
1312
|
+
- 提交成功或失败的终点页
|
|
1313
|
+
- 403 / 404 / 500 等阻断状态
|
|
1314
|
+
- 需要明确的下一步(返回、重试、回首页)
|
|
1315
|
+
|
|
1316
|
+
**Avoid when**
|
|
1317
|
+
|
|
1318
|
+
- 正常的无数据
|
|
1319
|
+
- 表格内部的空行
|
|
1320
|
+
|
|
1321
|
+
**Recipe · props**
|
|
1322
|
+
|
|
1323
|
+
- status:success|error|403|404|500 等
|
|
1324
|
+
- title + description
|
|
1325
|
+
- size 按页面比重
|
|
1326
|
+
|
|
1327
|
+
**Recipe · slots**
|
|
1328
|
+
|
|
1329
|
+
- #footer 逃逸/下一步按钮
|
|
1330
|
+
|
|
1331
|
+
**Anti-patterns**
|
|
1332
|
+
|
|
1333
|
+
- 表格无数据用 Result → Empty
|
|
1334
|
+
- 操作插槽写成 #extra → #footer
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
---
|
|
1338
|
+
|
|
1339
|
+
## `action-menu-choice` — 如何选择菜单
|
|
1340
|
+
|
|
1341
|
+
> 这是按钮上的操作项、侧栏导航、右键菜单,还是全局命令搜索?
|
|
1342
|
+
|
|
1343
|
+
### Dropdown
|
|
1344
|
+
|
|
1345
|
+
**When**
|
|
1346
|
+
|
|
1347
|
+
- 从按钮或图标打开一组操作
|
|
1348
|
+
- 编辑、删除、更多
|
|
1349
|
+
|
|
1350
|
+
**Avoid when**
|
|
1351
|
+
|
|
1352
|
+
- 表单里选一个枚举值
|
|
1353
|
+
- 常驻侧栏导航
|
|
1354
|
+
|
|
1355
|
+
**Recipe · props**
|
|
1356
|
+
|
|
1357
|
+
- :model / items 操作项
|
|
1358
|
+
- 触发器放默认插槽(按钮/图标)
|
|
1359
|
+
- 危险项用文档 severity / 确认流
|
|
1360
|
+
|
|
1361
|
+
**Anti-patterns**
|
|
1362
|
+
|
|
1363
|
+
- 表单枚举用 Dropdown → Select
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
### Menu
|
|
1367
|
+
|
|
1368
|
+
**When**
|
|
1369
|
+
|
|
1370
|
+
- 后台侧栏或页面内的常驻导航
|
|
1371
|
+
- 需要选中项与路由同步
|
|
1372
|
+
|
|
1373
|
+
**Avoid when**
|
|
1374
|
+
|
|
1375
|
+
- 一次性操作菜单
|
|
1376
|
+
- 右键弹出
|
|
1377
|
+
|
|
1378
|
+
**Recipe · props**
|
|
1379
|
+
|
|
1380
|
+
- :model 导航项(含 icon)
|
|
1381
|
+
- 放在 MLayoutSider 内
|
|
1382
|
+
- 与路由选中态同步
|
|
1383
|
+
|
|
1384
|
+
**Anti-patterns**
|
|
1385
|
+
|
|
1386
|
+
- 行内「更多」用 Menu → Dropdown
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
### ContextMenu
|
|
1390
|
+
|
|
1391
|
+
**When**
|
|
1392
|
+
|
|
1393
|
+
- 在指针位置弹出,通常由右键触发
|
|
1394
|
+
|
|
1395
|
+
**Avoid when**
|
|
1396
|
+
|
|
1397
|
+
- 可见的导航
|
|
1398
|
+
- 表单选择
|
|
1399
|
+
|
|
1400
|
+
**Recipe · props**
|
|
1401
|
+
|
|
1402
|
+
- :model 菜单项
|
|
1403
|
+
- 绑定上下文目标事件(右键)
|
|
1404
|
+
- 在指针位置打开,不是侧栏常驻
|
|
1405
|
+
|
|
1406
|
+
**Anti-patterns**
|
|
1407
|
+
|
|
1408
|
+
- 常驻导航用 ContextMenu → Menu
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
### CommandMenu
|
|
1412
|
+
|
|
1413
|
+
**When**
|
|
1414
|
+
|
|
1415
|
+
- 全局搜索命令或跳转
|
|
1416
|
+
- 键盘优先,例如 Cmd/Ctrl+K
|
|
1417
|
+
|
|
1418
|
+
**Avoid when**
|
|
1419
|
+
|
|
1420
|
+
- 少量固定操作放在按钮旁即可
|
|
1421
|
+
|
|
1422
|
+
**Recipe · props**
|
|
1423
|
+
|
|
1424
|
+
- v-model 开关
|
|
1425
|
+
- 命令列表 / 搜索按文档
|
|
1426
|
+
- 全局快捷键打开
|
|
1427
|
+
|
|
1428
|
+
**Anti-patterns**
|
|
1429
|
+
|
|
1430
|
+
- 两三个固定操作也用 CommandMenu → Dropdown / 按钮
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
### Menubar
|
|
1434
|
+
|
|
1435
|
+
**When**
|
|
1436
|
+
|
|
1437
|
+
- 顶部应用菜单,项很多且分组
|
|
1438
|
+
|
|
1439
|
+
**Avoid when**
|
|
1440
|
+
|
|
1441
|
+
- 侧栏只有一层链接
|
|
1442
|
+
|
|
1443
|
+
**Recipe · props**
|
|
1444
|
+
|
|
1445
|
+
- :model 分组菜单
|
|
1446
|
+
- 放在顶栏而非侧栏
|
|
1447
|
+
- 项多且需要分组时再用
|
|
1448
|
+
|
|
1449
|
+
**Anti-patterns**
|
|
1450
|
+
|
|
1451
|
+
- 侧栏单层链接用 Menubar → Menu
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
---
|
|
1455
|
+
|
|
1456
|
+
## `feedback-choice` — 如何选择操作反馈
|
|
1457
|
+
|
|
1458
|
+
> 这是一句话结果、带详情的通知,还是要留在表单里的错误?
|
|
1459
|
+
|
|
1460
|
+
### message
|
|
1461
|
+
|
|
1462
|
+
**When**
|
|
1463
|
+
|
|
1464
|
+
- CRUD / 保存 / 删除后的单行结果
|
|
1465
|
+
- 不需要单独标题和详情
|
|
1466
|
+
|
|
1467
|
+
**Avoid when**
|
|
1468
|
+
|
|
1469
|
+
- 需要 summary + detail
|
|
1470
|
+
- 错误必须留在表单直到修正
|
|
1471
|
+
|
|
1472
|
+
**Recipe · props**
|
|
1473
|
+
|
|
1474
|
+
- import { message } from 'morya-ui'
|
|
1475
|
+
- message.success('已保存') / info / warn / error
|
|
1476
|
+
- 大多数操作反馈的默认选择
|
|
1477
|
+
|
|
1478
|
+
**Anti-patterns**
|
|
1479
|
+
|
|
1480
|
+
- toast.add({ summary: '已保存' }) → message.success('已保存')
|
|
1481
|
+
- <MMessage severity> 当内嵌 Alert → errorMessage / role="alert"
|
|
1482
|
+
|
|
1483
|
+
|
|
1484
|
+
### toast
|
|
1485
|
+
|
|
1486
|
+
**When**
|
|
1487
|
+
|
|
1488
|
+
- 需要 summary + detail
|
|
1489
|
+
- 异步/后台任务完成感
|
|
1490
|
+
|
|
1491
|
+
**Avoid when**
|
|
1492
|
+
|
|
1493
|
+
- 只有一句话的 CRUD 回执
|
|
1494
|
+
|
|
1495
|
+
**Recipe · props**
|
|
1496
|
+
|
|
1497
|
+
- import { toast } from 'morya-ui'
|
|
1498
|
+
- toast.success({ summary, detail })
|
|
1499
|
+
- 不要用 toast 代替默认 message
|
|
1500
|
+
|
|
1501
|
+
**Anti-patterns**
|
|
1502
|
+
|
|
1503
|
+
- 单行「已保存」用 toast → message
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
### field errorMessage / role="alert"
|
|
1507
|
+
|
|
1508
|
+
**When**
|
|
1509
|
+
|
|
1510
|
+
- 字段校验错误需常驻
|
|
1511
|
+
- 登录/鉴权失败需留在表单区
|
|
1512
|
+
|
|
1513
|
+
**Avoid when**
|
|
1514
|
+
|
|
1515
|
+
- 一次性操作成功提示
|
|
1516
|
+
|
|
1517
|
+
**Recipe · props**
|
|
1518
|
+
|
|
1519
|
+
- 字段:invalid + errorMessage
|
|
1520
|
+
- 表单级:token 样式的 role="alert" 条(见 login-page)
|
|
1521
|
+
- <MMessage> 只是 message 宿主,不是内嵌 Alert
|
|
1522
|
+
|
|
1523
|
+
**Anti-patterns**
|
|
1524
|
+
|
|
1525
|
+
- 登录失败只闪 Toast → 表单区 alert / errorMessage
|
|
1526
|
+
- 编造 MMessage severity 插槽 Alert API
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
---
|
|
1530
|
+
|
|
1531
|
+
## `confirm-choice` — 如何选择确认框
|
|
1532
|
+
|
|
1533
|
+
> 危险操作需要居中确认,还是贴着触发点的轻量确认?
|
|
1534
|
+
|
|
1535
|
+
### ConfirmDialog
|
|
1536
|
+
|
|
1537
|
+
**When**
|
|
1538
|
+
|
|
1539
|
+
- 删除/不可逆操作需要明确确认
|
|
1540
|
+
- 需要标题、说明与阻塞式决定
|
|
1541
|
+
- 列表行删除的默认选择
|
|
1542
|
+
|
|
1543
|
+
**Avoid when**
|
|
1544
|
+
|
|
1545
|
+
- 只需贴着按钮的轻量确认
|
|
1546
|
+
- 复杂编辑表单(那是 Dialog)
|
|
1547
|
+
|
|
1548
|
+
**Recipe · props**
|
|
1549
|
+
|
|
1550
|
+
- v-model / modelValue
|
|
1551
|
+
- header + message
|
|
1552
|
+
- acceptLabel / rejectLabel
|
|
1553
|
+
- acceptSeverity="danger" 用于删除
|
|
1554
|
+
|
|
1555
|
+
**Recipe · events**
|
|
1556
|
+
|
|
1557
|
+
- @accept 执行删除
|
|
1558
|
+
- @reject 关闭
|
|
1559
|
+
|
|
1560
|
+
**Anti-patterns**
|
|
1561
|
+
|
|
1562
|
+
- 普通 Dialog 手写「确定/取消」删除 → ConfirmDialog
|
|
1563
|
+
- 编辑表单误用 ConfirmDialog → Dialog + Form
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
### ConfirmPopup
|
|
1567
|
+
|
|
1568
|
+
**When**
|
|
1569
|
+
|
|
1570
|
+
- 确认应贴着触发按钮/行内操作
|
|
1571
|
+
- 文案短、不需要大对话框
|
|
1572
|
+
|
|
1573
|
+
**Avoid when**
|
|
1574
|
+
|
|
1575
|
+
- 需要醒目标题与强阻塞感的删除
|
|
1576
|
+
- 无定位目标时的全局确认
|
|
1577
|
+
|
|
1578
|
+
**Recipe · props**
|
|
1579
|
+
|
|
1580
|
+
- v-model / modelValue
|
|
1581
|
+
- message;acceptSeverity="danger" 按需
|
|
1582
|
+
- target 锚定触发元素(或 position)
|
|
1583
|
+
- placement top|bottom|left|right
|
|
1584
|
+
|
|
1585
|
+
**Recipe · events**
|
|
1586
|
+
|
|
1587
|
+
- @accept / @reject
|
|
1588
|
+
|
|
1589
|
+
**Anti-patterns**
|
|
1590
|
+
|
|
1591
|
+
- 无 target 的全局危险确认 → ConfirmDialog
|