befly-admin-ui 1.10.1 → 1.10.5

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 (35) hide show
  1. package/components/detailPanel.vue +52 -54
  2. package/components/pageDialog.vue +131 -117
  3. package/components/pageTableDetail.vue +381 -402
  4. package/layouts/default.vue +212 -215
  5. package/package.json +2 -2
  6. package/views/config/dict/components/edit.vue +83 -60
  7. package/views/config/dict/index.vue +51 -55
  8. package/views/config/dictType/components/edit.vue +81 -57
  9. package/views/config/dictType/index.vue +37 -39
  10. package/views/config/system/components/edit.vue +97 -86
  11. package/views/config/system/index.vue +35 -37
  12. package/views/index/components/addonList.vue +14 -11
  13. package/views/index/components/environmentInfo.vue +25 -22
  14. package/views/index/components/operationLogs.vue +20 -16
  15. package/views/index/components/performanceMetrics.vue +24 -21
  16. package/views/index/components/serviceStatus.vue +26 -22
  17. package/views/index/components/systemNotifications.vue +24 -19
  18. package/views/index/components/systemOverview.vue +368 -385
  19. package/views/index/components/systemResources.vue +22 -19
  20. package/views/index/components/userInfo.vue +56 -56
  21. package/views/log/email/index.vue +96 -85
  22. package/views/log/error/index.vue +111 -117
  23. package/views/log/login/index.vue +15 -13
  24. package/views/log/operate/index.vue +31 -31
  25. package/views/login_1/index.vue +50 -32
  26. package/views/people/admin/components/edit.vue +1 -1
  27. package/views/people/admin/index.vue +27 -28
  28. package/views/permission/api/index.vue +44 -45
  29. package/views/permission/menu/index.vue +35 -35
  30. package/views/permission/role/components/api.vue +143 -144
  31. package/views/permission/role/components/edit.vue +74 -52
  32. package/views/permission/role/components/menu.vue +119 -121
  33. package/views/permission/role/index.vue +47 -49
  34. package/views/resource/gallery/index.vue +77 -78
  35. package/LICENSE +0 -201
@@ -1,43 +1,43 @@
1
1
  <template>
2
2
  <PageTableDetail class="page-error-log page-table" :columns="$Data.columns" :endpoints="$Data.endpoints" :table-slot-names="['errorType', 'reportTime', 'firstReportTime', 'source', 'message', 'hitCount', 'deviceType']">
3
3
  <template #toolLeft="scope">
4
- <TInput v-model="$Data.filter.keyword" clearable placeholder="搜索页面/产品/消息/类型" style="width: 220px" @enter="handleFilter(scope.reload)" @clear="handleFilter(scope.reload)">
4
+ <TInput v-model="$Data.filter.keyword" clearable placeholder="搜索页面/产品/消息/类型" style="width: 220px" @enter="$Method.handleFilter(scope.reload)" @clear="$Method.handleFilter(scope.reload)">
5
5
  <template #suffix-icon>
6
6
  <SearchIcon />
7
7
  </template>
8
8
  </TInput>
9
- <TSelect v-model="$Data.filter.errorType" clearable placeholder="错误类型" style="width: 150px" @change="handleFilter(scope.reload)">
9
+ <TSelect v-model="$Data.filter.errorType" clearable placeholder="错误类型" style="width: 150px" @change="$Method.handleFilter(scope.reload)">
10
10
  <TOption label="Vue" value="vue" />
11
11
  <TOption label="Window" value="window" />
12
12
  <TOption label="Promise" value="promise" />
13
13
  <TOption label="Unknown" value="unknown" />
14
14
  </TSelect>
15
- <TSelect v-model="$Data.filter.source" clearable placeholder="来源" style="width: 140px" @change="handleFilter(scope.reload)">
15
+ <TSelect v-model="$Data.filter.source" clearable placeholder="来源" style="width: 140px" @change="$Method.handleFilter(scope.reload)">
16
16
  <TOption label="Admin" value="admin" />
