@befly-addon/admin 1.0.33 → 1.0.35
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/package.json +2 -2
- package/views/403/index.vue +5 -3
- package/views/admin/components/edit.vue +32 -31
- package/views/admin/components/role.vue +9 -8
- package/views/admin/index.vue +35 -29
- package/views/dict/components/edit.vue +32 -31
- package/views/dict/index.vue +28 -23
- package/views/index/components/addonList.vue +2 -2
- package/views/index/components/environmentInfo.vue +2 -1
- package/views/index/components/operationLogs.vue +1 -1
- package/views/index/components/performanceMetrics.vue +11 -6
- package/views/index/components/quickActions.vue +6 -3
- package/views/index/components/serviceStatus.vue +20 -11
- package/views/index/components/systemNotifications.vue +14 -7
- package/views/index/components/systemOverview.vue +28 -28
- package/views/index/components/systemResources.vue +12 -7
- package/views/index/components/userInfo.vue +16 -19
- package/views/login/components/emailLoginForm.vue +20 -17
- package/views/login/components/registerForm.vue +32 -27
- package/views/menu/components/edit.vue +26 -25
- package/views/menu/index.vue +30 -24
- package/views/role/components/api.vue +21 -15
- package/views/role/components/edit.vue +26 -25
- package/views/role/components/menu.vue +7 -6
- package/views/role/index.vue +36 -29
- package/views/news/detail/index.vue +0 -26
- package/views/news/index.vue +0 -26
- package/views/user/index.vue +0 -322
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="section-block">
|
|
3
3
|
<div class="section-header flex items-center gap-2">
|
|
4
|
-
<
|
|
4
|
+
<ILucideBell />
|
|
5
5
|
<h2>系统通知</h2>
|
|
6
6
|
</div>
|
|
7
7
|
<div class="section-content">
|
|
8
8
|
<div class="notification-compact-list">
|
|
9
9
|
<div v-for="notification in notifications" :key="notification.id" class="notification-compact-item">
|
|
10
10
|
<div class="notification-icon" :class="`type-${notification.type}`">
|
|
11
|
-
<
|
|
12
|
-
<
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
<
|
|
11
|
+
<ILucideInfo v-if="notification.type === 'info'" />
|
|
12
|
+
<ILucideCheckCircle v-else-if="notification.type === 'success'" />
|
|
13
|
+
<ILucideAlertTriangle v-else-if="notification.type === 'warning'" />
|
|
14
|
+
<ILucideXCircle v-else-if="notification.type === 'error'" />
|
|
15
|
+
<ILucideBell v-else />
|
|
16
16
|
</div>
|
|
17
17
|
<div class="notification-content">
|
|
18
18
|
<span class="notification-title">{{ notification.title }}</span>
|
|
19
19
|
<span class="notification-time">{{ formatTime(notification.createdAt) }}</span>
|
|
20
20
|
</div>
|
|
21
|
-
<
|
|
21
|
+
<TTag v-if="!notification.isRead" type="primary" size="small">新</TTag>
|
|
22
22
|
</div>
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
@@ -26,6 +26,13 @@
|
|
|
26
26
|
</template>
|
|
27
27
|
|
|
28
28
|
<script setup>
|
|
29
|
+
import { Tag as TTag } from 'tdesign-vue-next';
|
|
30
|
+
import ILucideBell from '~icons/lucide/bell';
|
|
31
|
+
import ILucideInfo from '~icons/lucide/info';
|
|
32
|
+
import ILucideCheckCircle from '~icons/lucide/check-circle';
|
|
33
|
+
import ILucideAlertTriangle from '~icons/lucide/alert-triangle';
|
|
34
|
+
import ILucideXCircle from '~icons/lucide/x-circle';
|
|
35
|
+
|
|
29
36
|
// 组件内部数据
|
|
30
37
|
const notifications = $ref([
|
|
31
38
|
{ id: 1, type: 'warning', title: '系统更新提醒 - v1.1.0 版本已发布', isRead: false, createdAt: Date.now() - 3600000 },
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="section-block">
|
|
3
3
|
<div class="section-header flex items-center gap-2">
|
|
4
|
-
<
|
|
4
|
+
<ILucideInfo />
|
|
5
5
|
<h2>系统概览</h2>
|
|
6
6
|
</div>
|
|
7
7
|
<div class="section-content">
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
<div class="
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<div class="stat-value">{{ permissionStats.menuCount }}</div>
|
|
16
|
-
<div class="stat-label">菜单总数</div>
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
<div class="stat-box stat-success">
|
|
20
|
-
<IconLucideWebhook />
|
|
21
|
-
<div class="stat-content">
|
|
22
|
-
<div class="stat-value">{{ permissionStats.apiCount }}</div>
|
|
23
|
-
<div class="stat-label">接口总数</div>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
<div class="stat-box stat-warning">
|
|
27
|
-
<IconLucideUsers />
|
|
28
|
-
<div class="stat-content">
|
|
29
|
-
<div class="stat-value">{{ permissionStats.roleCount }}</div>
|
|
30
|
-
<div class="stat-label">角色总数</div>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
8
|
+
<div class="info-block">
|
|
9
|
+
<div class="stats-grid">
|
|
10
|
+
<div class="stat-box stat-primary">
|
|
11
|
+
<ILucideMenu />
|
|
12
|
+
<div class="stat-content">
|
|
13
|
+
<div class="stat-value">{{ permissionStats.menuCount }}</div>
|
|
14
|
+
<div class="stat-label">菜单总数</div>
|
|
33
15
|
</div>
|
|
34
16
|
</div>
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
<div class="stat-box stat-success">
|
|
18
|
+
<ILucideWebhook />
|
|
19
|
+
<div class="stat-content">
|
|
20
|
+
<div class="stat-value">{{ permissionStats.apiCount }}</div>
|
|
21
|
+
<div class="stat-label">接口总数</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="stat-box stat-warning">
|
|
25
|
+
<ILucideUsers />
|
|
26
|
+
<div class="stat-content">
|
|
27
|
+
<div class="stat-value">{{ permissionStats.roleCount }}</div>
|
|
28
|
+
<div class="stat-label">角色总数</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
37
33
|
</div>
|
|
38
34
|
</div>
|
|
39
35
|
</template>
|
|
40
36
|
|
|
41
37
|
<script setup>
|
|
38
|
+
import ILucideInfo from '~icons/lucide/info';
|
|
39
|
+
import ILucideMenu from '~icons/lucide/menu';
|
|
40
|
+
import ILucideWebhook from '~icons/lucide/webhook';
|
|
41
|
+
import ILucideUsers from '~icons/lucide/users';
|
|
42
42
|
import { $Http } from '@/plugins/http';
|
|
43
43
|
|
|
44
44
|
// 组件内部数据
|
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="section-block">
|
|
3
3
|
<div class="section-header flex items-center gap-2">
|
|
4
|
-
<
|
|
4
|
+
<ILucideActivity />
|
|
5
5
|
<h2>系统资源</h2>
|
|
6
6
|
</div>
|
|
7
7
|
<div class="section-content">
|
|
8
8
|
<div class="resource-compact-list">
|
|
9
9
|
<div class="resource-compact-item">
|
|
10
10
|
<div class="resource-compact-header">
|
|
11
|
-
<
|
|
11
|
+
<ILucideCpu />
|
|
12
12
|
<span class="resource-label">CPU</span>
|
|
13
13
|
<span class="resource-value">{{ systemResources.cpu.usage }}%</span>
|
|
14
14
|
<span class="resource-desc">{{ systemResources.cpu.cores }}核心</span>
|
|
15
15
|
</div>
|
|
16
|
-
<
|
|
16
|
+
<TProgress :percentage="systemResources.cpu.usage" :status="getProgressColor(systemResources.cpu.usage)" />
|
|
17
17
|
</div>
|
|
18
18
|
<div class="resource-compact-item">
|
|
19
19
|
<div class="resource-compact-header">
|
|
20
|
-
<
|
|
20
|
+
<ILucideHardDrive />
|
|
21
21
|
<span class="resource-label">内存</span>
|
|
22
22
|
<span class="resource-value">{{ systemResources.memory.percentage }}%</span>
|
|
23
23
|
<span class="resource-desc">{{ systemResources.memory.used }}GB / {{ systemResources.memory.total }}GB</span>
|
|
24
24
|
</div>
|
|
25
|
-
<
|
|
25
|
+
<TProgress :percentage="systemResources.memory.percentage" :status="getProgressColor(systemResources.memory.percentage)" />
|
|
26
26
|
</div>
|
|
27
27
|
<div class="resource-compact-item">
|
|
28
28
|
<div class="resource-compact-header">
|
|
29
|
-
<
|
|
29
|
+
<ILucideDisc />
|
|
30
30
|
<span class="resource-label">磁盘</span>
|
|
31
31
|
<span class="resource-value">{{ systemResources.disk.percentage }}%</span>
|
|
32
32
|
<span class="resource-desc">{{ systemResources.disk.used }}GB / {{ systemResources.disk.total }}GB</span>
|
|
33
33
|
</div>
|
|
34
|
-
<
|
|
34
|
+
<TProgress :percentage="systemResources.disk.percentage" :status="getProgressColor(systemResources.disk.percentage)" />
|
|
35
35
|
</div>
|
|
36
36
|
</div>
|
|
37
37
|
</div>
|
|
@@ -39,6 +39,11 @@
|
|
|
39
39
|
</template>
|
|
40
40
|
|
|
41
41
|
<script setup>
|
|
42
|
+
import { Progress as TProgress } from 'tdesign-vue-next';
|
|
43
|
+
import ILucideActivity from '~icons/lucide/activity';
|
|
44
|
+
import ILucideCpu from '~icons/lucide/cpu';
|
|
45
|
+
import ILucideHardDrive from '~icons/lucide/hard-drive';
|
|
46
|
+
import ILucideDisc from '~icons/lucide/disc';
|
|
42
47
|
import { $Http } from '@/plugins/http';
|
|
43
48
|
|
|
44
49
|
// 组件内部数据
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="section-block user-info-card">
|
|
3
3
|
<div class="user-header">
|
|
4
4
|
<div class="user-avatar">
|
|
5
|
-
<
|
|
5
|
+
<ILucideUser />
|
|
6
6
|
</div>
|
|
7
7
|
<div class="user-basic">
|
|
8
8
|
<div class="user-name">{{ $Data.userInfo.nickname || $Data.userInfo.name || $Data.userInfo.username || '未设置' }}</div>
|
|
@@ -11,32 +11,38 @@
|
|
|
11
11
|
</div>
|
|
12
12
|
<div class="user-details">
|
|
13
13
|
<div class="detail-item">
|
|
14
|
-
<
|
|
14
|
+
<ILucideMail />
|
|
15
15
|
<span>{{ $Data.userInfo.email || '未设置' }}</span>
|
|
16
16
|
</div>
|
|
17
17
|
<div v-if="$Data.userInfo.phone" class="detail-item">
|
|
18
|
-
<
|
|
18
|
+
<ILucidePhone />
|
|
19
19
|
<span>{{ $Data.userInfo.phone }}</span>
|
|
20
20
|
</div>
|
|
21
21
|
<div v-if="$Data.userInfo.lastLoginTime" class="detail-item">
|
|
22
|
-
<
|
|
22
|
+
<ILucideClock />
|
|
23
23
|
<span>{{ $Method.formatTime($Data.userInfo.lastLoginTime) }}</span>
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
26
|
|
|
27
27
|
<!-- 仅 dev 角色显示刷新缓存按钮 -->
|
|
28
28
|
<div v-if="$Data.userInfo.roleCode === 'dev'" class="user-actions">
|
|
29
|
-
<
|
|
29
|
+
<TButton theme="primary" size="mini" :loading="$Data.refreshing" @click="$Method.handleRefreshCache">
|
|
30
30
|
<template #icon>
|
|
31
|
-
<
|
|
31
|
+
<ILucideRotateCw />
|
|
32
32
|
</template>
|
|
33
33
|
刷新缓存
|
|
34
|
-
</
|
|
34
|
+
</TButton>
|
|
35
35
|
</div>
|
|
36
36
|
</div>
|
|
37
37
|
</template>
|
|
38
38
|
|
|
39
39
|
<script setup>
|
|
40
|
+
import { Button as TButton, MessagePlugin } from 'tdesign-vue-next';
|
|
41
|
+
import ILucideUser from '~icons/lucide/user';
|
|
42
|
+
import ILucideMail from '~icons/lucide/mail';
|
|
43
|
+
import ILucidePhone from '~icons/lucide/phone';
|
|
44
|
+
import ILucideClock from '~icons/lucide/clock';
|
|
45
|
+
import ILucideRotateCw from '~icons/lucide/rotate-cw';
|
|
40
46
|
import { $Http } from '@/plugins/http';
|
|
41
47
|
|
|
42
48
|
// 响应式数据
|
|
@@ -77,22 +83,13 @@ const $Method = {
|
|
|
77
83
|
messages.push(`角色缓存: ${roles.count} 个`);
|
|
78
84
|
}
|
|
79
85
|
|
|
80
|
-
|
|
81
|
-
message: `缓存刷新成功!${messages.join(',')}`,
|
|
82
|
-
duration: 3000
|
|
83
|
-
});
|
|
86
|
+
MessagePlugin.success(`缓存刷新成功!${messages.join(',')}`);
|
|
84
87
|
} else {
|
|
85
|
-
|
|
86
|
-
message: result.msg || '部分缓存刷新失败',
|
|
87
|
-
duration: 3000
|
|
88
|
-
});
|
|
88
|
+
MessagePlugin.warning(result.msg || '部分缓存刷新失败');
|
|
89
89
|
}
|
|
90
90
|
} catch (error) {
|
|
91
91
|
console.error('刷新缓存失败:', error);
|
|
92
|
-
|
|
93
|
-
message: '刷新缓存失败,请稍后重试',
|
|
94
|
-
duration: 3000
|
|
95
|
-
});
|
|
92
|
+
MessagePlugin.error('刷新缓存失败,请稍后重试');
|
|
96
93
|
} finally {
|
|
97
94
|
$Data.refreshing = false;
|
|
98
95
|
}
|
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
2
|
+
<TForm :model="$Data.formData" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)" class="login-form" label-width="90px" label-position="left" :show-message="false">
|
|
3
|
+
<TFormItem prop="account" label="账号">
|
|
4
|
+
<TInput v-model="$Data.formData.account" placeholder="请输入用户名或邮箱" size="large" clearable>
|
|
5
5
|
<template #prefix-icon>
|
|
6
|
-
<
|
|
6
|
+
<ILucideUser />
|
|
7
7
|
</template>
|
|
8
|
-
</
|
|
9
|
-
</
|
|
8
|
+
</TInput>
|
|
9
|
+
</TFormItem>
|
|
10
10
|
|
|
11
|
-
<
|
|
12
|
-
<
|
|
11
|
+
<TFormItem prop="password" label="密码">
|
|
12
|
+
<TInput v-model="$Data.formData.password" type="password" placeholder="请输入密码" size="large" clearable>
|
|
13
13
|
<template #prefix-icon>
|
|
14
|
-
<
|
|
14
|
+
<ILucideLock />
|
|
15
15
|
</template>
|
|
16
|
-
</
|
|
17
|
-
</
|
|
16
|
+
</TInput>
|
|
17
|
+
</TFormItem>
|
|
18
18
|
|
|
19
19
|
<div class="form-footer">
|
|
20
20
|
<a href="#" class="forgot-password">忘记密码?</a>
|
|
21
21
|
</div>
|
|
22
22
|
|
|
23
|
-
<
|
|
24
|
-
</
|
|
23
|
+
<TButton theme="primary" class="auth-btn" size="large" :loading="$Data.loading" @click="$Method.apiLogin"> 登录 </TButton>
|
|
24
|
+
</TForm>
|
|
25
25
|
</template>
|
|
26
26
|
|
|
27
27
|
<script setup>
|
|
28
|
+
import { Form as TForm, FormItem as TFormItem, Input as TInput, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
|
|
29
|
+
import ILucideUser from '~icons/lucide/user';
|
|
30
|
+
import ILucideLock from '~icons/lucide/lock';
|
|
28
31
|
import { $Http } from '@/plugins/http';
|
|
29
32
|
import { $Storage } from '@/plugins/storage';
|
|
30
33
|
|
|
@@ -94,15 +97,15 @@ const $Method = {
|
|
|
94
97
|
max-width: 450px;
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
.
|
|
100
|
+
.t-form__item {
|
|
98
101
|
width: 100%;
|
|
99
102
|
margin-bottom: 1.2rem;
|
|
100
103
|
|
|
101
|
-
:deep(.
|
|
104
|
+
:deep(.t-form__controls) {
|
|
102
105
|
width: 100%;
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
:deep(.
|
|
108
|
+
:deep(.t-input) {
|
|
106
109
|
width: 100%;
|
|
107
110
|
background: #f8f9fa;
|
|
108
111
|
border: 1px solid #e0e0e0;
|
|
@@ -159,7 +162,7 @@ const $Method = {
|
|
|
159
162
|
box-shadow: 0 3px 10px rgba(72, 177, 159, 0.3);
|
|
160
163
|
}
|
|
161
164
|
|
|
162
|
-
:deep(.
|
|
165
|
+
:deep(.t-button__text) {
|
|
163
166
|
color: #fff;
|
|
164
167
|
}
|
|
165
168
|
}
|
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
2
|
+
<TForm :model="$Data.formData" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)" class="login-form" label-width="70px" label-position="left">
|
|
3
|
+
<TFormItem prop="username" label="用户名">
|
|
4
|
+
<TInput v-model="$Data.formData.username" placeholder="请输入用户名" size="large" clearable>
|
|
5
5
|
<template #prefix-icon>
|
|
6
|
-
<
|
|
6
|
+
<ILucideUser />
|
|
7
7
|
</template>
|
|
8
|
-
</
|
|
9
|
-
</
|
|
8
|
+
</TInput>
|
|
9
|
+
</TFormItem>
|
|
10
10
|
|
|
11
|
-
<
|
|
12
|
-
<
|
|
11
|
+
<TFormItem prop="email" label="邮箱">
|
|
12
|
+
<TInput v-model="$Data.formData.email" placeholder="请输入邮箱" size="large" clearable>
|
|
13
13
|
<template #prefix-icon>
|
|
14
|
-
<
|
|
14
|
+
<ILucideMail />
|
|
15
15
|
</template>
|
|
16
|
-
</
|
|
17
|
-
</
|
|
16
|
+
</TInput>
|
|
17
|
+
</TFormItem>
|
|
18
18
|
|
|
19
|
-
<
|
|
20
|
-
<
|
|
19
|
+
<TFormItem prop="password" label="密码">
|
|
20
|
+
<TInput v-model="$Data.formData.password" type="password" placeholder="请输入密码" size="large" clearable>
|
|
21
21
|
<template #prefix-icon>
|
|
22
|
-
<
|
|
22
|
+
<ILucideLock />
|
|
23
23
|
</template>
|
|
24
|
-
</
|
|
25
|
-
</
|
|
24
|
+
</TInput>
|
|
25
|
+
</TFormItem>
|
|
26
26
|
|
|
27
|
-
<
|
|
28
|
-
<
|
|
27
|
+
<TFormItem prop="nickname" label="昵称">
|
|
28
|
+
<TInput v-model="$Data.formData.nickname" placeholder="请输入昵称(选填)" size="large" clearable>
|
|
29
29
|
<template #prefix-icon>
|
|
30
|
-
<
|
|
30
|
+
<ILucideSmile />
|
|
31
31
|
</template>
|
|
32
|
-
</
|
|
33
|
-
</
|
|
32
|
+
</TInput>
|
|
33
|
+
</TFormItem>
|
|
34
34
|
|
|
35
|
-
<
|
|
36
|
-
</
|
|
35
|
+
<TButton theme="primary" class="auth-btn" size="large" :loading="$Data.loading" @click="$Method.handleSubmit"> 注册 </TButton>
|
|
36
|
+
</TForm>
|
|
37
37
|
</template>
|
|
38
38
|
|
|
39
39
|
<script setup>
|
|
40
|
+
import { Form as TForm, FormItem as TFormItem, Input as TInput, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
|
|
41
|
+
import ILucideUser from '~icons/lucide/user';
|
|
42
|
+
import ILucideMail from '~icons/lucide/mail';
|
|
43
|
+
import ILucideLock from '~icons/lucide/lock';
|
|
44
|
+
import ILucideSmile from '~icons/lucide/smile';
|
|
40
45
|
import { $Http } from '@/plugins/http';
|
|
41
46
|
|
|
42
47
|
const emit = defineEmits(['success']);
|
|
@@ -115,15 +120,15 @@ const $Method = {
|
|
|
115
120
|
max-width: 450px;
|
|
116
121
|
}
|
|
117
122
|
|
|
118
|
-
.
|
|
123
|
+
.t-form__item {
|
|
119
124
|
width: 100%;
|
|
120
125
|
margin-bottom: 1.2rem;
|
|
121
126
|
|
|
122
|
-
:deep(.
|
|
127
|
+
:deep(.t-form__controls) {
|
|
123
128
|
width: 100%;
|
|
124
129
|
}
|
|
125
130
|
|
|
126
|
-
:deep(.
|
|
131
|
+
:deep(.t-input) {
|
|
127
132
|
width: 100%;
|
|
128
133
|
background: #f8f9fa;
|
|
129
134
|
border: 1px solid #e0e0e0;
|
|
@@ -163,7 +168,7 @@ const $Method = {
|
|
|
163
168
|
box-shadow: 0 3px 10px rgba(72, 177, 159, 0.3);
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
:deep(.
|
|
171
|
+
:deep(.t-button__text) {
|
|
167
172
|
color: #fff;
|
|
168
173
|
}
|
|
169
174
|
}
|
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
</
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
</
|
|
10
|
-
<
|
|
11
|
-
<
|
|
12
|
-
</
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
</
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
</
|
|
21
|
-
</
|
|
22
|
-
</
|
|
1
|
+
<template>
|
|
2
|
+
<TDialog v-model:visible="$Data.visible" :title="$Prop.actionType === 'add' ? '添加菜单' : '编辑菜单'" width="600px" :append-to-body="true" :show-footer="true" top="10vh">
|
|
3
|
+
<TForm :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)">
|
|
4
|
+
<TFormItem label="菜单名称" prop="name">
|
|
5
|
+
<TInput v-model="$Data.formData.name" placeholder="请输入菜单名称" />
|
|
6
|
+
</TFormItem>
|
|
7
|
+
<TFormItem label="菜单路径" prop="path">
|
|
8
|
+
<TInput v-model="$Data.formData.path" placeholder="请输入菜单路径,如:/user" />
|
|
9
|
+
</TFormItem>
|
|
10
|
+
<TFormItem label="图标" prop="icon">
|
|
11
|
+
<TInput v-model="$Data.formData.icon" placeholder="请输入图标名称,如:User" />
|
|
12
|
+
</TFormItem>
|
|
13
|
+
<TFormItem label="排序" prop="sort">
|
|
14
|
+
<TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" />
|
|
15
|
+
</TFormItem>
|
|
16
|
+
<TFormItem label="状态" prop="state">
|
|
17
|
+
<TRadioGroup v-model="$Data.formData.state">
|
|
18
|
+
<TRadio :label="1">正常</TRadio>
|
|
19
|
+
<TRadio :label="2">禁用</TRadio>
|
|
20
|
+
</TRadioGroup>
|
|
21
|
+
</TFormItem>
|
|
22
|
+
</TForm>
|
|
23
23
|
<template #footer>
|
|
24
|
-
<
|
|
25
|
-
<
|
|
24
|
+
<TButton @click="$Method.onClose">取消</TButton>
|
|
25
|
+
<TButton theme="primary" @click="$Method.onSubmit">确定</TButton>
|
|
26
26
|
</template>
|
|
27
|
-
</
|
|
27
|
+
</TDialog>
|
|
28
28
|
</template>
|
|
29
29
|
|
|
30
30
|
<script setup>
|
|
31
31
|
import { watch } from 'vue';
|
|
32
|
+
import { Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, InputNumber as TInputNumber, RadioGroup as TRadioGroup, Radio as TRadio, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
|
|
32
33
|
import { $Http } from '@/plugins/http';
|
|
33
34
|
|
|
34
35
|
const $Prop = defineProps({
|
package/views/menu/index.vue
CHANGED
|
@@ -2,53 +2,53 @@
|
|
|
2
2
|
<div class="page-menu page-table">
|
|
3
3
|
<div class="main-tool">
|
|
4
4
|
<div class="left">
|
|
5
|
-
<
|
|
5
|
+
<TButton theme="primary" @click="$Method.onAction('add', {})">
|
|
6
6
|
<template #icon>
|
|
7
|
-
<
|
|
7
|
+
<ILucidePlus />
|
|
8
8
|
</template>
|
|
9
9
|
添加菜单
|
|
10
|
-
</
|
|
10
|
+
</TButton>
|
|
11
11
|
</div>
|
|
12
12
|
<div class="right">
|
|
13
|
-
<
|
|
13
|
+
<TButton @click="$Method.handleRefresh">
|
|
14
14
|
<template #icon>
|
|
15
|
-
<
|
|
15
|
+
<ILucideRotateCw />
|
|
16
16
|
</template>
|
|
17
17
|
刷新
|
|
18
|
-
</
|
|
18
|
+
</TButton>
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
21
|
<div class="main-table">
|
|
22
|
-
<
|
|
22
|
+
<TTable :data="$Data.menuList" :columns="$Data.columns" header-cell-class-name="custom-table-cell-class" size="small" height="100%" row-key="id">
|
|
23
23
|
<template #icon="{ row }">
|
|
24
|
-
<
|
|
24
|
+
<ILucideSquare v-if="row.icon" />
|
|
25
25
|
<span v-else>-</span>
|
|
26
26
|
</template>
|
|
27
27
|
<template #state="{ row }">
|
|
28
|
-
<
|
|
29
|
-
<
|
|
30
|
-
<
|
|
28
|
+
<TTag v-if="row.state === 1" theme="success">正常</TTag>
|
|
29
|
+
<TTag v-else-if="row.state === 2" theme="warning">禁用</TTag>
|
|
30
|
+
<TTag v-else theme="danger">已删除</TTag>
|
|
31
31
|
</template>
|
|
32
32
|
<template #operation="{ row }">
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
<
|
|
37
|
-
<
|
|
33
|
+
<TDropdown trigger="click" min-column-width="120" @click="(data) => $Method.onAction(data.value, row)">
|
|
34
|
+
<TButton variant="text" size="small">操作</TButton>
|
|
35
|
+
<TDropdownMenu slot="dropdown">
|
|
36
|
+
<TDropdownItem value="upd">
|
|
37
|
+
<ILucidePencil />
|
|
38
38
|
编辑
|
|
39
|
-
</
|
|
40
|
-
<
|
|
41
|
-
<
|
|
39
|
+
</TDropdownItem>
|
|
40
|
+
<TDropdownItem value="del" :divider="true">
|
|
41
|
+
<ILucideTrash2 style="width: 14px; height: 14px; margin-right: 6px" />
|
|
42
42
|
删除
|
|
43
|
-
</
|
|
44
|
-
</
|
|
45
|
-
</
|
|
43
|
+
</TDropdownItem>
|
|
44
|
+
</TDropdownMenu>
|
|
45
|
+
</TDropdown>
|
|
46
46
|
</template>
|
|
47
|
-
</
|
|
47
|
+
</TTable>
|
|
48
48
|
</div>
|
|
49
49
|
|
|
50
50
|
<div class="main-page">
|
|
51
|
-
<
|
|
51
|
+
<TPagination :current-page="$Data.pagerConfig.currentPage" :page-size="$Data.pagerConfig.pageSize" :total="$Data.pagerConfig.total" @current-change="$Method.onPageChange" @size-change="$Method.handleSizeChange" />
|
|
52
52
|
</div>
|
|
53
53
|
|
|
54
54
|
<!-- 编辑对话框组件 -->
|
|
@@ -57,6 +57,12 @@
|
|
|
57
57
|
</template>
|
|
58
58
|
|
|
59
59
|
<script setup>
|
|
60
|
+
import { Button as TButton, Table as TTable, Tag as TTag, Dropdown as TDropdown, DropdownMenu as TDropdownMenu, DropdownItem as TDropdownItem, Pagination as TPagination, MessagePlugin, DialogPlugin } from 'tdesign-vue-next';
|
|
61
|
+
import ILucidePlus from '~icons/lucide/plus';
|
|
62
|
+
import ILucideRotateCw from '~icons/lucide/rotate-cw';
|
|
63
|
+
import ILucideSquare from '~icons/lucide/square';
|
|
64
|
+
import ILucidePencil from '~icons/lucide/pencil';
|
|
65
|
+
import ILucideTrash2 from '~icons/lucide/trash-2';
|
|
60
66
|
import EditDialog from './components/edit.vue';
|
|
61
67
|
import { $Http } from '@/plugins/http';
|
|
62
68
|
|