@befly-addon/admin 1.0.55 → 1.0.57
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/apis/admin/ins.ts +11 -15
- package/apis/admin/upd.ts +1 -13
- package/apis/auth/login.ts +49 -5
- package/apis/email/config.ts +16 -0
- package/apis/email/logList.ts +13 -0
- package/apis/email/send.ts +42 -0
- package/apis/email/verify.ts +12 -0
- package/apis/loginLog/list.ts +13 -0
- package/apis/operateLog/list.ts +13 -0
- package/apis/sysConfig/all.ts +12 -0
- package/apis/sysConfig/del.ts +30 -0
- package/apis/sysConfig/get.ts +31 -0
- package/apis/sysConfig/ins.ts +38 -0
- package/apis/sysConfig/list.ts +14 -0
- package/apis/sysConfig/upd.ts +50 -0
- package/package.json +14 -3
- package/plugins/email.ts +206 -0
- package/styles/variables.scss +121 -60
- package/tables/admin.json +12 -15
- package/tables/emailLog.json +69 -0
- package/tables/loginLog.json +96 -0
- package/tables/operateLog.json +82 -0
- package/tables/role.json +1 -1
- package/tables/sysConfig.json +53 -0
- package/views/403_1/meta.json +4 -0
- package/views/{dict → config/dict}/index.vue +27 -38
- package/views/config/dict/meta.json +4 -0
- package/views/config/meta.json +4 -0
- package/views/config/system/components/edit.vue +179 -0
- package/views/config/system/index.vue +256 -0
- package/views/config/system/meta.json +4 -0
- package/views/index/index.vue +46 -9
- package/views/index/meta.json +4 -0
- package/views/log/email/index.vue +285 -0
- package/views/log/email/meta.json +4 -0
- package/views/log/login/index.vue +180 -0
- package/views/log/login/meta.json +4 -0
- package/views/log/meta.json +4 -0
- package/views/log/operate/index.vue +242 -0
- package/views/log/operate/meta.json +4 -0
- package/views/login_1/meta.json +4 -0
- package/views/{admin → people/admin}/components/edit.vue +22 -24
- package/views/{admin → people/admin}/index.vue +21 -61
- package/views/people/admin/meta.json +4 -0
- package/views/people/meta.json +4 -0
- package/views/{api → permission/api}/index.vue +17 -55
- package/views/permission/api/meta.json +4 -0
- package/views/{menu → permission/menu}/index.vue +17 -56
- package/views/permission/menu/meta.json +4 -0
- package/views/permission/meta.json +4 -0
- package/views/{role → permission/role}/components/api.vue +13 -38
- package/views/{role → permission/role}/components/edit.vue +9 -8
- package/views/{role → permission/role}/components/menu.vue +2 -25
- package/views/{role → permission/role}/index.vue +27 -36
- package/views/permission/role/meta.json +4 -0
- /package/views/{403 → 403_1}/index.vue +0 -0
- /package/views/{dict → config/dict}/components/edit.vue +0 -0
- /package/views/{login → login_1}/components/emailLoginForm.vue +0 -0
- /package/views/{login → login_1}/components/registerForm.vue +0 -0
- /package/views/{login → login_1}/components/welcomePanel.vue +0 -0
- /package/views/{login/index_1.vue → login_1/index.vue} +0 -0
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
<div class="main-content">
|
|
21
21
|
<div class="main-table">
|
|
22
|
-
<TTable
|
|
22
|
+
<TTable :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" :active-row-keys="$Data.activeRowKeys" row-key="id" height="calc(100vh - 94px)" active-row-type="single" @active-change="$Method.onActiveChange">
|
|
23
23
|
<template #state="{ row }">
|
|
24
24
|
<TTag v-if="row.state === 1" shape="round" theme="success" variant="light-outline">正常</TTag>
|
|
25
25
|
<TTag v-else-if="row.state === 2" shape="round" theme="warning" variant="light-outline">禁用</TTag>
|
|
@@ -27,7 +27,10 @@
|
|
|
27
27
|
</template>
|
|
28
28
|
<template #operation="{ row }">
|
|
29
29
|
<TDropdown trigger="click" placement="bottom-right" @click="(data) => $Method.onAction(data.value, row)">
|
|
30
|
-
<TButton theme="primary" size="small"
|
|
30
|
+
<TButton theme="primary" size="small">
|
|
31
|
+
操作
|
|
32
|
+
<template #suffix> <t-icon name="chevron-down" size="16" /></template>
|
|
33
|
+
</TButton>
|
|
31
34
|
<TDropdownMenu slot="dropdown">
|
|
32
35
|
<TDropdownItem value="upd">
|
|
33
36
|
<ILucidePencil />
|
|
@@ -44,17 +47,7 @@
|
|
|
44
47
|
</div>
|
|
45
48
|
|
|
46
49
|
<div class="main-detail">
|
|
47
|
-
<DetailPanel
|
|
48
|
-
:data="$Data.currentRow"
|
|
49
|
-
:fields="[
|
|
50
|
-
{ key: 'id', label: 'ID' },
|
|
51
|
-
{ key: 'username', label: '用户名' },
|
|
52
|
-
{ key: 'email', label: '邮箱' },
|
|
53
|
-
{ key: 'nickname', label: '昵称' },
|
|
54
|
-
{ key: 'roleCode', label: '角色' },
|
|
55
|
-
{ key: 'state', label: '状态' }
|
|
56
|
-
]"
|
|
57
|
-
/>
|
|
50
|
+
<DetailPanel :data="$Data.currentRow" :fields="$Data.columns" />
|
|
58
51
|
</div>
|
|
59
52
|
</div>
|
|
60
53
|
|
|
@@ -76,28 +69,19 @@ import ILucideTrash2 from '~icons/lucide/trash-2';
|
|
|
76
69
|
import EditDialog from './components/edit.vue';
|
|
77
70
|
import DetailPanel from '@/components/DetailPanel.vue';
|
|
78
71
|
import { $Http } from '@/plugins/http';
|
|
79
|
-
import { withDefaultColumns
|
|
72
|
+
import { withDefaultColumns } from '@/utils';
|
|
80
73
|
|
|
81
74
|
// 响应式数据
|
|
82
75
|
const $Data = $ref({
|
|
83
76
|
tableData: [],
|
|
84
77
|
loading: false,
|
|
85
78
|
columns: withDefaultColumns([
|
|
86
|
-
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
ellipsis: false
|
|
93
|
-
},
|
|
94
|
-
{ colKey: 'username', title: '用户名', width: 150, fixed: 'left' },
|
|
95
|
-
{ colKey: 'id', title: '序号', width: 150, align: 'center' },
|
|
96
|
-
{ colKey: 'email', title: '邮箱', width: 200 },
|
|
97
|
-
{ colKey: 'nickname', title: '昵称', width: 150 },
|
|
98
|
-
{ colKey: 'roleCode', title: '角色', width: 120 },
|
|
99
|
-
{ colKey: 'state', title: '状态', width: 100, ellipsis: false },
|
|
100
|
-
{ colKey: 'operation', title: '操作', width: 80, align: 'center', fixed: 'right', ellipsis: false }
|
|
79
|
+
{ colKey: 'username', title: '用户名', fixed: 'left' },
|
|
80
|
+
{ colKey: 'id', title: '序号' },
|
|
81
|
+
{ colKey: 'nickname', title: '昵称' },
|
|
82
|
+
{ colKey: 'roleCode', title: '角色' },
|
|
83
|
+
{ colKey: 'state', title: '状态' },
|
|
84
|
+
{ colKey: 'operation', title: '操作' }
|
|
101
85
|
]),
|
|
102
86
|
pagerConfig: {
|
|
103
87
|
currentPage: 1,
|
|
@@ -110,7 +94,6 @@ const $Data = $ref({
|
|
|
110
94
|
actionType: 'add',
|
|
111
95
|
rowData: {},
|
|
112
96
|
currentRow: null,
|
|
113
|
-
selectedRowKeys: [],
|
|
114
97
|
activeRowKeys: []
|
|
115
98
|
});
|
|
116
99
|
|
|
@@ -131,14 +114,12 @@ const $Method = {
|
|
|
131
114
|
$Data.tableData = res.data.lists || [];
|
|
132
115
|
$Data.pagerConfig.total = res.data.total || 0;
|
|
133
116
|
|
|
134
|
-
//
|
|
117
|
+
// 自动高亮第一行
|
|
135
118
|
if ($Data.tableData.length > 0) {
|
|
136
119
|
$Data.currentRow = $Data.tableData[0];
|
|
137
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
138
120
|
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
139
121
|
} else {
|
|
140
122
|
$Data.currentRow = null;
|
|
141
|
-
$Data.selectedRowKeys = [];
|
|
142
123
|
$Data.activeRowKeys = [];
|
|
143
124
|
}
|
|
144
125
|
} catch (error) {
|
|
@@ -189,37 +170,16 @@ const $Method = {
|
|
|
189
170
|
$Method.apiAdminList();
|
|
190
171
|
},
|
|
191
172
|
|
|
192
|
-
// 单选变化
|
|
193
|
-
onSelectChange(value, { selectedRowData }) {
|
|
194
|
-
$Data.selectedRowKeys = value;
|
|
195
|
-
$Data.activeRowKeys = value;
|
|
196
|
-
// 更新当前选中的行数据
|
|
197
|
-
if (selectedRowData && selectedRowData.length > 0) {
|
|
198
|
-
$Data.currentRow = selectedRowData[0];
|
|
199
|
-
} else if ($Data.tableData.length > 0) {
|
|
200
|
-
// 如果取消选中,默认显示第一行
|
|
201
|
-
$Data.currentRow = $Data.tableData[0];
|
|
202
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
203
|
-
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
204
|
-
} else {
|
|
205
|
-
$Data.currentRow = null;
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
|
|
209
173
|
// 高亮行变化
|
|
210
|
-
onActiveChange(value,
|
|
174
|
+
onActiveChange(value, context) {
|
|
175
|
+
// 禁止取消高亮:如果新值为空,保持当前选中
|
|
176
|
+
if (value.length === 0 && $Data.activeRowKeys.length > 0) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
211
179
|
$Data.activeRowKeys = value;
|
|
212
|
-
$Data.selectedRowKeys = value;
|
|
213
180
|
// 更新当前高亮的行数据
|
|
214
|
-
if (
|
|
215
|
-
$Data.currentRow =
|
|
216
|
-
} else if ($Data.tableData.length > 0) {
|
|
217
|
-
// 如果取消高亮,默认显示第一行
|
|
218
|
-
$Data.currentRow = $Data.tableData[0];
|
|
219
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
220
|
-
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
221
|
-
} else {
|
|
222
|
-
$Data.currentRow = null;
|
|
181
|
+
if (context.activeRowList && context.activeRowList.length > 0) {
|
|
182
|
+
$Data.currentRow = context.activeRowList[0].row;
|
|
223
183
|
}
|
|
224
184
|
},
|
|
225
185
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
<div class="main-content">
|
|
22
22
|
<div class="main-table">
|
|
23
|
-
<TTable
|
|
23
|
+
<TTable :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" :active-row-keys="$Data.activeRowKeys" row-key="id" height="calc(100vh - 94px)" active-row-type="single" @active-change="$Method.onActiveChange">
|
|
24
24
|
<template #method="{ row }">
|
|
25
25
|
<TTag v-if="row.method === 'GET'" shape="round" theme="success" variant="light-outline">GET</TTag>
|
|
26
26
|
<TTag v-else-if="row.method === 'POST'" shape="round" theme="primary" variant="light-outline">POST</TTag>
|
|
@@ -36,17 +36,7 @@
|
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
<div class="main-detail">
|
|
39
|
-
<DetailPanel
|
|
40
|
-
:data="$Data.currentRow"
|
|
41
|
-
:fields="[
|
|
42
|
-
{ key: 'id', label: 'ID' },
|
|
43
|
-
{ key: 'name', label: '接口名称' },
|
|
44
|
-
{ key: 'path', label: '接口路径' },
|
|
45
|
-
{ key: 'method', label: '请求方法' },
|
|
46
|
-
{ key: 'addonName', label: '所属组件', default: '项目' },
|
|
47
|
-
{ key: 'description', label: '接口描述' }
|
|
48
|
-
]"
|
|
49
|
-
>
|
|
39
|
+
<DetailPanel :data="$Data.currentRow" :fields="$Data.columns">
|
|
50
40
|
<template #method="{ value }">
|
|
51
41
|
<TTag v-if="value === 'GET'" shape="round" theme="success" variant="light-outline">GET</TTag>
|
|
52
42
|
<TTag v-else-if="value === 'POST'" shape="round" theme="primary" variant="light-outline">POST</TTag>
|
|
@@ -65,7 +55,7 @@ import { Button as TButton, Table as TTable, Tag as TTag, Input as TInput, Messa
|
|
|
65
55
|
import ILucideRotateCw from '~icons/lucide/rotate-cw';
|
|
66
56
|
import ILucideSearch from '~icons/lucide/search';
|
|
67
57
|
import { $Http } from '@/plugins/http';
|
|
68
|
-
import { withDefaultColumns
|
|
58
|
+
import { withDefaultColumns } from '@/utils';
|
|
69
59
|
import DetailPanel from '@/components/DetailPanel.vue';
|
|
70
60
|
|
|
71
61
|
// 响应式数据
|
|
@@ -75,22 +65,13 @@ const $Data = $ref({
|
|
|
75
65
|
loading: false,
|
|
76
66
|
searchKeyword: '',
|
|
77
67
|
columns: withDefaultColumns([
|
|
78
|
-
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
checkProps: { allowUncheck: true },
|
|
84
|
-
ellipsis: false
|
|
85
|
-
},
|
|
86
|
-
{ colKey: 'name', title: '接口名称', width: 200, fixed: 'left' },
|
|
87
|
-
{ colKey: 'id', title: '序号', width: 80, align: 'center' },
|
|
88
|
-
{ colKey: 'path', title: '接口路径', width: 350 },
|
|
89
|
-
{ colKey: 'method', title: '请求方法', width: 100, align: 'center', ellipsis: false },
|
|
90
|
-
{ colKey: 'addonName', title: '所属组件', width: 120, ellipsis: false }
|
|
68
|
+
{ colKey: 'name', title: '接口名称' },
|
|
69
|
+
{ colKey: 'id', title: '序号' },
|
|
70
|
+
{ colKey: 'path', title: '接口路径' },
|
|
71
|
+
{ colKey: 'method', title: '请求方法' },
|
|
72
|
+
{ colKey: 'addonName', title: '所属组件' }
|
|
91
73
|
]),
|
|
92
74
|
currentRow: null,
|
|
93
|
-
selectedRowKeys: [],
|
|
94
75
|
activeRowKeys: []
|
|
95
76
|
});
|
|
96
77
|
|
|
@@ -109,14 +90,12 @@ const $Method = {
|
|
|
109
90
|
$Data.allData = list;
|
|
110
91
|
$Data.tableData = list;
|
|
111
92
|
|
|
112
|
-
//
|
|
93
|
+
// 自动高亮第一行
|
|
113
94
|
if ($Data.tableData.length > 0) {
|
|
114
95
|
$Data.currentRow = $Data.tableData[0];
|
|
115
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
116
96
|
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
117
97
|
} else {
|
|
118
98
|
$Data.currentRow = null;
|
|
119
|
-
$Data.selectedRowKeys = [];
|
|
120
99
|
$Data.activeRowKeys = [];
|
|
121
100
|
}
|
|
122
101
|
} catch (error) {
|
|
@@ -142,33 +121,16 @@ const $Method = {
|
|
|
142
121
|
$Data.tableData = $Data.allData.filter((item) => item.name?.toLowerCase().includes(keyword) || item.path?.toLowerCase().includes(keyword));
|
|
143
122
|
},
|
|
144
123
|
|
|
145
|
-
// 单选变化
|
|
146
|
-
onSelectChange(value, { selectedRowData }) {
|
|
147
|
-
$Data.selectedRowKeys = value;
|
|
148
|
-
$Data.activeRowKeys = value;
|
|
149
|
-
if (selectedRowData && selectedRowData.length > 0) {
|
|
150
|
-
$Data.currentRow = selectedRowData[0];
|
|
151
|
-
} else if ($Data.tableData.length > 0) {
|
|
152
|
-
$Data.currentRow = $Data.tableData[0];
|
|
153
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
154
|
-
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
155
|
-
} else {
|
|
156
|
-
$Data.currentRow = null;
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
|
|
160
124
|
// 高亮行变化
|
|
161
|
-
onActiveChange(value,
|
|
125
|
+
onActiveChange(value, context) {
|
|
126
|
+
// 禁止取消高亮:如果新值为空,保持当前选中
|
|
127
|
+
if (value.length === 0 && $Data.activeRowKeys.length > 0) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
162
130
|
$Data.activeRowKeys = value;
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
$Data.currentRow =
|
|
166
|
-
} else if ($Data.tableData.length > 0) {
|
|
167
|
-
$Data.currentRow = $Data.tableData[0];
|
|
168
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
169
|
-
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
170
|
-
} else {
|
|
171
|
-
$Data.currentRow = null;
|
|
131
|
+
// 更新当前高亮的行数据
|
|
132
|
+
if (context.activeRowList && context.activeRowList.length > 0) {
|
|
133
|
+
$Data.currentRow = context.activeRowList[0].row;
|
|
172
134
|
}
|
|
173
135
|
}
|
|
174
136
|
};
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
<div class="main-content">
|
|
15
15
|
<div class="main-table">
|
|
16
|
-
<TTable v-bind="withTreeTableProps()" :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" :
|
|
16
|
+
<TTable v-bind="withTreeTableProps()" :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" :active-row-keys="$Data.activeRowKeys" row-key="id" height="calc(100vh - 94px)" active-row-type="single" @active-change="$Method.onActiveChange">
|
|
17
17
|
<template #state="{ row }">
|
|
18
18
|
<TTag v-if="row.state === 1" shape="round" theme="success" variant="light-outline">正常</TTag>
|
|
19
19
|
<TTag v-else-if="row.state === 2" shape="round" theme="warning" variant="light-outline">禁用</TTag>
|
|
@@ -23,18 +23,7 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
25
|
<div class="main-detail">
|
|
26
|
-
<DetailPanel
|
|
27
|
-
:data="$Data.currentRow"
|
|
28
|
-
:fields="[
|
|
29
|
-
{ key: 'id', label: 'ID' },
|
|
30
|
-
{ key: 'name', label: '菜单名称' },
|
|
31
|
-
{ key: 'path', label: '路由路径' },
|
|
32
|
-
{ key: 'icon', label: '图标' },
|
|
33
|
-
{ key: 'sort', label: '排序' },
|
|
34
|
-
{ key: 'pid', label: '父级ID', default: '顶级菜单' },
|
|
35
|
-
{ key: 'state', label: '状态' }
|
|
36
|
-
]"
|
|
37
|
-
/>
|
|
26
|
+
<DetailPanel :data="$Data.currentRow" :fields="$Data.columns" />
|
|
38
27
|
</div>
|
|
39
28
|
</div>
|
|
40
29
|
</div>
|
|
@@ -52,23 +41,14 @@ const $Data = $ref({
|
|
|
52
41
|
tableData: [],
|
|
53
42
|
loading: false,
|
|
54
43
|
columns: withDefaultColumns([
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
ellipsis: false
|
|
62
|
-
},
|
|
63
|
-
{ colKey: 'name', title: '菜单名称', width: 200, fixed: 'left' },
|
|
64
|
-
{ colKey: 'id', title: '序号', width: 100, align: 'center' },
|
|
65
|
-
{ colKey: 'path', title: '路由路径', width: 250 },
|
|
66
|
-
{ colKey: 'icon', title: '图标', width: 120 },
|
|
67
|
-
{ colKey: 'sort', title: '排序', width: 80, align: 'center' },
|
|
68
|
-
{ colKey: 'state', title: '状态', width: 100, ellipsis: false }
|
|
44
|
+
{ colKey: 'name', title: '菜单名称', fixed: 'left' },
|
|
45
|
+
{ colKey: 'id', title: '序号' },
|
|
46
|
+
{ colKey: 'path', title: '路由路径' },
|
|
47
|
+
{ colKey: 'icon', title: '图标' },
|
|
48
|
+
{ colKey: 'sort', title: '排序' },
|
|
49
|
+
{ colKey: 'state', title: '状态' }
|
|
69
50
|
]),
|
|
70
51
|
currentRow: null,
|
|
71
|
-
selectedRowKeys: [],
|
|
72
52
|
activeRowKeys: []
|
|
73
53
|
});
|
|
74
54
|
|
|
@@ -86,14 +66,12 @@ const $Method = {
|
|
|
86
66
|
// 构建树形结构
|
|
87
67
|
$Data.tableData = $Method.buildTree(res.data || []);
|
|
88
68
|
|
|
89
|
-
//
|
|
69
|
+
// 自动高亮第一行
|
|
90
70
|
if ($Data.tableData.length > 0) {
|
|
91
71
|
$Data.currentRow = $Data.tableData[0];
|
|
92
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
93
72
|
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
94
73
|
} else {
|
|
95
74
|
$Data.currentRow = null;
|
|
96
|
-
$Data.selectedRowKeys = [];
|
|
97
75
|
$Data.activeRowKeys = [];
|
|
98
76
|
}
|
|
99
77
|
} catch (error) {
|
|
@@ -146,33 +124,16 @@ const $Method = {
|
|
|
146
124
|
$Method.apiMenuList();
|
|
147
125
|
},
|
|
148
126
|
|
|
149
|
-
// 单选变化
|
|
150
|
-
onSelectChange(value, { selectedRowData }) {
|
|
151
|
-
$Data.selectedRowKeys = value;
|
|
152
|
-
$Data.activeRowKeys = value;
|
|
153
|
-
if (selectedRowData && selectedRowData.length > 0) {
|
|
154
|
-
$Data.currentRow = selectedRowData[0];
|
|
155
|
-
} else if ($Data.tableData.length > 0) {
|
|
156
|
-
$Data.currentRow = $Data.tableData[0];
|
|
157
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
158
|
-
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
159
|
-
} else {
|
|
160
|
-
$Data.currentRow = null;
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
|
|
164
127
|
// 高亮行变化
|
|
165
|
-
onActiveChange(value,
|
|
128
|
+
onActiveChange(value, context) {
|
|
129
|
+
// 禁止取消高亮:如果新值为空,保持当前选中
|
|
130
|
+
if (value.length === 0 && $Data.activeRowKeys.length > 0) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
166
133
|
$Data.activeRowKeys = value;
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
$Data.currentRow =
|
|
170
|
-
} else if ($Data.tableData.length > 0) {
|
|
171
|
-
$Data.currentRow = $Data.tableData[0];
|
|
172
|
-
$Data.selectedRowKeys = [$Data.tableData[0].id];
|
|
173
|
-
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
174
|
-
} else {
|
|
175
|
-
$Data.currentRow = null;
|
|
134
|
+
// 更新当前高亮的行数据
|
|
135
|
+
if (context.activeRowList && context.activeRowList.length > 0) {
|
|
136
|
+
$Data.currentRow = context.activeRowList[0].row;
|
|
176
137
|
}
|
|
177
138
|
}
|
|
178
139
|
};
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
<!-- 接口分组列表 -->
|
|
14
14
|
<div class="api-container">
|
|
15
|
-
<div v-for="group in $Data.filteredApiData" :key="group.name"
|
|
15
|
+
<div class="api-group" v-for="group in $Data.filteredApiData" :key="group.name">
|
|
16
16
|
<div class="group-header">{{ group.title }}</div>
|
|
17
17
|
<div class="api-checkbox-list">
|
|
18
18
|
<TCheckboxGroup v-model="$Data.checkedApiIds">
|
|
@@ -24,13 +24,11 @@
|
|
|
24
24
|
</div>
|
|
25
25
|
|
|
26
26
|
<template #footer>
|
|
27
|
-
<div class="footer
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<TButton @click="$Method.onClose">取消</TButton>
|
|
33
|
-
<TButton theme="primary" :loading="$Data.submitting" @click="$Method.onSubmit">保存</TButton>
|
|
27
|
+
<div class="dialog-footer">
|
|
28
|
+
<t-space>
|
|
29
|
+
<TButton theme="default" @click="$Method.onClose">取消</TButton>
|
|
30
|
+
<TButton theme="primary" :loading="$Data.submitting" @click="$Method.onSubmit">保存</TButton>
|
|
31
|
+
</t-space>
|
|
34
32
|
</div>
|
|
35
33
|
</template>
|
|
36
34
|
</TDialog>
|
|
@@ -149,22 +147,6 @@ const $Method = {
|
|
|
149
147
|
.filter((group) => group.apis.length > 0);
|
|
150
148
|
},
|
|
151
149
|
|
|
152
|
-
// 全选
|
|
153
|
-
onCheckAll() {
|
|
154
|
-
const allApiIds = [];
|
|
155
|
-
$Data.apiData.forEach((group) => {
|
|
156
|
-
group.apis.forEach((api) => {
|
|
157
|
-
allApiIds.push(api.id);
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
$Data.checkedApiIds = allApiIds;
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
// 取消全选
|
|
164
|
-
onUncheckAll() {
|
|
165
|
-
$Data.checkedApiIds = [];
|
|
166
|
-
},
|
|
167
|
-
|
|
168
150
|
// 提交表单
|
|
169
151
|
async onSubmit() {
|
|
170
152
|
try {
|
|
@@ -214,6 +196,10 @@ $Method.initData();
|
|
|
214
196
|
border-radius: var(--border-radius-small);
|
|
215
197
|
overflow: hidden;
|
|
216
198
|
|
|
199
|
+
.api-checkbox-list {
|
|
200
|
+
padding: 10px;
|
|
201
|
+
}
|
|
202
|
+
|
|
217
203
|
&:last-child {
|
|
218
204
|
margin-bottom: 0;
|
|
219
205
|
}
|
|
@@ -267,20 +253,9 @@ $Method.initData();
|
|
|
267
253
|
}
|
|
268
254
|
}
|
|
269
255
|
|
|
270
|
-
|
|
271
|
-
:
|
|
256
|
+
.dialog-footer {
|
|
257
|
+
width: 100%;
|
|
272
258
|
display: flex;
|
|
273
|
-
justify-content:
|
|
274
|
-
align-items: center;
|
|
275
|
-
|
|
276
|
-
.footer-left {
|
|
277
|
-
display: flex;
|
|
278
|
-
gap: 8px;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.footer-right {
|
|
282
|
-
display: flex;
|
|
283
|
-
gap: 8px;
|
|
284
|
-
}
|
|
259
|
+
justify-content: center;
|
|
285
260
|
}
|
|
286
261
|
</style>
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
<TInput v-model="$Data.formData.code" placeholder="请输入角色代码,如:admin" />
|
|
10
10
|
</TFormItem>
|
|
11
11
|
<TFormItem label="角色描述" prop="description">
|
|
12
|
-
<TInput v-model="$Data.formData.description"
|
|
12
|
+
<TInput v-model="$Data.formData.description" placeholder="请输入角色描述" />
|
|
13
13
|
</TFormItem>
|
|
14
14
|
<TFormItem label="排序" prop="sort">
|
|
15
15
|
<TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" />
|
|
16
16
|
</TFormItem>
|
|
17
17
|
<TFormItem label="状态" prop="state">
|
|
18
18
|
<TRadioGroup v-model="$Data.formData.state">
|
|
19
|
-
<TRadio :
|
|
20
|
-
<TRadio :
|
|
19
|
+
<TRadio :value="1">正常</TRadio>
|
|
20
|
+
<TRadio :value="2">禁用</TRadio>
|
|
21
21
|
</TRadioGroup>
|
|
22
22
|
</TFormItem>
|
|
23
23
|
</TForm>
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
Button as TButton,
|
|
43
43
|
MessagePlugin
|
|
44
44
|
} from 'tdesign-vue-next';
|
|
45
|
+
import { fieldClear } from 'befly-shared/fieldClear';
|
|
45
46
|
import { $Http } from '@/plugins/http';
|
|
46
47
|
|
|
47
48
|
const $Prop = defineProps({
|
|
@@ -118,14 +119,14 @@ const $Method = {
|
|
|
118
119
|
if (!valid) return;
|
|
119
120
|
|
|
120
121
|
$Data.submitting = true;
|
|
121
|
-
const
|
|
122
|
+
const formData = $Prop.actionType === 'add' ? fieldClear($Data.formData, { omitKeys: ['id', 'state'] }) : $Data.formData;
|
|
123
|
+
const res = await $Http($Prop.actionType === 'upd' ? '/addon/admin/role/upd' : '/addon/admin/role/ins', formData);
|
|
122
124
|
|
|
123
|
-
MessagePlugin.success(
|
|
124
|
-
$Data.visible = false;
|
|
125
|
+
MessagePlugin.success(res.msg);
|
|
125
126
|
$Emit('success');
|
|
127
|
+
$Method.onClose();
|
|
126
128
|
} catch (error) {
|
|
127
|
-
|
|
128
|
-
MessagePlugin.error('提交失败');
|
|
129
|
+
MessagePlugin.error(error.msg || '提交失败');
|
|
129
130
|
} finally {
|
|
130
131
|
$Data.submitting = false;
|
|
131
132
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<TDialog v-model:visible="$Data.visible" title="菜单权限" width="600px" :append-to-body="true" :show-footer="true" top="10vh" @close="$Method.onClose">
|
|
3
3
|
<div class="comp-role-menu">
|
|
4
|
-
<TTree :data="$Data.menuTreeData"
|
|
4
|
+
<TTree v-model:value="$Data.menuTreeCheckedKeys" :data="$Data.menuTreeData" value-mode="all" :keys="{ value: 'id', label: 'name', children: 'children' }" checkable expand-all />
|
|
5
5
|
</div>
|
|
6
6
|
<template #footer>
|
|
7
7
|
<TButton @click="$Method.onClose">取消</TButton>
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<script setup>
|
|
14
|
-
import { nextTick } from 'vue';
|
|
15
14
|
import { Dialog as TDialog, Tree as TTree, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
|
|
16
15
|
import { arrayToTree } from '@/utils';
|
|
17
16
|
import { $Http } from '@/plugins/http';
|
|
@@ -29,11 +28,6 @@ const $Prop = defineProps({
|
|
|
29
28
|
|
|
30
29
|
const $Emit = defineEmits(['update:modelValue', 'success']);
|
|
31
30
|
|
|
32
|
-
// 表单引用
|
|
33
|
-
const $From = $shallowRef({
|
|
34
|
-
tree: null
|
|
35
|
-
});
|
|
36
|
-
|
|
37
31
|
const $Data = $ref({
|
|
38
32
|
visible: false,
|
|
39
33
|
submitting: false,
|
|
@@ -85,13 +79,6 @@ const $Method = {
|
|
|
85
79
|
|
|
86
80
|
// roleMenuDetail 返回的 data 直接就是菜单 ID 数组
|
|
87
81
|
$Data.menuTreeCheckedKeys = Array.isArray(res.data) ? res.data : [];
|
|
88
|
-
|
|
89
|
-
// 等待树渲染完成后设置选中状态
|
|
90
|
-
nextTick(() => {
|
|
91
|
-
if ($From.tree && $Data.menuTreeCheckedKeys.length > 0) {
|
|
92
|
-
$From.tree.setCheckedKeys($Data.menuTreeCheckedKeys);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
82
|
} catch (error) {
|
|
96
83
|
console.error('加载角色菜单失败:', error);
|
|
97
84
|
}
|
|
@@ -100,21 +87,11 @@ const $Method = {
|
|
|
100
87
|
// 提交表单
|
|
101
88
|
async onSubmit() {
|
|
102
89
|
try {
|
|
103
|
-
if (!$From.tree) {
|
|
104
|
-
MessagePlugin.error('菜单树未初始化');
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
90
|
$Data.submitting = true;
|
|
109
91
|
|
|
110
|
-
// 获取选中的节点(包括半选中的父节点)
|
|
111
|
-
const checkedKeys = $From.tree.getCheckedKeys();
|
|
112
|
-
const halfCheckedKeys = $From.tree.getHalfCheckedKeys();
|
|
113
|
-
const menuIds = [...checkedKeys, ...halfCheckedKeys];
|
|
114
|
-
|
|
115
92
|
const res = await $Http('/addon/admin/role/menuSave', {
|
|
116
93
|
roleId: $Prop.rowData.id,
|
|
117
|
-
menuIds
|
|
94
|
+
menuIds: $Data.menuTreeCheckedKeys
|
|
118
95
|
});
|
|
119
96
|
|
|
120
97
|
if (res.code === 0) {
|