17
17
  </TSelect>
18
- <TInput v-model="$Data.filter.productName" clearable placeholder="产品名称" style="width: 160px" @enter="handleFilter(scope.reload)" @clear="handleFilter(scope.reload)" />
19
- <TInput v-model="$Data.filter.productCode" clearable placeholder="产品代号" style="width: 160px" @enter="handleFilter(scope.reload)" @clear="handleFilter(scope.reload)" />
20
- <TInput v-model="$Data.filter.productVersion" clearable placeholder="产品版本" style="width: 160px" @enter="handleFilter(scope.reload)" @clear="handleFilter(scope.reload)" />
21
- <TSelect v-model="$Data.filter.deviceType" clearable placeholder="设备类型" style="width: 140px" @change="handleFilter(scope.reload)">
18
+ <TInput v-model="$Data.filter.productName" clearable placeholder="产品名称" style="width: 160px" @enter="$Method.handleFilter(scope.reload)" @clear="$Method.handleFilter(scope.reload)" />
19
+ <TInput v-model="$Data.filter.productCode" clearable placeholder="产品代号" style="width: 160px" @enter="$Method.handleFilter(scope.reload)" @clear="$Method.handleFilter(scope.reload)" />
20
+ <TInput v-model="$Data.filter.productVersion" clearable placeholder="产品版本" style="width: 160px" @enter="$Method.handleFilter(scope.reload)" @clear="$Method.handleFilter(scope.reload)" />
21
+ <TSelect v-model="$Data.filter.deviceType" clearable placeholder="设备类型" style="width: 140px" @change="$Method.handleFilter(scope.reload)">
22
22
  <TOption label="桌面端" value="desktop" />
23
23
  <TOption label="移动端" value="mobile" />
24
24
  <TOption label="平板" value="tablet" />
25
25
  <TOption label="电视" value="smarttv" />
26
26
  </TSelect>
27
- <TInput v-model="$Data.filter.browserName" clearable placeholder="浏览器" style="width: 160px" @enter="handleFilter(scope.reload)" @clear="handleFilter(scope.reload)" />
28
- <TInput v-model="$Data.filter.osName" clearable placeholder="操作系统" style="width: 160px" @enter="handleFilter(scope.reload)" @clear="handleFilter(scope.reload)" />
27
+ <TInput v-model="$Data.filter.browserName" clearable placeholder="浏览器" style="width: 160px" @enter="$Method.handleFilter(scope.reload)" @clear="$Method.handleFilter(scope.reload)" />
28
+ <TInput v-model="$Data.filter.osName" clearable placeholder="操作系统" style="width: 160px" @enter="$Method.handleFilter(scope.reload)" @clear="$Method.handleFilter(scope.reload)" />
29
29
  </template>
30
30
 
31
31
  <template #errorType="{ row }">
32
- <TTag shape="round" :theme="getErrorTheme(row.errorType)" variant="light-outline">{{ formatErrorType(row.errorType) }}</TTag>
32
+ <TTag shape="round" :theme="$Method.getErrorTheme(row.errorType)" variant="light-outline">{{ $Method.formatErrorType(row.errorType) }}</TTag>
33
33
  </template>
34
34
 
35
35
  <template #reportTime="{ row }">
36
- {{ formatTime(row.reportTime) }}
36
+ {{ $Method.formatTime(row.reportTime) }}
37
37
  </template>
38
38
 
39
39
  <template #firstReportTime="{ row }">
40
- {{ formatTime(row.firstReportTime) }}
40
+ {{ $Method.formatTime(row.firstReportTime) }}
41
41
  </template>
42
42
 
43
43
  <template #source="{ row }">
@@ -49,7 +49,7 @@
49
49
  </template>
50
50
 
51
51
  <template #deviceType="{ row }">
