@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.
Files changed (61) hide show
  1. package/apis/admin/ins.ts +11 -15
  2. package/apis/admin/upd.ts +1 -13
  3. package/apis/auth/login.ts +49 -5
  4. package/apis/email/config.ts +16 -0
  5. package/apis/email/logList.ts +13 -0
  6. package/apis/email/send.ts +42 -0
  7. package/apis/email/verify.ts +12 -0
  8. package/apis/loginLog/list.ts +13 -0
  9. package/apis/operateLog/list.ts +13 -0
  10. package/apis/sysConfig/all.ts +12 -0
  11. package/apis/sysConfig/del.ts +30 -0
  12. package/apis/sysConfig/get.ts +31 -0
  13. package/apis/sysConfig/ins.ts +38 -0
  14. package/apis/sysConfig/list.ts +14 -0
  15. package/apis/sysConfig/upd.ts +50 -0
  16. package/package.json +14 -3
  17. package/plugins/email.ts +206 -0
  18. package/styles/variables.scss +121 -60
  19. package/tables/admin.json +12 -15
  20. package/tables/emailLog.json +69 -0
  21. package/tables/loginLog.json +96 -0
  22. package/tables/operateLog.json +82 -0
  23. package/tables/role.json +1 -1
  24. package/tables/sysConfig.json +53 -0
  25. package/views/403_1/meta.json +4 -0
  26. package/views/{dict → config/dict}/index.vue +27 -38
  27. package/views/config/dict/meta.json +4 -0
  28. package/views/config/meta.json +4 -0
  29. package/views/config/system/components/edit.vue +179 -0
  30. package/views/config/system/index.vue +256 -0
  31. package/views/config/system/meta.json +4 -0
  32. package/views/index/index.vue +46 -9
  33. package/views/index/meta.json +4 -0
  34. package/views/log/email/index.vue +285 -0
  35. package/views/log/email/meta.json +4 -0
  36. package/views/log/login/index.vue +180 -0
  37. package/views/log/login/meta.json +4 -0
  38. package/views/log/meta.json +4 -0
  39. package/views/log/operate/index.vue +242 -0
  40. package/views/log/operate/meta.json +4 -0
  41. package/views/login_1/meta.json +4 -0
  42. package/views/{admin → people/admin}/components/edit.vue +22 -24
  43. package/views/{admin → people/admin}/index.vue +21 -61
  44. package/views/people/admin/meta.json +4 -0
  45. package/views/people/meta.json +4 -0
  46. package/views/{api → permission/api}/index.vue +17 -55
  47. package/views/permission/api/meta.json +4 -0
  48. package/views/{menu → permission/menu}/index.vue +17 -56
  49. package/views/permission/menu/meta.json +4 -0
  50. package/views/permission/meta.json +4 -0
  51. package/views/{role → permission/role}/components/api.vue +13 -38
  52. package/views/{role → permission/role}/components/edit.vue +9 -8
  53. package/views/{role → permission/role}/components/menu.vue +2 -25
  54. package/views/{role → permission/role}/index.vue +27 -36
  55. package/views/permission/role/meta.json +4 -0
  56. /package/views/{403 → 403_1}/index.vue +0 -0
  57. /package/views/{dict → config/dict}/components/edit.vue +0 -0
  58. /package/views/{login → login_1}/components/emailLoginForm.vue +0 -0
  59. /package/views/{login → login_1}/components/registerForm.vue +0 -0
  60. /package/views/{login → login_1}/components/welcomePanel.vue +0 -0
  61. /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 v-bind="withTableProps()" :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" select-on-row-click :selected-row-keys="$Data.selectedRowKeys" :active-row-keys="$Data.activeRowKeys" @select-change="$Method.onSelectChange" @active-change="$Method.onActiveChange">
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">操作</TButton>
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, withTableProps } from '@/utils';
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
- colKey: 'row-select',
88
- type: 'single',
89
- width: 50,
90
- fixed: 'left',
91
- checkProps: { allowUncheck: true },
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, { activeRowData }) {
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 (activeRowData && activeRowData.length > 0) {
215
- $Data.currentRow = activeRowData[0];
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
 
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "管理员",
3
+ "order": 1
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "人员管理",
3
+ "order": 10
4
+ }
@@ -20,7 +20,7 @@
20
20
 
21
21
  <div class="main-content">
22
22
  <div class="main-table">
23
- <TTable v-bind="withTableProps()" :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" :selected-row-keys="$Data.selectedRowKeys" :active-row-keys="$Data.activeRowKeys" @select-change="$Method.onSelectChange" @active-change="$Method.onActiveChange">
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, withTableProps } from '@/utils';
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
- colKey: 'row-select',
80
- type: 'single',
81
- width: 50,
82
- fixed: 'left',
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, { activeRowData }) {
125
+ onActiveChange(value, context) {
126
+ // 禁止取消高亮:如果新值为空,保持当前选中
127
+ if (value.length === 0 && $Data.activeRowKeys.length > 0) {
128
+ return;
129
+ }
162
130
  $Data.activeRowKeys = value;
163
- $Data.selectedRowKeys = value;
164
- if (activeRowData && activeRowData.length > 0) {
165
- $Data.currentRow = activeRowData[0];
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
  };
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "接口列表",
3
+ "order": 3
4
+ }
@@ -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" :selected-row-keys="$Data.selectedRowKeys" :active-row-keys="$Data.activeRowKeys" @select-change="$Method.onSelectChange" @active-change="$Method.onActiveChange">
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
- colKey: 'row-select',
57
- type: 'single',
58
- width: 50,
59
- fixed: 'left',
60
- checkProps: { allowUncheck: true },
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, { activeRowData }) {
128
+ onActiveChange(value, context) {
129
+ // 禁止取消高亮:如果新值为空,保持当前选中
130
+ if (value.length === 0 && $Data.activeRowKeys.length > 0) {
131
+ return;
132
+ }
166
133
  $Data.activeRowKeys = value;
167
- $Data.selectedRowKeys = value;
168
- if (activeRowData && activeRowData.length > 0) {
169
- $Data.currentRow = activeRowData[0];
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
  };
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "菜单列表",
3
+ "order": 2
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "权限设置",
3
+ "order": 20
4
+ }
@@ -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" class="api-group">
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-left">
28
- <TButton size="small" @click="$Method.onCheckAll">全选</TButton>
29
- <TButton size="small" @click="$Method.onUncheckAll">取消全选</TButton>
30
- </div>
31
- <div class="footer-right">
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
- :deep(.t-dialog__footer) {
256
+ .dialog-footer {
257
+ width: 100%;
272
258
  display: flex;
273
- justify-content: space-between;
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" type="textarea" placeholder="请输入角色描述" :rows="3" />
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 :label="1">正常</TRadio>
20
- <TRadio :label="2">禁用</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 res = await $Http($Prop.actionType === 'upd' ? '/addon/admin/roleUpd' : '/addon/admin/roleIns', $Data.formData);
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($Prop.actionType === 'upd' ? '更新成功' : '添加成功');
124
- $Data.visible = false;
125
+ MessagePlugin.success(res.msg);
125
126
  $Emit('success');
127
+ $Method.onClose();
126
128
  } catch (error) {
127
- console.error('提交失败:', error);
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" node-key="id" show-checkbox default-expand-all :props="{ label: 'name' }" :ref="(el) => ($From.tree = el)" />
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) {