@morya-ui/mcp 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.
@@ -0,0 +1,166 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 黄金样例:列表页 · dense(高密度工具台)
4
+ * structure: list · style: dense
5
+ * 镜像区块顺序;气质跟 styleDirection / 参考走,不要把本文件当唯一审美。
6
+ * @see list-page.vue · style-presets.md · page-layouts.md
7
+ */
8
+ import {
9
+ MBreadcrumb,
10
+ MButton,
11
+ MConfigProvider,
12
+ MEmpty,
13
+ MInput,
14
+ MLayout,
15
+ MLayoutContent,
16
+ MLayoutHeader,
17
+ MLayoutSider,
18
+ MMenu,
19
+ MPageContent,
20
+ MPageFilters,
21
+ MPageHeader,
22
+ MSelect,
23
+ MSpace,
24
+ MStatus,
25
+ MTable,
26
+ zhCN,
27
+ } from 'morya-ui'
28
+ import { ref } from 'vue'
29
+
30
+ const keyword = ref('')
31
+ const status = ref<string | undefined>()
32
+ const siderCollapsed = ref(false)
33
+
34
+ const menuModel = [
35
+ { key: 'users', label: '用户管理', icon: 'user', to: '/users' },
36
+ { key: 'roles', label: '角色管理', icon: 'shield', to: '/roles' },
37
+ { key: 'settings', label: '系统设置', icon: 'settings', to: '/settings' },
38
+ ]
39
+
40
+ const statusOptions = [
41
+ { label: '全部', value: '' },
42
+ { label: '启用', value: 'active' },
43
+ { label: '停用', value: 'inactive' },
44
+ ]
45
+
46
+ function resetFilters() {
47
+ keyword.value = ''
48
+ status.value = undefined
49
+ }
50
+
51
+ const columns = [
52
+ { key: 'name', label: '名称' },
53
+ { key: 'status', label: '状态', width: 96 },
54
+ { key: 'updatedAt', label: '更新', width: 110 },
55
+ { key: 'actions', label: '操作', width: 120 },
56
+ ]
57
+
58
+ const rows = [
59
+ { id: '1', name: '示例项目 A', status: 'active', updatedAt: '09-01' },
60
+ { id: '2', name: '示例项目 B', status: 'inactive', updatedAt: '08-28' },
61
+ { id: '3', name: '示例项目 C', status: 'active', updatedAt: '08-25' },
62
+ { id: '4', name: '示例项目 D', status: 'active', updatedAt: '08-20' },
63
+ { id: '5', name: '示例项目 E', status: 'inactive', updatedAt: '08-15' },
64
+ { id: '6', name: '示例项目 F', status: 'active', updatedAt: '08-12' },
65
+ { id: '7', name: '示例项目 G', status: 'inactive', updatedAt: '08-10' },
66
+ { id: '8', name: '示例项目 H', status: 'active', updatedAt: '08-08' },
67
+ ]
68
+ </script>
69
+
70
+ <template>
71
+ <MConfigProvider :locale="zhCN">
72
+ <MLayout has-sider fill-viewport>
73
+ <MLayoutSider v-model:collapsed="siderCollapsed" bordered :collapsed-width="64">
74
+ <MMenu
75
+ :model="menuModel"
76
+ :collapsed="siderCollapsed"
77
+ :collapsed-width="64"
78
+ selected-key="users"
79
+ />
80
+ </MLayoutSider>
81
+
82
+ <MLayout>
83
+ <MLayoutHeader padding="var(--m-space-3) var(--m-space-4)">
84
+ <MBreadcrumb :model="[{ label: '首页', to: '/' }, { label: '用户管理' }]" />
85
+ </MLayoutHeader>
86
+
87
+ <MLayoutContent>
88
+ <MPageContent fill density="compact">
89
+ <MPageHeader title="用户管理">
90
+ <template #actions>
91
+ <MButton severity="primary" size="small">
92
+ 新建
93
+ </MButton>
94
+ </template>
95
+ </MPageHeader>
96
+
97
+ <MPageFilters aria-label="筛选" variant="plain">
98
+ <MSpace wrap>
99
+ <MInput
100
+ v-model="keyword"
101
+ placeholder="搜索"
102
+ clearable
103
+ size="small"
104
+ style="width: 11rem"
105
+ />
106
+ <MSelect
107
+ v-model="status"
108
+ :options="statusOptions"
109
+ placeholder="状态"
110
+ clearable
111
+ size="small"
112
+ style="width: 8rem"
113
+ />
114
+ <MButton severity="secondary" size="small">
115
+ 查询
116
+ </MButton>
117
+ <MButton severity="secondary" size="small" text @click="resetFilters">
118
+ 重置
119
+ </MButton>
120
+ </MSpace>
121
+ </MPageFilters>
122
+
123
+ <MTable
124
+ :columns="columns"
125
+ :rows="rows"
126
+ :rows-per-page="10"
127
+ fill
128
+ paginator
129
+ size="small"
130
+ striped
131
+ bordered
132
+ row-key="id"
133
+ aria-label="用户列表"
134
+ >
135
+ <template #cell-status="{ value }">
136
+ <MStatus
137
+ :label="value === 'active' ? '启用' : '停用'"
138
+ :severity="value === 'active' ? 'success' : 'secondary'"
139
+ />
140
+ </template>
141
+ <template #cell-actions>
142
+ <MSpace>
143
+ <MButton severity="secondary" size="small" text>
144
+ 编辑
145
+ </MButton>
146
+ <MButton severity="danger" size="small" text>
147
+ 删除
148
+ </MButton>
149
+ </MSpace>
150
+ </template>
151
+ <template #empty>
152
+ <MEmpty title="暂无数据" description="创建后在此浏览。" icon="user">
153
+ <template #extra>
154
+ <MButton severity="primary" size="small">
155
+ 新建
156
+ </MButton>
157
+ </template>
158
+ </MEmpty>
159
+ </template>
160
+ </MTable>
161
+ </MPageContent>
162
+ </MLayoutContent>
163
+ </MLayout>
164
+ </MLayout>
165
+ </MConfigProvider>
166
+ </template>
@@ -0,0 +1,270 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 黄金样例:列表页 · rail(侧栏强调)
4
+ * structure: list · style: rail
5
+ * 氛围只在 chrome(侧栏);内容区保持克制。镜像区块顺序。
6
+ * @see list-page.vue · style-presets.md · visual-craft § Atmosphere
7
+ */
8
+ import {
9
+ MBreadcrumb,
10
+ MButton,
11
+ MConfigProvider,
12
+ MEmpty,
13
+ MInput,
14
+ MLayout,
15
+ MLayoutContent,
16
+ MLayoutHeader,
17
+ MLayoutSider,
18
+ MMenu,
19
+ MPageContent,
20
+ MPageFilterChips,
21
+ MPageFilters,
22
+ MPageHeader,
23
+ MSelect,
24
+ MSpace,
25
+ MStatus,
26
+ MTable,
27
+ MTag,
28
+ zhCN,
29
+ } from 'morya-ui'
30
+ import { computed, ref } from 'vue'
31
+
32
+ const keyword = ref('')
33
+ const status = ref<string | undefined>()
34
+ const department = ref<string | null>(null)
35
+ const filtersExpanded = ref(false)
36
+ const siderCollapsed = ref(false)
37
+
38
+ const menuModel = [
39
+ { key: 'users', label: '用户管理', icon: 'user', to: '/users' },
40
+ { key: 'roles', label: '角色管理', icon: 'shield', to: '/roles' },
41
+ { key: 'settings', label: '系统设置', icon: 'settings', to: '/settings' },
42
+ ]
43
+
44
+ const statusOptions = [
45
+ { label: '全部', value: '' },
46
+ { label: '启用', value: 'active' },
47
+ { label: '停用', value: 'inactive' },
48
+ ]
49
+
50
+ const departmentOptions = [
51
+ { label: '研发', value: '研发' },
52
+ { label: '运营', value: '运营' },
53
+ { label: '市场', value: '市场' },
54
+ ]
55
+
56
+ const activeFilters = computed(() => {
57
+ const items: Array<{ key: string; label: string }> = []
58
+ if (keyword.value.trim()) {
59
+ items.push({ key: 'keyword', label: `关键词:${keyword.value.trim()}` })
60
+ }
61
+ if (status.value) {
62
+ const label = statusOptions.find((o) => o.value === status.value)?.label ?? status.value
63
+ items.push({ key: 'status', label: `状态:${label}` })
64
+ }
65
+ if (department.value) {
66
+ items.push({ key: 'department', label: `部门:${department.value}` })
67
+ }
68
+ return items
69
+ })
70
+
71
+ function clearFilter(key: string) {
72
+ if (key === 'keyword') keyword.value = ''
73
+ if (key === 'status') status.value = undefined
74
+ if (key === 'department') department.value = null
75
+ }
76
+
77
+ function resetFilters() {
78
+ keyword.value = ''
79
+ status.value = undefined
80
+ department.value = null
81
+ }
82
+
83
+ const columns = [
84
+ { key: 'name', label: '名称' },
85
+ { key: 'status', label: '状态', width: 120 },
86
+ { key: 'updatedAt', label: '更新时间', width: 140 },
87
+ { key: 'actions', label: '操作', width: 148 },
88
+ ]
89
+
90
+ const rows = [
91
+ { id: '1', name: '示例项目 A', status: 'active', updatedAt: '2026-09-01' },
92
+ { id: '2', name: '示例项目 B', status: 'inactive', updatedAt: '2026-08-28' },
93
+ { id: '3', name: '示例项目 C', status: 'active', updatedAt: '2026-08-25' },
94
+ { id: '4', name: '示例项目 D', status: 'active', updatedAt: '2026-08-20' },
95
+ { id: '5', name: '示例项目 E', status: 'inactive', updatedAt: '2026-08-15' },
96
+ ]
97
+ </script>
98
+
99
+ <template>
100
+ <MConfigProvider :locale="zhCN">
101
+ <MLayout has-sider fill-viewport>
102
+ <MLayoutSider
103
+ v-model:collapsed="siderCollapsed"
104
+ bordered
105
+ :collapsed-width="72"
106
+ class="gp-rail-sider"
107
+ >
108
+ <div class="gp-rail-sider__brand">
109
+ <span class="gp-rail-sider__mark" aria-hidden="true" />
110
+ <span v-if="!siderCollapsed" class="gp-rail-sider__name">Acme Ops</span>
111
+ </div>
112
+ <MMenu
113
+ :model="menuModel"
114
+ :collapsed="siderCollapsed"
115
+ :collapsed-width="72"
116
+ selected-key="users"
117
+ />
118
+ </MLayoutSider>
119
+
120
+ <MLayout>
121
+ <MLayoutHeader padding="var(--m-space-4) var(--m-space-6)" class="gp-rail-header">
122
+ <MBreadcrumb :model="[{ label: '首页', to: '/' }, { label: '用户管理' }]" />
123
+ </MLayoutHeader>
124
+
125
+ <MLayoutContent>
126
+ <MPageContent fill>
127
+ <MPageHeader title="用户管理" description="维护账号、角色与权限。">
128
+ <template #actions>
129
+ <MButton severity="primary">
130
+ 新建用户
131
+ </MButton>
132
+ </template>
133
+ </MPageHeader>
134
+
135
+ <MPageFilters
136
+ v-model:expanded="filtersExpanded"
137
+ aria-label="筛选"
138
+ variant="filled"
139
+ collapsible
140
+ >
141
+ <MSpace wrap>
142
+ <MInput v-model="keyword" placeholder="搜索名称" clearable style="width: 14rem" />
143
+ <MSelect
144
+ v-model="status"
145
+ :options="statusOptions"
146
+ placeholder="状态"
147
+ clearable
148
+ style="width: 10rem"
149
+ />
150
+ <MButton severity="secondary">
151
+ 查询
152
+ </MButton>
153
+ <MButton severity="secondary" text @click="resetFilters">
154
+ 重置
155
+ </MButton>
156
+ </MSpace>
157
+ <template #advanced>
158
+ <MSpace wrap>
159
+ <MSelect
160
+ v-model="department"
161
+ :options="departmentOptions"
162
+ placeholder="部门"
163
+ clearable
164
+ style="width: 10rem"
165
+ />
166
+ </MSpace>
167
+ </template>
168
+ </MPageFilters>
169
+
170
+ <MPageFilterChips v-if="activeFilters.length" label="已选" aria-label="已选筛选">
171
+ <MTag
172
+ v-for="item in activeFilters"
173
+ :key="item.key"
174
+ :value="item.label"
175
+ size="small"
176
+ bordered
177
+ closable
178
+ @close="clearFilter(item.key)"
179
+ />
180
+ </MPageFilterChips>
181
+
182
+ <MTable
183
+ :columns="columns"
184
+ :rows="rows"
185
+ :rows-per-page="5"
186
+ fill
187
+ paginator
188
+ striped
189
+ bordered
190
+ row-key="id"
191
+ aria-label="用户列表"
192
+ >
193
+ <template #cell-status="{ value }">
194
+ <MStatus
195
+ :label="value === 'active' ? '启用' : '停用'"
196
+ :severity="value === 'active' ? 'success' : 'secondary'"
197
+ />
198
+ </template>
199
+ <template #cell-actions>
200
+ <MSpace>
201
+ <MButton severity="secondary" size="small" text>
202
+ 编辑
203
+ </MButton>
204
+ <MButton severity="danger" size="small" text>
205
+ 删除
206
+ </MButton>
207
+ </MSpace>
208
+ </template>
209
+ <template #empty>
210
+ <MEmpty
211
+ title="还没有用户"
212
+ description="创建第一个用户后,即可分配角色与权限。"
213
+ icon="user"
214
+ >
215
+ <template #extra>
216
+ <MButton severity="primary">
217
+ 新建用户
218
+ </MButton>
219
+ </template>
220
+ </MEmpty>
221
+ </template>
222
+ </MTable>
223
+ </MPageContent>
224
+ </MLayoutContent>
225
+ </MLayout>
226
+ </MLayout>
227
+ </MConfigProvider>
228
+ </template>
229
+
230
+ <style scoped>
231
+ .gp-rail-sider {
232
+ background:
233
+ linear-gradient(
234
+ 180deg,
235
+ color-mix(in srgb, var(--m-color-primary) 14%, var(--m-color-surface)) 0%,
236
+ var(--m-color-surface) 42%
237
+ );
238
+ }
239
+
240
+ .gp-rail-sider__brand {
241
+ align-items: center;
242
+ display: flex;
243
+ gap: var(--m-space-2);
244
+ min-height: 3rem;
245
+ padding: var(--m-space-3) var(--m-space-4);
246
+ }
247
+
248
+ .gp-rail-sider__mark {
249
+ background: var(--m-color-primary);
250
+ border-radius: var(--m-radius-sm);
251
+ flex-shrink: 0;
252
+ height: 1.25rem;
253
+ width: 1.25rem;
254
+ }
255
+
256
+ .gp-rail-sider__name {
257
+ color: var(--m-color-text);
258
+ font-size: var(--m-font-size-md);
259
+ font-weight: 600;
260
+ letter-spacing: -0.02em;
261
+ overflow: hidden;
262
+ text-overflow: ellipsis;
263
+ white-space: nowrap;
264
+ }
265
+
266
+ .gp-rail-header {
267
+ border-bottom: 1px solid var(--m-color-border);
268
+ box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--m-color-primary) 18%, transparent);
269
+ }
270
+ </style>