52
- <TTag shape="round" variant="light-outline">{{ formatDeviceType(row.deviceType) }}</TTag>
52
+ <TTag shape="round" variant="light-outline">{{ $Method.formatDeviceType(row.deviceType) }}</TTag>
53
53
  </template>
54
54
 
55
55
  <template #message="{ row }">
@@ -59,13 +59,13 @@
59
59
  <template #detail="scope">
60
60
  <DetailPanel :data="scope.row" :fields="$Data.columns">
61
61
  <template #errorType="slotScope">
62
- <TTag shape="round" :theme="getErrorTheme(slotScope.value)" variant="light-outline">{{ formatErrorType(slotScope.value) }}</TTag>
62
+ <TTag shape="round" :theme="$Method.getErrorTheme(slotScope.value)" variant="light-outline">{{ $Method.formatErrorType(slotScope.value) }}</TTag>
63
63
  </template>
64
64
  <template #reportTime="slotScope">
65
- {{ formatTime(slotScope.value) }}
65
+ {{ $Method.formatTime(slotScope.value) }}
66
66
  </template>
67
67
  <template #firstReportTime="slotScope">
68
- {{ formatTime(slotScope.value) }}
68
+ {{ $Method.formatTime(slotScope.value) }}
69
69
  </template>
70
70
  <template #source="slotScope">
71
71
  <TTag shape="round" variant="light-outline">{{ slotScope.value || "admin" }}</TTag>
@@ -74,16 +74,16 @@
74
74
  <TTag shape="round" theme="warning" variant="light-outline">{{ slotScope.value || 1 }} 次</TTag>
75
75
  </template>
76
76
  <template #deviceType="slotScope">
77
- <TTag shape="round" variant="light-outline">{{ formatDeviceType(slotScope.value) }}</TTag>
77
+ <TTag shape="round" variant="light-outline">{{ $Method.formatDeviceType(slotScope.value) }}</TTag>
78
78
  </template>
79
79
  <template #detail="slotScope">
80
80
  <div class="detail-actions">
81
- <TButton theme="primary" variant="outline" size="small" @click="handleCopyDetail(scope.row.detail)">复制详情</TButton>
82
- <TButton theme="default" variant="outline" size="small" @click="toggleDetailExpand(scope.row.id)">
83
- {{ isDetailExpanded(scope.row.id) ? "收起详情" : "展开详情" }}
81
+ <TButton theme="primary" variant="outline" size="small" @click="$Method.handleCopyDetail(scope.row.detail)">复制详情</TButton>
82
+ <TButton theme="default" variant="outline" size="small" @click="$Method.toggleDetailExpand(scope.row.id)">
83
+ {{ $Method.isDetailExpanded(scope.row.id) ? "收起详情" : "展开详情" }}
84
84
  </TButton>
85
85
  </div>
86
- <pre class="detail-content" :class="{ expanded: isDetailExpanded(scope.row.id) }">{{ formatDetail(slotScope.value) }}</pre>
86
+ <pre class="detail-content" :class="{ expanded: $Method.isDetailExpanded(scope.row.id) }">{{ $Method.formatDetail(slotScope.value) }}</pre>
87
87
  </template>
88
88
  </DetailPanel>
89
89
  </template>
@@ -169,121 +169,115 @@ const $Data = reactive({
169
169
  detailExpandedId: 0
170
170
  });
171
171
 
