@morya-ui/mcp 0.2.7 → 0.2.9

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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "generatedAt": "2026-09-18T07:52:19.611Z",
3
- "catalogGeneratedAt": "2026-09-18T07:52:14.544Z",
2
+ "generatedAt": "2026-09-21T09:57:51.741Z",
3
+ "catalogGeneratedAt": "2026-09-21T09:57:47.817Z",
4
4
  "components": [
5
5
  {
6
6
  "id": "Accordion",
@@ -1604,6 +1604,41 @@
1604
1604
  "missing": []
1605
1605
  }
1606
1606
  },
1607
+ {
1608
+ "id": "Loading",
1609
+ "exportName": "MLoading",
1610
+ "examples": 14,
1611
+ "props": {
1612
+ "total": 11,
1613
+ "covered": 4,
1614
+ "missing": [
1615
+ "ariaLabel",
1616
+ "background",
1617
+ "customClass",
1618
+ "fullscreen",
1619
+ "lock",
1620
+ "delay",
1621
+ "pt"
1622
+ ]
1623
+ },
1624
+ "events": {
1625
+ "total": 0,
1626
+ "covered": 0,
1627
+ "missing": []
1628
+ },
1629
+ "slots": {
1630
+ "total": 2,
1631
+ "covered": 1,
1632
+ "missing": [
1633
+ "indicator"
1634
+ ]
1635
+ },
1636
+ "methods": {
1637
+ "total": 0,
1638
+ "covered": 0,
1639
+ "missing": []
1640
+ }
1641
+ },
1607
1642
  {
1608
1643
  "id": "MegaMenu",
1609
1644
  "exportName": "MMegaMenu",
@@ -3194,8 +3229,8 @@
3194
3229
  }
3195
3230
  ],
3196
3231
  "summary": {
3197
- "components": 92,
3198
- "componentsWithMissingCoverage": 87,
3199
- "totalExamples": 789
3232
+ "components": 93,
3233
+ "componentsWithMissingCoverage": 88,
3234
+ "totalExamples": 803
3200
3235
  }
3201
3236
  }
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  /**
3
3
  * 黄金样例:仪表盘页
4
- * @see DESIGN.md §3
4
+ * @see DESIGN.md · morya-ui-pages references/page-layouts.md · visual-craft § Ops polish
5
5
  */
