@morya-ui/mcp 0.2.3 → 0.2.5

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/dist/patterns.js CHANGED
@@ -40,7 +40,8 @@ export const pagePatterns = [
40
40
  { component: 'Select', role: '枚举或状态筛选' },
41
41
  { component: 'Button', role: '查询、新增和行操作' },
42
42
  { component: 'Table', role: '数据展示', reason: 'paginator 启用内置分页' },
43
- { component: 'Tag', role: '业务状态展示' },
43
+ { component: 'Tag', role: '业务状态展示(分类/可关闭)', required: false },
44
+ { component: 'Status', role: '行内状态圆点+文案', required: false },
44
45
  { component: 'Dialog', role: '编辑或删除确认', required: false },
45
46
  ],
46
47
  structure: [
@@ -65,7 +66,7 @@ export const pagePatterns = [
65
66
  '新增、保存等主操作使用 primary MButton',
66
67
  '查询等次要操作使用 secondary 或 outlined MButton',
67
68
  '删除使用 danger MButton,并配合 MDialog 或 MConfirmDialog',
68
- '业务状态使用 MTag,不使用 Button severity 表达状态',
69
+ '业务状态优先使用 MStatus(圆点+文案)或 MTag(分类标签),不使用 Button severity 表达状态',
69
70
  '间距、颜色、圆角优先使用 --m-* 设计令牌,不直接硬编码色板',
70
71
  ],
71
72
  interactionRules: [
@@ -163,7 +164,10 @@ export const pagePatterns = [
163
164
  { component: 'GridItem', role: '栅格子项' },
164
165
  { component: 'Card', role: '图表与列表明细分区' },
165
166
  { component: 'Icon', role: 'KPI 图标', required: false },
166
- { component: 'Tag', role: '状态和告警级别' },
167
+ { component: 'Tag', role: '分类标签和告警级别', required: false },
168
+ { component: 'Status', role: '行内状态圆点+文案', required: false },
169
+ { component: 'Empty', role: '明细表空态', required: false },
170
+ { component: 'Result', role: '接口失败结果区', required: false },
167
171
  { component: 'Table', role: '明细数据', required: false },
168
172
  { component: 'Button', role: '刷新、查看详情和快捷操作', required: false },
169
173
  { component: 'Skeleton', role: '初始加载占位', required: false },
@@ -186,8 +190,8 @@ export const pagePatterns = [
186
190
  content: '图表和明细按业务优先级排列,重要告警靠前',
187
191
  responsive: '多列网格在窄屏降为单列或两列',
188
192
  },
189
- styleRules: ['指标使用 text hierarchy,不用大面积高饱和背景', '状态和告警使用 MTag 等语义组件', '图表容器使用 Card 和 --m-* Token 保持表面一致', '实时刷新操作使用 secondary 或 text MButton'],
190
- interactionRules: ['首次加载使用 Skeleton', '无数据和接口错误必须有明确状态', '刷新中禁用重复请求并保留上次数据', '告警需要可追踪到详情或处理入口'],
193
+ styleRules: ['指标使用 text hierarchy,不用大面积高饱和背景', '状态用 MStatus / 告警级别用 MTag', '图表容器使用 Card 和 --m-* Token 保持表面一致', '实时刷新操作使用 secondary 或 text MButton'],
194
+ interactionRules: ['首次加载使用 Skeleton', '无数据用 MEmpty;接口错误用 MResult 或 Message', '刷新中禁用重复请求并保留上次数据', '告警需要可追踪到详情或处理入口'],
191
195
  avoid: ['不要把所有信息都做成 KPI 卡片', '不要使用颜色作为唯一告警表达', '不要用固定像素绝对定位实现响应式布局'],
192
196
  },
193
197
  {
@@ -219,17 +223,29 @@ export const pagePatterns = [
219
223
  titleEn: 'Empty state / no results page',
220
224
  description: '用于首次使用、搜索无结果、资源已清空或暂时没有内容的场景。',
221
225
  descriptionEn: 'For first use, no search results, empty resources, or temporarily unavailable content.',
226
+ goldenPage: 'docs/golden-pages/empty-state.vue',
222
227
  keywords: ['空状态', '无数据', '无结果', '首次使用', 'empty', 'no results', 'no data', 'zero state'],
223
228
  components: [
224
- { component: 'DataView', role: '列表或网格空态承载' },
229
+ { component: 'PageContent', role: '承载空态的内容区', required: false },
230
+ { component: 'PageToolbar', role: '保留列表上下文标题与主操作', required: false },
231
+ { component: 'Empty', role: '空态主体:图标、标题、说明与操作', required: true },
232
+ { component: 'Icon', role: '空态视觉锚点(也可由 Empty icon 提供)', required: false },
225
233
  { component: 'Button', role: '创建、重置筛选或返回', required: false },
234
+ { component: 'Table', role: '表格 #empty 插槽承载', required: false },
235
+ { component: 'DataView', role: '列表或网格空态承载', required: false },
226
236
  { component: 'Card', role: '在列表或详情容器中承载空态', required: false },
227
237
  ],
228
- structure: ['Container or Card', '└── DataView / Table #empty', ' ├── Explanation', ' └── Primary recovery action (optional)'],
238
+ structure: [
239
+ 'MPageContent (or MTable #empty)',
240
+ '└── MEmpty',
241
+ ' ├── icon / image',
242
+ ' ├── title + description',
243
+ ' └── #extra primary + optional secondary MButton',
244
+ ],
229
245
  layout: { page: '空态在当前内容区域内居中,不一定占满整个视口', content: '说明原因、下一步动作和可选的辅助信息', responsive: '保持按钮可触达,窄屏垂直排列' },
230
- styleRules: ['空态文案使用中性、可行动的语气', '主恢复动作使用 primary MButton,次动作使用 text', '不要用错误色表达正常的无数据状态'],
246
+ styleRules: ['空态文案使用中性、可行动的语气', '主恢复动作使用 primary MButton,次动作使用 text', '不要用错误色表达正常的无数据状态', '颜色与间距使用 --m-* Token'],
231
247
  interactionRules: ['搜索无结果提供清除筛选或修改条件入口', '首次使用提供创建或导入入口', '保留页面标题和上下文导航'],
232
- avoid: ['不要只显示“暂无数据”而没有下一步', '不要把无数据和接口错误混为一谈'],
248
+ avoid: ['不要只显示“暂无数据”而没有下一步', '不要把无数据和接口错误混为一谈', '不要堆 emoji 或促销贴纸'],
233
249
  },
234
250
  {
235
251
  id: 'auth-page',
@@ -237,22 +253,79 @@ export const pagePatterns = [
237
253
  titleEn: 'Login / authentication page',
238
254
  description: '用于登录、注册、找回密码和二次认证流程。',
239
255
  descriptionEn: 'For login, registration, password recovery, and second-factor authentication flows.',
256
+ goldenPage: 'docs/golden-pages/login-page.vue',
240
257
  keywords: ['登录', '注册', '认证', '密码', '验证码', 'login', 'register', 'authentication', 'password', 'otp'],
241
258
  components: [
242
- { component: 'Card', role: '认证表面' },
259
+ { component: 'ConfigProvider', role: '应用根包裹' },
243
260
  { component: 'Form', role: '认证字段校验' },
244
- { component: 'FormItem', role: '字段标签和错误信息', required: false, reason: '由 MForm 同目录导出,作为表单子结构使用' },
245
- { component: 'Input', role: '账号或密码字段' },
261
+ { component: 'FormItem', role: '字段标签和错误信息', required: false },
262
+ { component: 'Input', role: '账号字段' },
263
+ { component: 'InputPassword', role: '密码字段' },
246
264
  { component: 'InputOtp', role: '验证码字段', required: false },
247
265
  { component: 'Button', role: '提交认证' },
248
- { component: 'Message', role: '页面级反馈', required: false },
266
+ { component: 'Space', role: '主次操作排列', required: false },
249
267
  ],
250
- structure: ['AuthLayout', '└── Card', ' └── Form', ' ├── Identity fields', ' ├── Recovery / alternative links', ' └── Submit action'],
251
- layout: { page: '认证表单使用窄 max-width 并保持视觉聚焦', form: '字段垂直排列,提交按钮 fluid', 'feedback': '错误信息靠近字段,认证失败提供页面级总结' },
252
- styleRules: ['密码字段使用 InputPassword documented password API', '提交按钮使用 primary + fluid', '不要用高对比装饰削弱错误信息和焦点状态', '品牌视觉可定制,但控件状态仍使用 --m-* Token'],
253
- interactionRules: ['提交中显示 loading 并防止重复提交', '错误不清空用户已填写的非敏感字段', '密码输入和验证码输入提供可访问名称', '支持键盘提交和清晰焦点顺序'],
268
+ structure: [
269
+ 'MConfigProvider',
270
+ '└── Split or centered shell',
271
+ ' ├── Brand panel (optional Express craft)',
272
+ ' └── Form panel',
273
+ ' ├── Persistent form-level alert (token-styled) when needed',
274
+ ' ├── MForm + MInput / MInputPassword',
275
+ ' └── Submit + recovery links',
276
+ ],
277
+ layout: { page: '认证表单使用窄 max-width 并保持视觉聚焦', form: '字段垂直排列', feedback: '字段错误用 errorMessage;表单级常驻错误用 token 告警条,勿默认 Toast' },
278
+ styleRules: ['密码字段使用 MInputPassword', '提交按钮使用 primary', '品牌视觉可定制,但颜色仍映射 --m-*', '不要用高对比装饰削弱错误信息和焦点状态'],
279
+ interactionRules: ['提交中显示 loading 并防止重复提交', '错误不清空用户已填写的非敏感字段', '支持键盘提交和清晰焦点顺序'],
254
280
  avoid: ['不要用 placeholder 代替字段 label', '不要把所有认证错误只放在 Toast 中', '不要在错误时回显密码'],
255
281
  },
282
+ {
283
+ id: 'marketing-landing',
284
+ title: '营销落地页',
285
+ titleEn: 'Marketing landing page',
286
+ description: '用于产品官网、发布页、定价前导等公开营销表面;首屏单一任务,控件仍用 morya-ui。',
287
+ descriptionEn: 'Public marketing surfaces (product home, launch, pre-pricing). One job in the first viewport; controls still use morya-ui.',
288
+ goldenPage: 'docs/golden-pages/landing-page.vue',
289
+ keywords: [
290
+ '落地页',
291
+ '营销',
292
+ '官网',
293
+ '首页',
294
+ 'landing',
295
+ 'marketing',
296
+ 'pricing',
297
+ 'hero',
298
+ '产品介绍',
299
+ ],
300
+ components: [
301
+ { component: 'ConfigProvider', role: '应用根包裹' },
302
+ { component: 'Button', role: 'CTA' },
303
+ { component: 'Tag', role: '能力标签', required: false },
304
+ { component: 'Accordion', role: 'FAQ', required: false },
305
+ { component: 'Card', role: '套餐或能力卡', required: false },
306
+ ],
307
+ structure: [
308
+ 'MConfigProvider',
309
+ '├── Nav (brand + links + CTA)',
310
+ '├── Hero (brand, one headline, one lead, CTA group, one visual)',
311
+ '├── Sections (one job each)',
312
+ '└── Footer',
313
+ ],
314
+ layout: {
315
+ page: '首屏单一构图;勿做成后台仪表盘',
316
+ hero: '品牌 + 标题 + 一句支持文案 + CTA + 一个主视觉',
317
+ sections: '每节一个目的与一个短说明',
318
+ responsive: '导航链接可折叠;能力卡降为单列',
319
+ },
320
+ styleRules: [
321
+ '交互控件使用 MButton / MTag / MAccordion 等',
322
+ '颜色与间距使用 --m-*,可用 color-mix 做氛围',
323
+ '避开紫渐变、奶油衬线陶土、报纸风等 AI 默认脸(除非 brief 指定)',
324
+ '首屏不要堆统计条、促销胶囊、日程碎片',
325
+ ],
326
+ interactionRules: ['CTA 指向明确下一步', 'FAQ 用 Accordion 降低长页噪声', '尊重 prefers-reduced-motion 若加动画'],
327
+ avoid: ['不要用第二套 UI 库', '不要把 Ops 的 MPageFilters 壳套在营销页上', '不要用 inset 小卡片代替首屏主视觉'],
328
+ },
256
329
  {
257
330
  id: 'wizard-form',
258
331
  title: '分步表单 / 向导',
@@ -285,16 +358,18 @@ export const pagePatterns = [
285
358
  components: [
286
359
  { component: 'Breadcrumb', role: '页面层级导航' },
287
360
  { component: 'Card', role: '内容分组表面' },
288
- { component: 'Tag', role: '状态展示' },
361
+ { component: 'Status', role: '标题旁轻量状态(圆点+文案)', required: false },
362
+ { component: 'Tag', role: '分类/强调态标签', required: false },
289
363
  { component: 'Divider', role: '内容分组分隔', required: false },
290
364
  { component: 'Button', role: '编辑、返回和危险操作' },
291
365
  { component: 'Dialog', role: '危险操作确认', required: false },
366
+ { component: 'Result', role: '资源不存在或无权访问时的结果页', required: false },
292
367
  ],
293
368
  structure: [
294
369
  'Page',
295
370
  '├── Breadcrumb',
296
371
  '├── PageHeader',
297
- '│ ├── Title + Status Tag',
372
+ '│ ├── Title + MStatus (or MTag)',
298
373
  '│ └── Actions',
299
374
  '├── Summary Card',
300
375
  '├── Properties Card',
@@ -307,14 +382,14 @@ export const pagePatterns = [
307
382
  actions: '编辑为主操作,返回为次操作,删除放在低强调区域',
308
383
  },
309
384
  styleRules: [
310
- '状态使用 MTag 的语义色',
385
+ '轻量状态优先 MStatus;需要芯片感或可关闭时用 MTag',
311
386
  '内容分组使用 MCard,必要时用 MDivider 分隔',
312
387
  '编辑使用 primary 或 outlined MButton,删除使用 danger',
313
388
  '不使用大面积自定义背景色覆盖组件库 surface Token',
314
389
  ],
315
390
  interactionRules: [
316
391
  '详情加载中使用 Skeleton 或 ProgressSpinner',
317
- '资源不存在时提供明确的 Table #empty 或 DataView 空态和返回入口',
392
+ '资源不存在用 MResult status="404";列表空数据用 MEmpty,不要混用',
318
393
  '危险操作必须确认并在成功后刷新或离开当前详情页',
319
394
  ],
320
395
  avoid: [
@@ -323,8 +398,198 @@ export const pagePatterns = [
323
398
  '不要让详情页的操作按钮分散在多个无关区域',
324
399
  ],
325
400
  },
401
+ {
402
+ id: 'result-page',
403
+ title: '结果页 / 阻断页',
404
+ titleEn: 'Result / terminal page',
405
+ description: '用于提交成功、失败回执、403、404、500 等流程终点或阻断场景。',
406
+ descriptionEn: 'Terminal outcomes: success, failure, 403, 404, 500, and other blocking pages.',
407
+ keywords: [
408
+ '结果',
409
+ '成功',
410
+ '失败',
411
+ '403',
412
+ '404',
413
+ '500',
414
+ '无权',
415
+ '不存在',
416
+ 'result',
417
+ 'success',
418
+ 'error',
419
+ 'forbidden',
420
+ 'not found',
421
+ ],
422
+ components: [
423
+ { component: 'Result', role: '结果主体:图标、标题、说明与操作', required: true },
424
+ { component: 'Button', role: '下一步:返回、重试、查看详情', required: false },
425
+ { component: 'PageContent', role: '承载结果区', required: false },
426
+ ],
427
+ structure: [
428
+ 'MPageContent (optional shell)',
429
+ '└── MResult',
430
+ ' ├── status icon',
431
+ ' ├── title + description',
432
+ ' └── #extra primary + optional secondary MButton',
433
+ ],
434
+ layout: {
435
+ page: '结果在内容区居中,不一定占满整屏',
436
+ content: '说明发生了什么,以及用户下一步能做什么',
437
+ responsive: '操作按钮可触达,窄屏垂直排列',
438
+ },
439
+ styleRules: [
440
+ '使用 MResult 的 status 语义,不要手写大图标+文案拼盘',
441
+ '成功/失败用对应 severity 色;403/404 保持中性',
442
+ '主恢复动作使用 primary MButton,次动作使用 secondary 或 text',
443
+ '颜色与间距使用 --m-* Token',
444
+ ],
445
+ interactionRules: [
446
+ '成功后提供查看详情或返回列表',
447
+ '失败提供重试或联系支持入口',
448
+ '不要把无数据空态做成 Result;空态用 MEmpty',
449
+ ],
450
+ avoid: [
451
+ '不要用 Empty 表达 403/404/提交失败',
452
+ '不要只用颜色表达结果而无标题文案',
453
+ '不要在结果页堆砌无关营销内容',
454
+ ],
455
+ },
456
+ ];
457
+ /** Advisory page-writing standards for MCP and human authors — not enforced blockers. */
458
+ export const pageStandards = [
459
+ {
460
+ id: 'layout-shell',
461
+ title: '页面骨架',
462
+ titleEn: 'Page shell',
463
+ recommend: [
464
+ '后台页根布局使用 MLayout fillViewport',
465
+ 'MLayoutContent 内使用 MPageContent 统一 padding 与区块间距',
466
+ '写整页前先 get_golden_page 复制对应类型结构',
467
+ ],
468
+ recommendEn: [
469
+ 'Use MLayout fillViewport as the admin page root',
470
+ 'Place MPageContent inside MLayoutContent for consistent padding and section gap',
471
+ 'Call get_golden_page before writing a full page and copy the matching structure',
472
+ ],
473
+ discouraged: [
474
+ '手写 min-height:100vh',
475
+ '在 MLayoutContent 上写 padding/gap',
476
+ '嵌套多层 MPageContent',
477
+ ],
478
+ discouragedEn: [
479
+ 'Hand-written min-height:100vh',
480
+ 'Padding/gap on MLayoutContent instead of MPageContent',
481
+ 'Nesting multiple MPageContent shells',
482
+ ],
483
+ mcp: { snippet: 'layout-app-shell' },
484
+ },
485
+ {
486
+ id: 'page-sections',
487
+ title: '页面区块组件',
488
+ titleEn: 'Page section components',
489
+ recommend: [
490
+ '筛选区用 MPageFilters,标题+操作用 MPageToolbar,表单区用 MPageSection',
491
+ '列表页 MTable 直接放在 MPageContent 内',
492
+ '同行控件用 MSpace / MFlex;区块之间依赖 MPageContent 的 gap',
493
+ '局部区块优先 get_page_snippet(filters / toolbar / form-actions 等)',
494
+ ],
495
+ recommendEn: [
496
+ 'Use MPageFilters, MPageToolbar, and MPageSection for filters, headers/actions, and forms',
497
+ 'Place MTable directly in MPageContent on list pages',
498
+ 'Use MSpace / MFlex for same-row controls; let MPageContent gap separate sections',
499
+ 'Prefer get_page_snippet for local blocks such as filters, toolbar, or form-actions',
500
+ ],
501
+ discouraged: [
502
+ '手写 .page-filters / .page-toolbar 类',
503
+ '用 MCard 或带 padding 的容器再包 MPageFilters / MPageSection / MPageToolbar',
504
+ '在已有 MPage* 区块之间再写 margin 叠间距',
505
+ ],
506
+ discouragedEn: [
507
+ 'Hand-written .page-filters / .page-toolbar classes',
508
+ 'Wrapping MPageFilters / MPageSection / MPageToolbar with MCard or extra padded containers',
509
+ 'Adding margin between MPage* siblings that PageContent gap already spaces',
510
+ ],
511
+ mcp: { decision: 'surface-nesting-choice' },
512
+ },
513
+ {
514
+ id: 'scroll',
515
+ title: '滚动',
516
+ titleEn: 'Scroll',
517
+ recommend: [
518
+ '组件内置滚动区(Layout 壳、菜单/下拉面板、Table 视口等)使用内置 MScrollbar',
519
+ 'Dialog / Drawer / Popover / Splitter 等内容区不强制主题滚动;需要时由业务自行包 MScrollbar',
520
+ '已内置滚动的组件通常无需再外包一层',
521
+ ],
522
+ recommendEn: [
523
+ 'Component-owned scroll chrome (Layout shell, menu/select panels, Table viewport) uses built-in MScrollbar',
524
+ 'Do not force themed scroll into Dialog / Drawer / Popover / Splitter content; apps can wrap MScrollbar when needed',
525
+ 'Components that already scroll internally usually need no extra wrapper',
526
+ ],
527
+ discouraged: [
528
+ '在 Dialog / Drawer / Popover / Splitter / Textarea 等用户内容区强行内置 MScrollbar',
529
+ '业务代码定制 ::-webkit-scrollbar 替代组件内置滚动',
530
+ '重复包裹已内置滚动的组件',
531
+ ],
532
+ discouragedEn: [
533
+ 'Forcing MScrollbar into user content areas such as Dialog, Drawer, Popover, Splitter, or Textarea',
534
+ '::-webkit-scrollbar styling instead of component-owned scroll chrome',
535
+ 'Extra scroll wrappers around components that already scroll',
536
+ ],
537
+ mcp: { snippet: 'scrollable-panel', decision: 'page-scroll-choice' },
538
+ },
539
+ {
540
+ id: 'tokens',
541
+ title: '设计令牌',
542
+ titleEn: 'Design tokens',
543
+ recommend: ['颜色、间距、圆角、字号优先 --m-* Token', '控件宽度等局部尺寸可用 inline style'],
544
+ recommendEn: [
545
+ 'Prefer --m-* tokens for color, spacing, radius, and typography',
546
+ 'Inline styles are fine for local control widths',
547
+ ],
548
+ discouraged: ['页面级 hex / 裸 rgb() 色值', '维护第二套色板变量'],
549
+ discouragedEn: ['Page-level hex or raw rgb() colors', 'Maintaining a second color palette'],
550
+ },
551
+ {
552
+ id: 'feedback',
553
+ title: '操作反馈',
554
+ titleEn: 'Action feedback',
555
+ recommend: [
556
+ '单行结果(已保存/已删除)默认 message.success / error',
557
+ '需要标题+补充说明时用 toast',
558
+ '危险操作配合 MConfirmDialog',
559
+ ],
560
+ recommendEn: [
561
+ 'Default single-line results to message.success / error',
562
+ 'Use toast when a summary plus detail is needed',
563
+ 'Pair destructive actions with MConfirmDialog',
564
+ ],
565
+ discouraged: ['只有一行文案却用 toast', '删除等危险操作无确认'],
566
+ discouragedEn: ['Toast for single-line-only feedback', 'Destructive actions without confirmation'],
567
+ mcp: { decision: 'overlay-choice' },
568
+ },
569
+ {
570
+ id: 'accessibility',
571
+ title: '无障碍',
572
+ titleEn: 'Accessibility',
573
+ recommend: [
574
+ '图标按钮提供 aria-label 或 ariaLabel',
575
+ '表单控件有可见 label 或等价可访问名称',
576
+ '筛选区、表格等语义区域可加 aria-label',
577
+ ],
578
+ recommendEn: [
579
+ 'Provide aria-label or ariaLabel on icon-only buttons',
580
+ 'Give form controls a visible label or equivalent accessible name',
581
+ 'Add aria-label to semantic regions such as filter bars or tables when helpful',
582
+ ],
583
+ },
326
584
  ];
327
585
  export const designRules = {
586
+ meta: {
587
+ nature: 'recommended',
588
+ noteZh: 'standards 为页面书写标准(推荐实践);特殊场景可偏离。validate_page 仅给出参考建议。',
589
+ noteEn: 'standards are recommended page-writing practices; deviations are fine when justified. validate_page is advisory only.',
590
+ },
591
+ /** Page writing standards — single source for layout, scroll, tokens, feedback, a11y, etc. */
592
+ standards: pageStandards,
328
593
  tokens: {
329
594
  colors: ['--m-color-primary', '--m-color-surface', '--m-color-text', '--m-color-border'],
330
595
  spacing: '--m-space-*',
@@ -334,8 +599,8 @@ export const designRules = {
334
599
  },
335
600
  composition: {
336
601
  workflow: [
337
- 'For full pages: recommend_page then get_golden_page before writing layout code.',
338
- 'For local edits: get_page_snippet(section) for filters/toolbar/form-actions/KPI blocks instead of reading the whole golden page.',
602
+ 'For full pages: recommend_page get_golden_page get_design_rules.',
603
+ 'For local edits: get_page_snippet(section) for filters/toolbar/form-actions/KPI/scrollable-panel blocks.',
339
604
  'Use MLayout fillViewport as the app shell; put MPageContent inside MLayoutContent.',
340
605
  'Prefer MPage* components over scoped CSS for filters, toolbars, headers, form surfaces, and KPI cards.',
341
606
  'Use MSpace or MFlex for control groups inside MPageFilters; use MPageToolbar for title + primary action.',
@@ -351,6 +616,7 @@ export const designRules = {
351
616
  'dashboard-kpi-grid',
352
617
  'dashboard-chart-card',
353
618
  'layout-app-shell',
619
+ 'scrollable-panel',
354
620
  ],
355
621
  pageStack: {
356
622
  list: ['MLayout', 'MLayoutHeader', 'MLayoutContent', 'MPageContent', 'MPageFilters', 'MPageToolbar', 'MTable'],
@@ -372,7 +638,7 @@ export const designRules = {
372
638
  'Double borders on filter + table wrapper',
373
639
  ],
374
640
  },
375
- goldenPages: ['list-page', 'form-page', 'dashboard-page'],
641
+ goldenPages: ['list-page', 'form-page', 'dashboard-page', 'login-page', 'landing-page', 'empty-state'],
376
642
  },
377
643
  actions: {
378
644
  primary: { component: 'MButton', props: ['severity omitted or primary'] },
@@ -381,8 +647,10 @@ export const designRules = {
381
647
  cancel: { component: 'MButton', props: ['severity="secondary"', 'text'] },
382
648
  },
383
649
  status: {
384
- component: 'MTag',
650
+ preferred: 'MStatus',
651
+ chip: 'MTag',
385
652
  mapping: { active: 'success', pending: 'warn', disabled: 'secondary', error: 'danger' },
653
+ note: '行内轻量状态用 MStatus;芯片/可关闭标签用 MTag',
386
654
  },
387
655
  feedback: {
388
656
  default: 'message',
@@ -396,19 +664,33 @@ export const designRules = {
396
664
  when: ['同时需要标题与补充说明', '后台任务/批量结果含统计', '异步通知感、角落堆叠'],
397
665
  avoid: ['仅有单行文案时不要使用 Toast'],
398
666
  },
667
+ empty: {
668
+ component: 'MEmpty',
669
+ when: ['列表无数据', '筛选无结果', '首次使用'],
670
+ avoid: ['不要用错误色表达正常空态', '不要用 MResult 表达无数据'],
671
+ },
672
+ result: {
673
+ component: 'MResult',
674
+ when: ['提交成功/失败页', '403 / 404 / 500', '流程终点回执'],
675
+ avoid: ['不要用手写图标+文案替代 MResult', '不要用 MEmpty 表达阻断错误'],
676
+ },
399
677
  inlineMessage: {
400
- component: 'MMessage',
401
- when: ['登录/表单区常驻错误', '页面级错误需与表单同区展示'],
678
+ api: 'field errorMessage | token-styled role=alert',
679
+ when: [
680
+ '登录/表单区常驻错误:优先字段 errorMessage',
681
+ '表单级总结:使用 --m-* 样式的 role=alert 条(见 login-page 黄金样例)',
682
+ 'MMessage 组件当前主要为 message 服务宿主,勿臆造 severity 子节点 API',
683
+ ],
402
684
  },
403
685
  doc: 'docs/feedback-message-vs-toast.md',
404
686
  },
405
687
  global: [
406
- '优先使用组件库组件和 --m-* Token,不重复维护第二套色板',
407
- '操作反馈默认 message;无 detail 禁止用 toast.add({ summary only })',
408
- '图标按钮必须提供 aria-label ariaLabel',
409
- '表单字段必须有可见 label 或等价的可访问名称',
410
- '浮层默认 Teleport 到 body;只有有明确布局约束时才改 appendTo',
411
- '优先使用组件的 documented variant,不通过深层 CSS 覆盖内部样式',
688
+ '优先使用组件库组件和 --m-* Token',
689
+ '操作反馈默认 message;仅一行文案时优先于 toast',
690
+ '空态用 MEmpty;结果/阻断页用 MResult;行内状态优先 MStatus',
691
+ '图标按钮建议提供 aria-label;表单字段建议有可见 label',
692
+ '浮层默认 Teleport 到 body;有明确布局约束时再改 appendTo',
693
+ '优先使用组件 documented variant,少写深层 CSS 覆盖',
412
694
  ],
413
695
  };
414
696
  export function findPattern(input) {
@@ -1,4 +1,4 @@
1
- import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import type { Catalog } from './catalog.js';
3
3
  export declare function registerCatalogResources(server: McpServer, catalog: Catalog): void;
4
4
  export declare function countCatalogResources(catalog: Catalog): number;