172
- function handleFilter(reload) {
173
- reload({ keepSelection: false, resetPage: true });
174
- }
175
-
176
- function isDetailExpanded(id) {
177
- return Number($Data.detailExpandedId) === Number(id || 0);
178
- }
179
-
180
- function toggleDetailExpand(id) {
181
- const nextId = Number(id || 0);
182
-
183
- if (Number($Data.detailExpandedId) === nextId) {
184
- $Data.detailExpandedId = 0;
185
- return;
186
- }
187
-
188
- $Data.detailExpandedId = nextId;
189
- }
190
-
191
- async function handleCopyDetail(value) {
192
- const text = formatDetail(value);
193
- if (text === "-") {
194
- MessagePlugin.warning("暂无可复制的错误详情");
195
- return;
196
- }
197
-
198
- try {
199
- await navigator.clipboard.writeText(text);
200
- MessagePlugin.success("错误详情已复制");
201
- } catch (_error) {
202
- MessagePlugin.error("复制失败,请检查浏览器剪贴板权限");
203
- }
204
- }
205
-
206
- function getErrorTheme(errorType) {
207
- if (errorType === "vue") {
208
- return "danger";
209
- }
172
+ const $Method = {
173
+ handleFilter(reload) {
174
+ reload({ keepSelection: false, resetPage: true });
175
+ },
176
+ isDetailExpanded(id) {
177
+ return Number($Data.detailExpandedId) === Number(id || 0);
178
+ },
179
+ toggleDetailExpand(id) {
180
+ const nextId = Number(id || 0);
210
181
 
211
- if (errorType === "promise") {
212
- return "warning";
213
- }
182
+ if (Number($Data.detailExpandedId) === nextId) {
183
+ $Data.detailExpandedId = 0;
184
+ return;
185
+ }
214
186
 
215
- if (errorType === "window") {
216
- return "primary";
217
- }
187
+ $Data.detailExpandedId = nextId;
188
+ },
189
+ async handleCopyDetail(value) {
190
+ const text = $Method.formatDetail(value);
191
+ if (text === "-") {
192
+ MessagePlugin.warning("暂无可复制的错误详情");
193
+ return;
194
+ }
218
195
 
219
- return "default";
220
- }
196
+ try {
197
+ await navigator.clipboard.writeText(text);
198
+ MessagePlugin.success("错误详情已复制");
199
+ } catch (_error) {
200
+ MessagePlugin.error("复制失败,请检查浏览器剪贴板权限");
201
+ }
202
+ },
203
+ getErrorTheme(errorType) {
204
+ if (errorType === "vue") {
205
+ return "danger";
206
+ }
221
207
 
222
- function formatErrorType(errorType) {
223
- if (errorType === "vue") {
224
- return "Vue";
225
- }
208
+ if (errorType === "promise") {
209
+ return "warning";
210
+ }
226
211
 
227
- if (errorType === "window") {
228
- return "Window";
229
- }
212
+ if (errorType === "window") {
213
+ return "primary";
214
+ }
230
215
 
231
- if (errorType === "promise") {
232
- return "Promise";
233
- }
216
+ return "default";
217
+ },
218
+ formatErrorType(errorType) {
219
+ if (errorType === "vue") {
220
+ return "Vue";
221
+ }
234
222
 
235
- return errorType || "Unknown";
236
- }
223
+ if (errorType === "window") {
224
+ return "Window";
225
+ }
237
226
 
238
- function formatDeviceType(deviceType) {
239
- if (deviceType === "desktop") {
240
- return "桌面端";
241
- }
227
+ if (errorType === "promise") {
228
+ return "Promise";
229
+ }
242
230
 
243
- if (deviceType === "mobile") {
244
- return "移动端";
245
- }
231
+ return errorType || "Unknown";
232
+ },
233
+ formatDeviceType(deviceType) {
234
+ if (deviceType === "desktop") {
235
+ return "桌面端";
236
+ }
246
237
 
247
- if (deviceType === "tablet") {
248
- return "平板";
249
- }
238
+ if (deviceType === "mobile") {
239
+ return "移动端";
240
+ }
250
241
 
251
- if (deviceType === "smarttv") {
252
- return "电视";
253
- }
242
+ if (deviceType === "tablet") {
243
+ return "平板";
244
+ }
254
245
 
255
- return deviceType || "Unknown";
256
- }
246
+ if (deviceType === "smarttv") {
247
+ return "电视";
248
+ }
257
249
 
258
- function formatTime(timestamp) {
259
- const value = Number(timestamp || 0);
250
+ return deviceType || "Unknown";
251
+ },
252
+ formatTime(timestamp) {
253
+ const value = Number(timestamp || 0);
260
254
 
261
- if (!value) {
262
- return "-";
263
- }
255
+ if (!value) {
256
+ return "-";
257
+ }
264
258
 
265
- const date = new Date(value);
259
+ const date = new Date(value);
266
260
 
267
- if (Number.isNaN(date.getTime())) {
268
- return "-";
269
- }
261
+ if (Number.isNaN(date.getTime())) {
262
+ return "-";
263
+ }
270
264
 
271
- const year = date.getFullYear();
272
- const month = String(date.getMonth() + 1).padStart(2, "0");
273
- const day = String(date.getDate()).padStart(2, "0");
274
- const hours = String(date.getHours()).padStart(2, "0");
275
- const minutes = String(date.getMinutes()).padStart(2, "0");
276
- const seconds = String(date.getSeconds()).padStart(2, "0");
277
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
278
- }
265
+ const year = date.getFullYear();
266
+ const month = String(date.getMonth() + 1).padStart(2, "0");
267
+ const day = String(date.getDate()).padStart(2, "0");
268
+ const hours = String(date.getHours()).padStart(2, "0");
269
+ const minutes = String(date.getMinutes()).padStart(2, "0");
270
+ const seconds = String(date.getSeconds()).padStart(2, "0");
271
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
272
+ },
273
+ formatDetail(value) {
274
+ if (!value) {
275
+ return "-";
276
+ }
279
277
 
280
- function formatDetail(value) {
281
- if (!value) {
282
- return "-";
278
+ return String(value);
283
279
  }
284
-
285
- return String(value);
286
- }
280
+ };
287
281
  </script>
288
282
 
289
283
  <style scoped lang="scss">
@@ -6,7 +6,7 @@
6
6
  </template>
7
7
 
8
8
  <template #loginTime="{ row }">
9
- {{ formatTime(row.loginTime) }}
9
+ {{ $Method.formatTime(row.loginTime) }}
10
10
  </template>
11
11
 
12
12
  <template #deviceType="{ row }">
@@ -20,7 +20,7 @@
20
20
  <TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
21
21
  </template>
22
22
  <template #loginTime="slotScope">
23
- {{ formatTime(slotScope.value) }}
23
+ {{ $Method.formatTime(slotScope.value) }}
24
24
  </template>
25
25
  <template #deviceType="slotScope">
26
26
  <TTag shape="round" variant="light-outline">{{ slotScope.value || "desktop" }}</TTag>
@@ -65,17 +65,19 @@ const $Data = reactive({
65
65
  }
66
66
  });