6
6
  import {
7
7
  MBreadcrumb,
@@ -16,6 +16,7 @@ import {
16
16
  MPageHeader,
17
17
  MPagePlaceholder,
18
18
  MPageStat,
19
+ MStatus,
19
20
  MTable,
20
21
  MTag,
21
22
  zhCN,
@@ -32,7 +33,7 @@ const recentColumns = [
32
33
  { key: 'id', label: '工单号', width: 96 },
33
34
  { key: 'title', label: '标题' },
34
35
  { key: 'priority', label: '优先级', width: 96 },
35
- { key: 'status', label: '状态', width: 96 },
36
+ { key: 'status', label: '状态', width: 110 },
36
37
  ]
37
38
 
38
39
  const recentRows = [
@@ -47,11 +48,23 @@ function prioritySeverity(p: string) {
47
48
  return 'secondary'
48
49
  }
49
50
 
51
+ function priorityLabel(p: string) {
52
+ if (p === 'high') return '高'
53
+ if (p === 'medium') return '中'
54
+ return '低'
55
+ }
56
+
50
57
  function statusLabel(s: string) {
51
58
  if (s === 'open') return '待处理'
52
59
  if (s === 'progress') return '进行中'
53
60
  return '已完成'
54
61
  }
62
+
63
+ function statusSeverity(s: string) {
64
+ if (s === 'open') return 'warn'
65
+ if (s === 'progress') return 'info'
66
+ return 'success'
67
+ }
55
68
  </script>
56
69
 
57
70
  <template>
@@ -63,7 +76,10 @@ function statusLabel(s: string) {
63
76
 
64
77
  <MLayoutContent>
65
78
  <MPageContent density="spacious">
66
- <MPageHeader title="仪表盘" />
79
+ <MPageHeader
80
+ title="运营概览"
81
+ description="关注今日活跃与待处理工单,异常优先下钻。"
82
+ />
67
83
 
68
84
  <MGrid :cols="4" :x-gap="16" :y-gap="16" responsive="screen">
69
85
  <MGridItem v-for="item in stats" :key="item.label" :span="1">
@@ -77,20 +93,37 @@ function statusLabel(s: string) {
77
93
  </MGridItem>
78
94
  </MGrid>
79
95
 
80
- <MGrid :cols="2" :x-gap="16" :y-gap="16">
96
+ <MGrid :cols="2" :x-gap="16" :y-gap="16" responsive="screen">
81
97
  <MGridItem :span="1">
82
98
  <MCard title="趋势概览">
83
- <MPagePlaceholder aria-label="图表占位" description="图表区域(接入 ECharts / 业务组件)" />
99
+ <MPagePlaceholder
100
+ aria-label="图表占位"
101
+ description="接入图表组件后展示近 7 日活跃与转化。"
102
+ />
84
103
  </MCard>
85
104
  </MGridItem>
86
105
  <MGridItem :span="1">
87
106
  <MCard title="最近工单">
88
- <MTable :columns="recentColumns" :rows="recentRows" size="small" :paginator="false" bordered>
107
+ <MTable
108
+ :columns="recentColumns"
109
+ :rows="recentRows"
110
+ size="small"
111
+ :paginator="false"
112
+ bordered
113
+ row-key="id"
114
+ aria-label="最近工单"
115
+ >
89
116
  <template #cell-priority="{ value }">
90
- <MTag :value="String(value)" :severity="prioritySeverity(String(value))" />
117
+ <MTag
118
+ :value="priorityLabel(String(value))"
119
+ :severity="prioritySeverity(String(value))"
120
+ />
91
121
  </template>
92
122
  <template #cell-status="{ value }">
93
- <MTag :value="statusLabel(String(value))" severity="info" />
123
+ <MStatus
124
+ :label="statusLabel(String(value))"
125
+ :severity="statusSeverity(String(value))"
126
+ />
94
127
  </template>
95
128
  </MTable>
96
129
  </MCard>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  /**
3
3
  * 黄金样例:列表空状态(Flow)
4
- * @see DESIGN.md §3 · morya-ui-pages surfaces § Flow
4
+ * @see DESIGN.md · page-layouts.md · surfaces § Flow
5
5
  * 可嵌在列表页 MPageContent / MTable #empty 中;此处给出完整可运行骨架。
6
6
  */
7
7
  import {
@@ -53,6 +53,10 @@ import {
53
53
 
54
54
  <style scoped>
55
55
  .empty-state-shell {
56
+ display: grid;
57
+ place-items: center;
58
+ min-height: 18rem;
59
+ padding: var(--m-space-8) var(--m-space-6);
56
60
  border: 1px dashed color-mix(in srgb, var(--m-color-border) 80%, var(--m-color-primary));
57
61
  border-radius: var(--m-radius-md);
58
62
  background:
@@ -63,4 +67,21 @@ import {
63
67
  ),
64
68
  var(--m-color-surface);
65
69
  }
70
+
71
+ @media (prefers-reduced-motion: no-preference) {
72
+ .empty-state-shell {
73
+ animation: empty-in 400ms ease both;
74
+ }
75
+ }
76
+
77
+ @keyframes empty-in {
78
+ from {
79
+ opacity: 0;
80
+ transform: translateY(0.35rem);
81
+ }
82
+ to {
83
+ opacity: 1;
84
+ transform: translateY(0);
85
+ }
86
+ }
66
87
  </style>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  /**
3
3
  * 黄金样例:表单页
4
- * @see DESIGN.md §3
4
+ * @see DESIGN.md · morya-ui-pages references/page-layouts.md
5
5
  */
6
6
  import {
7
7
  MBreadcrumb,
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  /**
3
3
  * 黄金样例:营销落地页(Express)
4
- * @see DESIGN.md §3 · morya-ui-pages surfaces § Express
4
+ * @see DESIGN.md · page-layouts.md · surfaces § Express
5
5
  * 首屏单一任务;控件用 M*;色彩只走 --m-*;避开 AI 默认脸。
6
6
  */
7
7
  import { MAccordion, MButton, MConfigProvider, MTag, zhCN } from 'morya-ui'
@@ -219,6 +219,36 @@ const faqTabs = [
219
219
  font-weight: 600;
220
220
  }
221
221
 
222
+ @media (prefers-reduced-motion: no-preference) {
223
+ .landing-hero__track span {
224
+ animation: landing-fade-up 480ms ease both;
225
+ }
226
+
227
+ .landing-hero__track span:nth-child(2) {
228
+ animation-delay: 60ms;
229
+ }
230
+
231
+ .landing-hero__track span:nth-child(3) {
232
+ animation-delay: 120ms;
233
+ }
234
+
235
+ .landing-hero__track span:nth-child(4) {
236
+ animation-delay: 180ms;
237
+ }
238
+ }
239
+
240
+ @keyframes landing-fade-up {
241
+ from {
242
+ opacity: 0;
243
+ transform: translateY(0.4rem);
244
+ }
245
+
246
+ to {
247
+ opacity: 1;
248
+ transform: translateY(0);
249
+ }
250
+ }
251
+
222
252
  .landing-section {
223
253
  padding: clamp(2.5rem, 6vw, 4rem) clamp(1.25rem, 4vw, 3rem);
224
254
  max-width: 72rem;
@@ -1,12 +1,13 @@
1
1
  <script setup lang="ts">
2
2
  /**
3
3
  * 黄金样例:列表页
4
- * @see DESIGN.md §3
4
+ * @see DESIGN.md · morya-ui-pages references/page-layouts.md · visual-craft § Ops polish
5
5
  */
6
6
  import {
7
7
  MBreadcrumb,
8
8
  MButton,
9
9
  MConfigProvider,
10
+ MEmpty,
10
11
  MInput,
11
12
  MLayout,
12
13
  MLayoutContent,
@@ -18,8 +19,8 @@ import {
18
19
  MPageToolbar,
19
20
  MSelect,
20
21
  MSpace,
22
+ MStatus,
21
23
  MTable,
22
- MTag,
23
24
  zhCN,
24
25
  } from 'morya-ui'
25
26
  import { ref } from 'vue'
@@ -31,6 +32,7 @@ const siderCollapsed = ref(false)
31
32
  const menuModel = [
32
33
  { key: 'users', label: '用户管理', icon: 'user', to: '/users' },
33
34
  { key: 'roles', label: '角色管理', icon: 'shield', to: '/roles' },
35
+ { key: 'settings', label: '系统设置', icon: 'settings', to: '/settings' },
34
36
  ]
35
37
 
36
38
  const statusOptions = [
@@ -41,9 +43,9 @@ const statusOptions = [
41
43
 
42
44
  const columns = [
43
45
  { key: 'name', label: '名称' },
44
- { key: 'status', label: '状态' },
45
- { key: 'updatedAt', label: '更新时间' },
46
- { key: 'actions', label: '操作', width: 128 },
46
+ { key: 'status', label: '状态', width: 120 },
47
+ { key: 'updatedAt', label: '更新时间', width: 140 },
48
+ { key: 'actions', label: '操作', width: 148 },
47
49
  ]
48
50
 
49
51
  const rows = [
@@ -104,7 +106,7 @@ const rows = [
104
106
  <MTable
105
107
  :columns="columns"
106
108
  :rows="rows"
107
- :rows-per-page="3"
109
+ :rows-per-page="5"
108
110
  paginator
109
111
  striped
110
112
  bordered
@@ -112,22 +114,33 @@ const rows = [
112
114
  aria-label="用户列表"
113
115
  >
114
116
  <template #cell-status="{ value }">
115
- <MTag :value="value === 'active' ? '启用' : '停用'" :severity="value === 'active' ? 'success' : 'secondary'" />
117
+ <MStatus
118
+ :label="value === 'active' ? '启用' : '停用'"
119
+ :severity="value === 'active' ? 'success' : 'secondary'"
120
+ />
116
121
  </template>
117
122
  <template #cell-actions>
118
123
  <MSpace>
119
- <MButton severity="secondary" size="small">
124
+ <MButton severity="secondary" size="small" text>
120
125
  编辑
121
126
  </MButton>
122
- <MButton severity="danger" size="small">
127
+ <MButton severity="danger" size="small" text>
123
128
  删除
124
129
  </MButton>
125
130
  </MSpace>
126
131
  </template>
127
132
  <template #empty>
128
- <p style="margin: 0; padding: var(--m-space-8); text-align: center; color: var(--m-color-text-muted)">
129
- 暂无用户数据
130
- </p>
133
+ <MEmpty
134
+ title="还没有用户"
135
+ description="创建第一个用户后,即可分配角色与权限。"
136
+ icon="user"
137
+ >
138
+ <template #extra>
139
+ <MButton severity="primary">
140
+ 新建用户
141
+ </MButton>
142
+ </template>
143
+ </MEmpty>
131
144
  </template>
132
145
  </MTable>
133
146
  </MPageContent>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  /**
3
3
  * 黄金样例:登录页(Account + 轻量品牌)
4
- * @see DESIGN.md §3 · morya-ui-pages surfaces § Account
4
+ * @see DESIGN.md · surfaces § Account · visual-craft § Atmosphere
5
5
  */
6
6
  import {
7
7
  MButton,
@@ -56,7 +56,6 @@ async function onSubmit() {
56
56
  <p>使用工作邮箱进入后台。</p>
57
57
  </header>
58
58
 
59
- <!-- 表单级常驻错误:token 样式告警条(字段错误优先用 errorMessage) -->
60
59
  <p v-if="formError" class="login-alert" role="alert">
61
60
  {{ formError }}
62
61
  </p>
@@ -82,7 +81,7 @@ async function onSubmit() {
82
81
  </MFormItem>
83
82
 
84
83
  <MSpace style="margin-top: var(--m-space-2)" alignment="center">
85
- <MButton type="submit" label="登录" :loading="submitting" />
84
+ <MButton type="submit" label="登录" severity="primary" :loading="submitting" />
86
85
  <MButton type="button" label="忘记密码" severity="secondary" text />
87
86
  </MSpace>
88
87
  </MForm>
@@ -102,21 +101,45 @@ async function onSubmit() {
102
101
  }
103
102
 
104
103
  .login-brand {
104
+ position: relative;
105
105
  display: flex;
106
106
  flex-direction: column;
107
107
  justify-content: flex-end;
108
108
  gap: var(--m-space-4);
109
109
  padding: clamp(2rem, 6vw, 4.5rem);
110
+ overflow: hidden;
110
111
  background:
112
+ radial-gradient(
113
+ 80% 60% at 10% 20%,
114
+ color-mix(in srgb, var(--m-color-primary) 22%, transparent),
115
+ transparent 55%
116
+ ),
111
117
  linear-gradient(
112
118
  165deg,
113
- color-mix(in srgb, var(--m-color-primary) 18%, var(--m-color-surface)) 0%,
119
+ color-mix(in srgb, var(--m-color-primary) 16%, var(--m-color-surface)) 0%,
114
120
  var(--m-color-surface) 55%,
115
121
  color-mix(in srgb, var(--m-color-border) 35%, var(--m-color-surface)) 100%
116
122
  );
117
123
  border-right: 1px solid var(--m-color-border);
118
124
  }
119
125
 
126
+ .login-brand::after {
127
+ content: '';
128
+ position: absolute;
129
+ inset: auto -10% -20% 40%;
130
+ height: 55%;
131
+ border-radius: 50%;
132
+ background: color-mix(in srgb, var(--m-color-primary) 12%, transparent);
133
+ pointer-events: none;
134
+ }
135
+
136
+ .login-brand__mark,
137
+ .login-brand__title,
138
+ .login-brand__lead {
139
+ position: relative;
140
+ z-index: 1;
141
+ }
142
+
120
143
  .login-brand__mark {
121
144
  margin: 0;
122
145
  font-size: 0.8125rem;
@@ -177,6 +200,23 @@ async function onSubmit() {
177
200
  line-height: 1.45;
178
201
  }
179
202
 
203
+ @media (prefers-reduced-motion: no-preference) {
204
+ .login-panel {
205
+ animation: login-panel-in 420ms ease both;
206
+ }
207
+ }
208
+
209
+ @keyframes login-panel-in {
210
+ from {
211
+ opacity: 0;
212
+ transform: translateY(0.5rem);
213
+ }
214
+ to {
215
+ opacity: 1;
216
+ transform: translateY(0);
217
+ }
218
+ }
219
+
180
220
  @media (max-width: 768px) {
181
221
  .login-shell {
182
222
  grid-template-columns: 1fr;
@@ -199,6 +199,16 @@ describe('@morya-ui/mcp handlers', () => {
199
199
  expect(result.id).toBe('overlay-choice');
200
200
  expect(result.options.some((option) => option.component === 'Drawer')).toBe(true);
201
201
  });
202
+ it('covers current selection, status, empty, and menu guides', () => {
203
+ const selection = read(handlers.recommendComponent({ decision: 'selection-choice' }));
204
+ expect(selection.options.map((option) => option.component)).toEqual(expect.arrayContaining(['Select', 'CascadeSelect', 'Listbox', 'SelectButton', 'Radio']));
205
+ const status = read(handlers.recommendComponent({ decision: 'status-label-choice' }));
206
+ expect(status.id).toBe('status-label-choice');
207
+ const empty = read(handlers.recommendComponent({ decision: 'empty-result-choice' }));
208
+ expect(empty.options.map((option) => option.component)).toEqual(['Empty', 'Result']);
209
+ const menu = read(handlers.recommendComponent({ decision: 'action-menu-choice' }));
210
+ expect(menu.options.some((option) => option.component === 'ContextMenu')).toBe(true);
211
+ });
202
212
  it('exposes catalog health in version metadata', () => {
203
213
  const result = read(handlers.version());
204
214
  expect(result.health.ok).toBe(true);