xto-fronted 0.4.72 → 0.4.74
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/index-BcEjdbz_.js +515 -0
- package/dist/index-CWMpaJJ6.js +3267 -0
- package/dist/index-DkHXkwpw.js +479 -0
- package/dist/index-Pg_OaPt4.js +641 -0
- package/dist/index-dVHlrUjM.js +189 -0
- package/dist/index.es.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/App.vue +30 -1
- package/src/assets/styles/_root.scss +141 -97
- package/src/assets/styles/_variables.scss +44 -19
- package/src/assets/styles/index.scss +267 -42
- package/src/views/dashboard/index.vue +417 -155
- package/src/views/error/403.vue +251 -56
- package/src/views/error/404.vue +253 -56
- package/src/views/login/index.vue +586 -194
- package/src/views/system/menu/index.vue +403 -94
- package/src/views/system/role/index.vue +348 -69
- package/src/views/system/user/index.vue +402 -73
- package/dist/index-48G2-eqi.js +0 -475
- package/dist/index-BhtcPIRK.js +0 -3169
- package/dist/index-CZKP8fOP.js +0 -372
- package/dist/index-JouxgO84.js +0 -142
- package/dist/index-qlKXxfT9.js +0 -345
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, reactive, computed, onMounted } from 'vue'
|
|
3
3
|
import { Form, FormItem, Input, Select, Switch, InputNumber } from '@xto/form'
|
|
4
|
-
import {
|
|
4
|
+
import { Tag } from '@xto/data'
|
|
5
5
|
import { Modal, Message } from '@xto/feedback'
|
|
6
6
|
import { Space, Button } from '@xto/base'
|
|
7
7
|
import { MenuType, MenuTypeOptions, Status } from '@/enums'
|
|
@@ -201,6 +201,24 @@ const getMenuIcon = (icon?: string) => {
|
|
|
201
201
|
return iconMap[icon || ''] || '📄'
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
// 获取类型标签类型
|
|
205
|
+
const getTypeTagType = (type: MenuType) => {
|
|
206
|
+
switch (type) {
|
|
207
|
+
case MenuType.DIRECTORY: return 'primary'
|
|
208
|
+
case MenuType.MENU: return 'success'
|
|
209
|
+
default: return 'warning'
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 获取类型标签文本
|
|
214
|
+
const getTypeTagText = (type: MenuType) => {
|
|
215
|
+
switch (type) {
|
|
216
|
+
case MenuType.DIRECTORY: return '目录'
|
|
217
|
+
case MenuType.MENU: return '菜单'
|
|
218
|
+
default: return '按钮'
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
204
222
|
onMounted(() => {
|
|
205
223
|
getMenuList()
|
|
206
224
|
})
|
|
@@ -208,74 +226,155 @@ onMounted(() => {
|
|
|
208
226
|
|
|
209
227
|
<template>
|
|
210
228
|
<div class="menu-page">
|
|
211
|
-
|
|
229
|
+
<!-- 表格 -->
|
|
230
|
+
<div class="table-section">
|
|
212
231
|
<!-- 工具栏 -->
|
|
213
|
-
<div class="toolbar">
|
|
214
|
-
<
|
|
232
|
+
<div class="table-toolbar">
|
|
233
|
+
<div class="toolbar-left">
|
|
234
|
+
<Button type="primary" @click="handleAdd()">
|
|
235
|
+
<template #icon>
|
|
236
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
237
|
+
<line x1="12" y1="5" x2="12" y2="19"/>
|
|
238
|
+
<line x1="5" y1="12" x2="19" y2="12"/>
|
|
239
|
+
</svg>
|
|
240
|
+
</template>
|
|
241
|
+
新增菜单
|
|
242
|
+
</Button>
|
|
243
|
+
</div>
|
|
244
|
+
<div class="toolbar-right">
|
|
245
|
+
<span class="table-count">共 {{ menuList.length }} 个菜单</span>
|
|
246
|
+
</div>
|
|
215
247
|
</div>
|
|
216
248
|
|
|
217
|
-
<!--
|
|
218
|
-
<div class="
|
|
219
|
-
<table class="
|
|
249
|
+
<!-- 菜单树表格 -->
|
|
250
|
+
<div class="table-wrapper">
|
|
251
|
+
<table class="data-table">
|
|
220
252
|
<thead>
|
|
221
253
|
<tr>
|
|
222
|
-
<th>菜单名称</th>
|
|
223
|
-
<th>图标</th>
|
|
224
|
-
<th>路由路径</th>
|
|
225
|
-
<th>类型</th>
|
|
226
|
-
<th>排序</th>
|
|
227
|
-
<th>状态</th>
|
|
228
|
-
<th>操作</th>
|
|
254
|
+
<th class="col-name">菜单名称</th>
|
|
255
|
+
<th class="col-icon">图标</th>
|
|
256
|
+
<th class="col-path">路由路径</th>
|
|
257
|
+
<th class="col-type">类型</th>
|
|
258
|
+
<th class="col-sort">排序</th>
|
|
259
|
+
<th class="col-status">状态</th>
|
|
260
|
+
<th class="col-actions">操作</th>
|
|
229
261
|
</tr>
|
|
230
262
|
</thead>
|
|
231
263
|
<tbody>
|
|
232
|
-
<
|
|
233
|
-
<
|
|
234
|
-
<
|
|
235
|
-
<
|
|
264
|
+
<tr v-if="loading">
|
|
265
|
+
<td colspan="7" class="loading-cell">
|
|
266
|
+
<div class="loading-content">
|
|
267
|
+
<div class="loading-spinner"></div>
|
|
268
|
+
<span>加载中...</span>
|
|
269
|
+
</div>
|
|
270
|
+
</td>
|
|
271
|
+
</tr>
|
|
272
|
+
<tr v-else-if="menuList.length === 0">
|
|
273
|
+
<td colspan="7" class="empty-cell">
|
|
274
|
+
<div class="empty-content">
|
|
275
|
+
<svg viewBox="0 0 64 41" fill="none">
|
|
276
|
+
<g transform="translate(0 1)">
|
|
277
|
+
<ellipse fill="#f5f5f5" cx="32" cy="33" rx="32" ry="7"/>
|
|
278
|
+
<g stroke="var(--color-text-placeholder)" stroke-width="2">
|
|
279
|
+
<path d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"/>
|
|
280
|
+
<path d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35H11.95C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z" fill="var(--color-fill)"/>
|
|
281
|
+
</g>
|
|
282
|
+
</g>
|
|
283
|
+
</svg>
|
|
284
|
+
<span>暂无数据</span>
|
|
285
|
+
</div>
|
|
286
|
+
</td>
|
|
287
|
+
</tr>
|
|
288
|
+
<template v-else v-for="menu in menuList" :key="menu.id">
|
|
289
|
+
<tr class="data-row tree-row--level-0">
|
|
290
|
+
<td class="col-name">
|
|
291
|
+
<div class="menu-info">
|
|
292
|
+
<span class="menu-icon-wrapper">{{ getMenuIcon(menu.icon) }}</span>
|
|
293
|
+
<span class="menu-title" @click="handleEdit(menu)">{{ menu.title }}</span>
|
|
294
|
+
</div>
|
|
295
|
+
</td>
|
|
296
|
+
<td class="col-icon">
|
|
297
|
+
<span class="icon-text">{{ getMenuIcon(menu.icon) }}</span>
|
|
298
|
+
</td>
|
|
299
|
+
<td class="col-path">
|
|
300
|
+
<code class="path-code">{{ menu.path }}</code>
|
|
236
301
|
</td>
|
|
237
|
-
<td
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
<Tag :type="menu.type === MenuType.DIRECTORY ? 'primary' : menu.type === MenuType.MENU ? 'success' : 'warning'" size="small">
|
|
241
|
-
{{ menu.type === MenuType.DIRECTORY ? '目录' : menu.type === MenuType.MENU ? '菜单' : '按钮' }}
|
|
302
|
+
<td class="col-type">
|
|
303
|
+
<Tag :type="getTypeTagType(menu.type)" size="small">
|
|
304
|
+
{{ getTypeTagText(menu.type) }}
|
|
242
305
|
</Tag>
|
|
243
306
|
</td>
|
|
244
|
-
<td
|
|
245
|
-
|
|
307
|
+
<td class="col-sort">
|
|
308
|
+
<span class="sort-badge">{{ menu.sort }}</span>
|
|
309
|
+
</td>
|
|
310
|
+
<td class="col-status">
|
|
246
311
|
<Tag :type="menu.status === Status.ENABLED ? 'success' : 'danger'" size="small">
|
|
247
312
|
{{ menu.status === Status.ENABLED ? '启用' : '禁用' }}
|
|
248
313
|
</Tag>
|
|
249
314
|
</td>
|
|
250
|
-
<td>
|
|
251
|
-
<Space>
|
|
252
|
-
<Button type="primary" link size="small" @click="handleAdd(menu.id)"
|
|
253
|
-
|
|
315
|
+
<td class="col-actions">
|
|
316
|
+
<Space class="action-buttons">
|
|
317
|
+
<Button type="primary" link size="small" @click="handleAdd(menu.id)">
|
|
318
|
+
<template #icon>
|
|
319
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
320
|
+
<line x1="12" y1="5" x2="12" y2="19"/>
|
|
321
|
+
<line x1="5" y1="12" x2="19" y2="12"/>
|
|
322
|
+
</svg>
|
|
323
|
+
</template>
|
|
324
|
+
新增
|
|
325
|
+
</Button>
|
|
326
|
+
<Button type="primary" link size="small" @click="handleEdit(menu)">
|
|
327
|
+
<template #icon>
|
|
328
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
329
|
+
<path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/>
|
|
330
|
+
<path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/>
|
|
331
|
+
</svg>
|
|
332
|
+
</template>
|
|
333
|
+
编辑
|
|
334
|
+
</Button>
|
|
254
335
|
</Space>
|
|
255
336
|
</td>
|
|
256
337
|
</tr>
|
|
257
338
|
<template v-if="menu.children" v-for="child in menu.children" :key="child.id">
|
|
258
|
-
<tr class="
|
|
259
|
-
<td>
|
|
260
|
-
<
|
|
261
|
-
|
|
339
|
+
<tr class="data-row tree-row--level-1">
|
|
340
|
+
<td class="col-name">
|
|
341
|
+
<div class="menu-info">
|
|
342
|
+
<span class="tree-indent"></span>
|
|
343
|
+
<span class="tree-line"></span>
|
|
344
|
+
<span class="menu-icon-wrapper">{{ getMenuIcon(child.icon) }}</span>
|
|
345
|
+
<span class="menu-title" @click="handleEdit(child)">{{ child.title }}</span>
|
|
346
|
+
</div>
|
|
347
|
+
</td>
|
|
348
|
+
<td class="col-icon">
|
|
349
|
+
<span class="icon-text">{{ getMenuIcon(child.icon) }}</span>
|
|
350
|
+
</td>
|
|
351
|
+
<td class="col-path">
|
|
352
|
+
<code class="path-code">{{ child.path }}</code>
|
|
262
353
|
</td>
|
|
263
|
-
<td
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
<Tag :type="child.type === MenuType.DIRECTORY ? 'primary' : child.type === MenuType.MENU ? 'success' : 'warning'" size="small">
|
|
267
|
-
{{ child.type === MenuType.DIRECTORY ? '目录' : child.type === MenuType.MENU ? '菜单' : '按钮' }}
|
|
354
|
+
<td class="col-type">
|
|
355
|
+
<Tag :type="getTypeTagType(child.type)" size="small">
|
|
356
|
+
{{ getTypeTagText(child.type) }}
|
|
268
357
|
</Tag>
|
|
269
358
|
</td>
|
|
270
|
-
<td
|
|
271
|
-
|
|
359
|
+
<td class="col-sort">
|
|
360
|
+
<span class="sort-badge">{{ child.sort }}</span>
|
|
361
|
+
</td>
|
|
362
|
+
<td class="col-status">
|
|
272
363
|
<Tag :type="child.status === Status.ENABLED ? 'success' : 'danger'" size="small">
|
|
273
364
|
{{ child.status === Status.ENABLED ? '启用' : '禁用' }}
|
|
274
365
|
</Tag>
|
|
275
366
|
</td>
|
|
276
|
-
<td>
|
|
277
|
-
<Space>
|
|
278
|
-
<Button type="primary" link size="small" @click="handleEdit(child)"
|
|
367
|
+
<td class="col-actions">
|
|
368
|
+
<Space class="action-buttons">
|
|
369
|
+
<Button type="primary" link size="small" @click="handleEdit(child)">
|
|
370
|
+
<template #icon>
|
|
371
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
372
|
+
<path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/>
|
|
373
|
+
<path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/>
|
|
374
|
+
</svg>
|
|
375
|
+
</template>
|
|
376
|
+
编辑
|
|
377
|
+
</Button>
|
|
279
378
|
</Space>
|
|
280
379
|
</td>
|
|
281
380
|
</tr>
|
|
@@ -284,44 +383,55 @@ onMounted(() => {
|
|
|
284
383
|
</tbody>
|
|
285
384
|
</table>
|
|
286
385
|
</div>
|
|
287
|
-
</
|
|
386
|
+
</div>
|
|
288
387
|
|
|
289
388
|
<!-- 编辑弹窗 -->
|
|
290
|
-
<Modal v-model="modalVisible" :title="modalTitle" width="600px">
|
|
291
|
-
<Form ref="formRef" :model="formData" :rules="rules" label-width="80px">
|
|
292
|
-
<
|
|
293
|
-
<
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
<
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
<
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
<
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
<
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
<
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
<
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
<
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
<
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
<
|
|
324
|
-
|
|
389
|
+
<Modal v-model="modalVisible" :title="modalTitle" width="600px" class="menu-modal">
|
|
390
|
+
<Form ref="formRef" :model="formData" :rules="rules" label-width="80px" class="menu-form">
|
|
391
|
+
<div class="form-grid">
|
|
392
|
+
<FormItem label="上级菜单" class="form-item-full">
|
|
393
|
+
<Input v-model="formData.parentId" placeholder="上级菜单ID" disabled />
|
|
394
|
+
</FormItem>
|
|
395
|
+
<FormItem label="菜单类型">
|
|
396
|
+
<Select v-model="formData.type" :options="MenuTypeOptions" />
|
|
397
|
+
</FormItem>
|
|
398
|
+
<FormItem label="排序">
|
|
399
|
+
<InputNumber v-model="formData.sort" :min="0" />
|
|
400
|
+
</FormItem>
|
|
401
|
+
<FormItem label="菜单名称" prop="name">
|
|
402
|
+
<Input v-model="formData.name" placeholder="请输入菜单名称(路由name)" />
|
|
403
|
+
</FormItem>
|
|
404
|
+
<FormItem label="菜单标题" prop="title">
|
|
405
|
+
<Input v-model="formData.title" placeholder="请输入菜单标题" />
|
|
406
|
+
</FormItem>
|
|
407
|
+
<FormItem label="路由路径" prop="path" class="form-item-full">
|
|
408
|
+
<Input v-model="formData.path" placeholder="请输入路由路径" />
|
|
409
|
+
</FormItem>
|
|
410
|
+
<FormItem label="组件路径" class="form-item-full">
|
|
411
|
+
<Input v-model="formData.component" placeholder="请输入组件路径" />
|
|
412
|
+
</FormItem>
|
|
413
|
+
<FormItem label="图标">
|
|
414
|
+
<Input v-model="formData.icon" placeholder="请输入图标名称" />
|
|
415
|
+
</FormItem>
|
|
416
|
+
<FormItem label="状态">
|
|
417
|
+
<div class="status-field">
|
|
418
|
+
<Switch v-model="formData.status" :active-value="Status.ENABLED" :inactive-value="Status.DISABLED" />
|
|
419
|
+
<span class="status-label">{{ formData.status === Status.ENABLED ? '启用' : '禁用' }}</span>
|
|
420
|
+
</div>
|
|
421
|
+
</FormItem>
|
|
422
|
+
<FormItem label="隐藏">
|
|
423
|
+
<div class="status-field">
|
|
424
|
+
<Switch v-model="formData.hidden" />
|
|
425
|
+
<span class="status-label">{{ formData.hidden ? '隐藏' : '显示' }}</span>
|
|
426
|
+
</div>
|
|
427
|
+
</FormItem>
|
|
428
|
+
<FormItem label="缓存">
|
|
429
|
+
<div class="status-field">
|
|
430
|
+
<Switch v-model="formData.keepAlive" />
|
|
431
|
+
<span class="status-label">{{ formData.keepAlive ? '开启' : '关闭' }}</span>
|
|
432
|
+
</div>
|
|
433
|
+
</FormItem>
|
|
434
|
+
</div>
|
|
325
435
|
</Form>
|
|
326
436
|
<template #footer>
|
|
327
437
|
<Space>
|
|
@@ -335,47 +445,246 @@ onMounted(() => {
|
|
|
335
445
|
|
|
336
446
|
<style lang="scss" scoped>
|
|
337
447
|
.menu-page {
|
|
338
|
-
padding:
|
|
448
|
+
padding: 24px;
|
|
449
|
+
background: var(--bg-color-page);
|
|
450
|
+
min-height: 100%;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// 表格区域
|
|
454
|
+
.table-section {
|
|
455
|
+
background: var(--bg-color);
|
|
456
|
+
border-radius: var(--border-radius-large);
|
|
457
|
+
box-shadow: var(--box-shadow-card);
|
|
458
|
+
overflow: hidden;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.table-toolbar {
|
|
462
|
+
display: flex;
|
|
463
|
+
justify-content: space-between;
|
|
464
|
+
align-items: center;
|
|
465
|
+
padding: 16px 24px;
|
|
466
|
+
border-bottom: 1px solid var(--color-border-lighter);
|
|
467
|
+
|
|
468
|
+
.toolbar-left {
|
|
469
|
+
display: flex;
|
|
470
|
+
gap: 12px;
|
|
471
|
+
}
|
|
339
472
|
|
|
340
|
-
.
|
|
341
|
-
|
|
473
|
+
.table-count {
|
|
474
|
+
font-size: 14px;
|
|
475
|
+
color: var(--color-text-secondary);
|
|
342
476
|
}
|
|
343
477
|
}
|
|
344
478
|
|
|
345
|
-
.
|
|
479
|
+
.table-wrapper {
|
|
480
|
+
overflow-x: auto;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// 表格样式
|
|
484
|
+
.data-table {
|
|
346
485
|
width: 100%;
|
|
347
486
|
border-collapse: collapse;
|
|
348
487
|
|
|
349
488
|
th, td {
|
|
350
|
-
padding:
|
|
489
|
+
padding: 14px 16px;
|
|
351
490
|
text-align: left;
|
|
352
491
|
border-bottom: 1px solid var(--color-border-lighter);
|
|
353
492
|
}
|
|
354
493
|
|
|
355
494
|
th {
|
|
495
|
+
font-size: 14px;
|
|
356
496
|
font-weight: 500;
|
|
357
|
-
color: var(--color-text-
|
|
358
|
-
background
|
|
497
|
+
color: var(--color-text-secondary);
|
|
498
|
+
background: var(--color-fill-light);
|
|
499
|
+
white-space: nowrap;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.data-row {
|
|
503
|
+
transition: background-color 0.2s;
|
|
504
|
+
|
|
505
|
+
&:hover {
|
|
506
|
+
background: var(--color-primary-light-6);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
td {
|
|
511
|
+
vertical-align: middle;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.loading-cell,
|
|
515
|
+
.empty-cell {
|
|
516
|
+
padding: 60px 20px;
|
|
359
517
|
}
|
|
360
518
|
|
|
361
|
-
.
|
|
362
|
-
|
|
363
|
-
|
|
519
|
+
.loading-content,
|
|
520
|
+
.empty-content {
|
|
521
|
+
display: flex;
|
|
522
|
+
flex-direction: column;
|
|
523
|
+
align-items: center;
|
|
524
|
+
gap: 16px;
|
|
525
|
+
color: var(--color-text-placeholder);
|
|
526
|
+
|
|
527
|
+
svg {
|
|
528
|
+
width: 64px;
|
|
529
|
+
height: 41px;
|
|
364
530
|
}
|
|
365
531
|
}
|
|
532
|
+
|
|
533
|
+
.loading-spinner {
|
|
534
|
+
width: 32px;
|
|
535
|
+
height: 32px;
|
|
536
|
+
border: 3px solid var(--color-border-lighter);
|
|
537
|
+
border-top-color: var(--color-primary);
|
|
538
|
+
border-radius: 50%;
|
|
539
|
+
animation: spin 0.8s linear infinite;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
@keyframes spin {
|
|
544
|
+
to { transform: rotate(360deg); }
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// 树形结构
|
|
548
|
+
.tree-row--level-1 {
|
|
549
|
+
.col-name {
|
|
550
|
+
padding-left: 40px;
|
|
551
|
+
}
|
|
366
552
|
}
|
|
367
553
|
|
|
368
554
|
.tree-indent {
|
|
369
555
|
display: inline-block;
|
|
370
|
-
width:
|
|
556
|
+
width: 24px;
|
|
371
557
|
}
|
|
372
558
|
|
|
373
|
-
.
|
|
559
|
+
.tree-line {
|
|
560
|
+
position: relative;
|
|
561
|
+
display: inline-block;
|
|
562
|
+
width: 16px;
|
|
563
|
+
height: 1px;
|
|
564
|
+
background: var(--color-border-light);
|
|
565
|
+
margin-right: 8px;
|
|
566
|
+
vertical-align: middle;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// 列样式
|
|
570
|
+
.col-name {
|
|
571
|
+
min-width: 200px;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.menu-info {
|
|
575
|
+
display: flex;
|
|
576
|
+
align-items: center;
|
|
577
|
+
gap: 8px;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.menu-icon-wrapper {
|
|
581
|
+
width: 28px;
|
|
582
|
+
height: 28px;
|
|
583
|
+
display: flex;
|
|
584
|
+
align-items: center;
|
|
585
|
+
justify-content: center;
|
|
586
|
+
background: var(--color-fill-light);
|
|
587
|
+
border-radius: 6px;
|
|
588
|
+
font-size: 14px;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.menu-title {
|
|
592
|
+
font-size: 14px;
|
|
593
|
+
font-weight: 500;
|
|
594
|
+
color: var(--color-text-primary);
|
|
374
595
|
cursor: pointer;
|
|
375
|
-
|
|
596
|
+
transition: color 0.2s;
|
|
376
597
|
|
|
377
598
|
&:hover {
|
|
378
|
-
|
|
599
|
+
color: var(--color-primary);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.col-icon {
|
|
604
|
+
width: 80px;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
.icon-text {
|
|
608
|
+
font-size: 16px;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.col-path {
|
|
612
|
+
min-width: 140px;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.path-code {
|
|
616
|
+
font-family: 'SF Mono', Monaco, Consolas, monospace;
|
|
617
|
+
font-size: 12px;
|
|
618
|
+
padding: 4px 8px;
|
|
619
|
+
background: var(--color-fill-light);
|
|
620
|
+
border-radius: 4px;
|
|
621
|
+
color: var(--color-text-secondary);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.col-type {
|
|
625
|
+
width: 80px;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.col-sort {
|
|
629
|
+
width: 60px;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.sort-badge {
|
|
633
|
+
display: inline-flex;
|
|
634
|
+
align-items: center;
|
|
635
|
+
justify-content: center;
|
|
636
|
+
min-width: 24px;
|
|
637
|
+
height: 24px;
|
|
638
|
+
padding: 0 8px;
|
|
639
|
+
background: var(--color-fill);
|
|
640
|
+
border-radius: 12px;
|
|
641
|
+
font-size: 12px;
|
|
642
|
+
color: var(--color-text-secondary);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
.col-status {
|
|
646
|
+
width: 80px;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
.col-actions {
|
|
650
|
+
min-width: 140px;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.action-buttons {
|
|
654
|
+
:deep(.x-button) {
|
|
655
|
+
padding: 4px 8px;
|
|
656
|
+
|
|
657
|
+
svg {
|
|
658
|
+
width: 14px;
|
|
659
|
+
height: 14px;
|
|
660
|
+
margin-right: 4px;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// 弹窗表单
|
|
666
|
+
.menu-form {
|
|
667
|
+
padding: 16px 0;
|
|
668
|
+
|
|
669
|
+
.form-grid {
|
|
670
|
+
display: grid;
|
|
671
|
+
grid-template-columns: repeat(2, 1fr);
|
|
672
|
+
gap: 0 24px;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
.form-item-full {
|
|
676
|
+
grid-column: span 2;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
.status-field {
|
|
680
|
+
display: flex;
|
|
681
|
+
align-items: center;
|
|
682
|
+
gap: 12px;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.status-label {
|
|
686
|
+
font-size: 14px;
|
|
687
|
+
color: var(--color-text-secondary);
|
|
379
688
|
}
|
|
380
689
|
}
|
|
381
|
-
</style>
|
|
690
|
+
</style>
|