67
67
 
68
- function formatTime(timestamp) {
69
- if (!timestamp) return "-";
70
- const date = new Date(timestamp);
71
- const year = date.getFullYear();
72
- const month = String(date.getMonth() + 1).padStart(2, "0");
73
- const day = String(date.getDate()).padStart(2, "0");
74
- const hours = String(date.getHours()).padStart(2, "0");
75
- const minutes = String(date.getMinutes()).padStart(2, "0");
76
- const seconds = String(date.getSeconds()).padStart(2, "0");
77
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
78
- }
68
+ const $Method = {
69
+ formatTime(timestamp) {
70
+ if (!timestamp) return "-";
71
+ const date = new Date(timestamp);
72
+ const year = date.getFullYear();
73
+ const month = String(date.getMonth() + 1).padStart(2, "0");
74
+ const day = String(date.getDate()).padStart(2, "0");
75
+ const hours = String(date.getHours()).padStart(2, "0");
76
+ const minutes = String(date.getMinutes()).padStart(2, "0");
77
+ const seconds = String(date.getSeconds()).padStart(2, "0");
78
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
79
+ }
80
+ };
79
81
  </script>
80
82
 
81
83
  <style scoped lang="scss">
@@ -1,13 +1,13 @@
1
1
  <template>
2
2
  <PageTableDetail class="page-operate-log page-table" :columns="$Data.columns" :endpoints="$Data.endpoints" :table-slot-names="['result', 'operateTime', 'duration', 'action']">
3
3
  <template #toolLeft="scope">
4
- <TSelect v-model="$Data.filter.module" placeholder="操作模块" clearable style="width: 150px" @change="handleFilter(scope.reload)">
4
+ <TSelect v-model="$Data.filter.module" placeholder="操作模块" clearable style="width: 150px" @change="$Method.handleFilter(scope.reload)">
5
5
  <TOption v-for="item in $Data.moduleOptions" :key="item.value" :label="item.label" :value="item.value" />
6
6
  </TSelect>
7
- <TSelect v-model="$Data.filter.action" placeholder="操作类型" clearable style="width: 150px" @change="handleFilter(scope.reload)">
7
+ <TSelect v-model="$Data.filter.action" placeholder="操作类型" clearable style="width: 150px" @change="$Method.handleFilter(scope.reload)">
8
8
  <TOption v-for="item in $Data.actionOptions" :key="item.value" :label="item.label" :value="item.value" />
9
9
  </TSelect>
10
- <TSelect v-model="$Data.filter.result" placeholder="操作结果" clearable style="width: 120px" @change="handleFilter(scope.reload)">
10
+ <TSelect v-model="$Data.filter.result" placeholder="操作结果" clearable style="width: 120px" @change="$Method.handleFilter(scope.reload)">
11
11
  <TOption label="成功" :value="1" />
12
12
  <TOption label="失败" :value="0" />
13
13
  </TSelect>
@@ -19,7 +19,7 @@
19
19
  </template>
20
20
 
21
21
  <template #operateTime="{ row }">
22
- {{ formatTime(row.operateTime) }}
22
+ {{ $Method.formatTime(row.operateTime) }}
23
23
  </template>
24
24
 
25
25
  <template #duration="{ row }">
@@ -37,16 +37,16 @@
37
37
  <TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
38
38
  </template>
39
39
  <template #operateTime="slotScope">
40
- {{ formatTime(slotScope.value) }}
40
+ {{ $Method.formatTime(slotScope.value) }}
41
41
  </template>
42
42
  <template #duration="slotScope">
43
43
  <TTag shape="round" :theme="slotScope.value > 1000 ? 'warning' : 'default'" variant="light-outline">{{ slotScope.value }}ms</TTag>
44
44
  </template>
45
45
  <template #params="slotScope">
46
- <pre class="json-content">{{ formatJson(slotScope.value) }}</pre>
46
+ <pre class="json-content">{{ $Method.formatJson(slotScope.value) }}</pre>
47
47
  </template>
48
48
  <template #response="slotScope">
49
- <pre class="json-content">{{ formatJson(slotScope.value) }}</pre>
49
+ <pre class="json-content">{{ $Method.formatJson(slotScope.value) }}</pre>
50
50
  </template>
51
51
  </DetailPanel>
52
52
  </template>
@@ -114,31 +114,31 @@ const $Data = reactive({
114
114
  ]
115
115
  });
116
116
 
117
- function handleFilter(reload) {
118
- reload({ keepSelection: false, resetPage: true });
119
- }
120
-
121
- function formatTime(timestamp) {
122
- if (!timestamp) return "-";
123
- const date = new Date(timestamp);
124
- const year = date.getFullYear();
125
- const month = String(date.getMonth() + 1).padStart(2, "0");
126
- const day = String(date.getDate()).padStart(2, "0");
127
- const hours = String(date.getHours()).padStart(2, "0");
128
- const minutes = String(date.getMinutes()).padStart(2, "0");
129
- const seconds = String(date.getSeconds()).padStart(2, "0");
130
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
131
- }
132
-
133
- function formatJson(value) {
134
- if (!value) return "-";
135
- try {
136
- const obj = typeof value === "string" ? JSON.parse(value) : value;
137
- return JSON.stringify(obj, null, 2);
138
- } catch {
139
- return String(value);
117
+ const $Method = {
118
+ handleFilter(reload) {
119
+ reload({ keepSelection: false, resetPage: true });
120
+ },
121
+ formatTime(timestamp) {
122
+ if (!timestamp) return "-";
123
+ const date = new Date(timestamp);
124
+ const year = date.getFullYear();
125
+ const month = String(date.getMonth() + 1).padStart(2, "0");
126
+ const day = String(date.getDate()).padStart(2, "0");
127
+ const hours = String(date.getHours()).padStart(2, "0");
128
+ const minutes = String(date.getMinutes()).padStart(2, "0");
129
+ const seconds = String(date.getSeconds()).padStart(2, "0");
130
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
131
+ },
132
+ formatJson(value) {
133
+ if (!value) return "-";
134
+ try {
135
+ const obj = typeof value === "string" ? JSON.parse(value) : value;
136
+ return JSON.stringify(obj, null, 2);
137
+ } catch {
138
+ return String(value);
139
+ }
140
140
  }
141
- }
141
+ };
142
142
  </script>
143
143
 
144
144
  <style scoped lang="scss">
@@ -20,7 +20,18 @@
20
20
  <h2 class="login-title">欢迎回来</h2>
21
21
  </div>
22
22
 
23
- <TForm :model="$Data.formData" :rules="$Data.formRules" ref="formRef" class="login-form" :show-message="false" label-width="0">
23
+ <TForm
24
+ :model="$Data.formData"
25
+ :rules="$Const.formRules"
26
+ :ref="
27
+ (value) => {
28
+ $From.formRef = value;
29
+ }
30
+ "
31
+ class="login-form"
32
+ :show-message="false"
33
+ label-width="0"
34
+ >
24
35
  <TFormItem prop="account">
25
36
  <TInputAdornment>
26
37
  <template #prepend>
@@ -30,7 +41,7 @@
30
41
  <TOption value="phone" label="手机号" />
31
42
  </TSelect>
32
43
  </template>
33
- <TInput v-model="$Data.formData.account" :placeholder="$Data.formData.loginType === 'username' ? '请输入用户名' : $Data.formData.loginType === 'email' ? '请输入邮箱' : '请输入手机号'" size="large" clearable @enter="apiLogin">
44
+ <TInput v-model="$Data.formData.account" :placeholder="$Data.formData.loginType === 'username' ? '请输入用户名' : $Data.formData.loginType === 'email' ? '请输入邮箱' : '请输入手机号'" size="large" clearable @enter="$Method.apiLogin">
34
45
  <template #prefix-icon>
35
46
  <UserIcon />
36
47
  </template>
@@ -39,7 +50,7 @@
39
50
  </TFormItem>
40
51
 
41
52
  <TFormItem prop="password">
42
- <TInput v-model="$Data.formData.password" type="password" placeholder="密码" size="large" clearable @enter="apiLogin">
53
+ <TInput v-model="$Data.formData.password" type="password" placeholder="密码" size="large" clearable @enter="$Method.apiLogin">
43
54
  <template #prefix-icon>
44
55
  <LockOnIcon />
45
56
  </template>
@@ -51,7 +62,7 @@
51
62
  <a href="#" class="link-text">忘记密码?</a>
52
63
  </div>
53
64
 
54
- <TButton theme="primary" class="login-btn" size="large" block :loading="$Data.loading" @click="apiLogin">登录</TButton>
65
+ <TButton theme="primary" class="login-btn" size="large" block :loading="$Data.loading" @click="$Method.apiLogin">登录</TButton>
55
66
  </TForm>
56
67
 
57
68
  <div class="login-footer">
@@ -63,7 +74,7 @@
63
74
  </template>
64
75
 
65
76
  <script setup>
66
- import { reactive, ref } from "vue";
77
+ import { reactive } from "vue";
67
78
  import { useRouter } from "vue-router";
68
79
  import { Form as TForm, FormItem as TFormItem, Input as TInput, Button as TButton, Checkbox as TCheckbox, InputAdornment as TInputAdornment, Select as TSelect, Option as TOption, MessagePlugin } from "tdesign-vue-next";
69
80
  import { LockOnIcon, UserIcon } from "tdesign-icons-vue-next";
@@ -74,16 +85,21 @@ import { $Store } from "@/plugins/store.js";
74
85
 
75
86
  const router = useRouter();
76
87
 
77
- const formRef = ref(null);
88
+ const $Const = {
89
+ formRules: {
90
+ account: [{ required: true, message: "请输入账号", trigger: "blur" }],
91
+ password: [{ required: true, message: "请输入密码", trigger: "blur" }]
92
+ }
93
+ };
94
+
95
+ const $From = {
96
+ formRef: null
97
+ };
78
98
 
79
99
  // 数据定义
80
100
  const $Data = reactive({
81
101
  loading: false,
82
102
  rememberMe: false,
83
- formRules: {
84
- account: [{ required: true, message: "请输入账号", trigger: "blur" }],
85
- password: [{ required: true, message: "请输入密码", trigger: "blur" }]
86
- },
87
103
  formData: {
88
104
  loginType: "username",
89
105
  account: "",
@@ -91,36 +107,38 @@ const $Data = reactive({
91
107
  }
92
108
  });
93
109
 
94
- async function apiLogin() {
95
- try {
96
- if (formRef.value === null) {
97
- MessagePlugin.error("表单未就绪");
98
- return;
99
- }
110
+ const $Method = {
111
+ async apiLogin() {
112
+ try {
113
+ if ($From.formRef === null) {
114
+ MessagePlugin.error("表单未就绪");
115
+ return;
116
+ }
100
117
 
101
- await formRef.value.validate();
118
+ await $From.formRef.validate();
102
119
 
103
- $Data.loading = true;
120
+ $Data.loading = true;
104
121
 
105
- const hashedPassword = await hashPassword($Data.formData.password);
122
+ const hashedPassword = await hashPassword($Data.formData.password);
106
123
 
107
- const res = await $Http("/core/auth/login", {
108
- loginType: $Data.formData.loginType,
109
- account: $Data.formData.account,
110
- password: hashedPassword
111
- });
124
+ const res = await $Http("/core/auth/login", {
125
+ loginType: $Data.formData.loginType,
126
+ account: $Data.formData.account,
127
+ password: hashedPassword
128
+ });
112
129
 
113
- $Store.local.set($Config.tokenName, res.data.token);
130
+ $Store.local.set($Config.tokenName, res.data.token);
114
131
 
115
- MessagePlugin.success(res.msg || "登录成功");
132
+ MessagePlugin.success(res.msg || "登录成功");
116
133
 
117
- await router.push($Config.homePath);
118
- } catch (error) {
119
- MessagePlugin.error(error.msg || error.message || "登录失败");
120
- } finally {
121
- $Data.loading = false;
134
+ await router.push($Config.homePath);
135
+ } catch (error) {
136
+ MessagePlugin.error(error.msg || error.message || "登录失败");
137
+ } finally {
138
+ $Data.loading = false;
139
+ }
122
140
  }
123
- }
141
+ };
124
142
  </script>
125
143
 
126
144
  <style scoped lang="scss">
@@ -38,7 +38,7 @@ import {
38
38
  MessagePlugin
39
39
  } from "tdesign-vue-next";
40
40
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
41
- import { $Http } from "@/plugins/http";
41
+ import { $Http } from "@/plugins/http.js";
42
42
  import { fieldClear } from "befly-admin-ui/utils/fieldClear";
43
43
  import { hashPassword } from "befly-admin-ui/utils/hashPassword";
44
44