@befly-addon/admin 1.1.35 → 1.2.0

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 (46) hide show
  1. package/apis/admin/cacheRefresh.ts +2 -2
  2. package/apis/menu/all.ts +8 -9
  3. package/apis/menu/list.ts +1 -2
  4. package/apis/role/apiSave.ts +3 -3
  5. package/apis/role/apis.ts +3 -3
  6. package/apis/role/menuSave.ts +2 -2
  7. package/apis/role/menus.ts +3 -3
  8. package/package.json +21 -21
  9. package/plugins/email.ts +3 -8
  10. package/tables/api.json +1 -20
  11. package/tables/menu.json +6 -11
  12. package/tables/role.json +4 -4
  13. package/views/403_1/index.vue +0 -75
  14. package/views/config/dict/components/edit.vue +0 -109
  15. package/views/config/dict/index.vue +0 -266
  16. package/views/config/dictType/components/edit.vue +0 -100
  17. package/views/config/dictType/index.vue +0 -244
  18. package/views/config/index.vue +0 -12
  19. package/views/config/system/components/edit.vue +0 -171
  20. package/views/config/system/index.vue +0 -286
  21. package/views/index/components/addonList.vue +0 -132
  22. package/views/index/components/environmentInfo.vue +0 -100
  23. package/views/index/components/operationLogs.vue +0 -112
  24. package/views/index/components/performanceMetrics.vue +0 -145
  25. package/views/index/components/quickActions.vue +0 -30
  26. package/views/index/components/serviceStatus.vue +0 -192
  27. package/views/index/components/systemNotifications.vue +0 -137
  28. package/views/index/components/systemOverview.vue +0 -190
  29. package/views/index/components/systemResources.vue +0 -111
  30. package/views/index/components/userInfo.vue +0 -204
  31. package/views/index/index.vue +0 -74
  32. package/views/log/email/index.vue +0 -292
  33. package/views/log/index.vue +0 -12
  34. package/views/log/login/index.vue +0 -187
  35. package/views/log/operate/index.vue +0 -249
  36. package/views/login_1/index.vue +0 -415
  37. package/views/people/admin/components/edit.vue +0 -168
  38. package/views/people/admin/index.vue +0 -240
  39. package/views/people/index.vue +0 -12
  40. package/views/permission/api/index.vue +0 -149
  41. package/views/permission/index.vue +0 -12
  42. package/views/permission/menu/index.vue +0 -128
  43. package/views/permission/role/components/api.vue +0 -261
  44. package/views/permission/role/components/edit.vue +0 -142
  45. package/views/permission/role/components/menu.vue +0 -116
  46. package/views/permission/role/index.vue +0 -263
@@ -1,292 +0,0 @@
1
- <template>
2
- <div class="page-email page-table">
3
- <div class="main-tool">
4
- <div class="left">
5
- <TButton theme="primary" @click="$Method.openSendDialog">
6
- <template #icon>
7
- <ILucideSend />
8
- </template>
9
- 发送邮件
10
- </TButton>
11
- <TButton variant="outline" @click="$Method.onVerify">
12
- <template #icon>
13
- <ILucideCheckCircle />
14
- </template>
15
- 验证配置
16
- </TButton>
17
- </div>
18
- <div class="right">
19
- <TButton shape="circle" @click="$Method.handleRefresh">
20
- <template #icon>
21
- <ILucideRotateCw />
22
- </template>
23
- </TButton>
24
- </div>
25
- </div>
26
-
27
- <div class="main-content">
28
- <div class="main-table">
29
- <TTable :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" :active-row-keys="$Data.activeRowKeys" row-key="id" height="100%" active-row-type="single" @active-change="$Method.onActiveChange">
30
- <template #sendResult="{ row }">
31
- <TTag v-if="row.sendResult === 1" shape="round" theme="success" variant="light-outline">成功</TTag>
32
- <TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
33
- </template>
34
- <template #sendTime="{ row }">
35
- {{ $Method.formatTime(row.sendTime) }}
36
- </template>
37
- </TTable>
38
- </div>
39
-
40
- <div class="main-detail">
41
- <DetailPanel :data="$Data.currentRow" :fields="$Data.detailFields">
42
- <template #sendResult="{ value }">
43
- <TTag v-if="value === 1" shape="round" theme="success" variant="light-outline">成功</TTag>
44
- <TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
45
- </template>
46
- <template #sendTime="{ value }">
47
- {{ $Method.formatTime(value) }}
48
- </template>
49
- <template #content="{ value }">
50
- <div class="email-content" v-html="value"></div>
51
- </template>
52
- </DetailPanel>
53
- </div>
54
- </div>
55
-
56
- <div class="main-page">
57
- <TPagination :current-page="$Data.pagerConfig.currentPage" :page-size="$Data.pagerConfig.limit" :total="$Data.pagerConfig.total" @current-change="$Method.onPageChange" @page-size-change="$Method.handleSizeChange" />
58
- </div>
59
-
60
- <!-- 发送邮件弹框 -->
61
- <TDialog v-model:visible="$Data.sendDialogVisible" header="发送邮件" :footer="false" width="600px">
62
- <TForm ref="sendFormRef" :data="$Data.sendForm" :rules="$Data.sendRules" label-width="80px">
63
- <TFormItem label="收件人" name="to">
64
- <TInput v-model="$Data.sendForm.to" placeholder="请输入收件人邮箱" />
65
- </TFormItem>
66
- <TFormItem label="抄送" name="cc">
67
- <TInput v-model="$Data.sendForm.cc" placeholder="多个邮箱用逗号分隔(可选)" />
68
- </TFormItem>
69
- <TFormItem label="主题" name="subject">
70
- <TInput v-model="$Data.sendForm.subject" placeholder="请输入邮件主题" />
71
- </TFormItem>
72
- <TFormItem label="内容" name="content">
73
- <TTextarea v-model="$Data.sendForm.content" placeholder="请输入邮件内容(支持HTML)" :autosize="{ minRows: 6, maxRows: 12 }" />
74
- </TFormItem>
75
- <TFormItem>
76
- <TSpace>
77
- <TButton theme="primary" :loading="$Data.sending" @click="$Method.onSend">发送</TButton>
78
- <TButton variant="outline" @click="$Data.sendDialogVisible = false">取消</TButton>
79
- </TSpace>
80
- </TFormItem>
81
- </TForm>
82
- </TDialog>
83
- </div>
84
- </template>
85
-
86
- <script setup>
87
- import { Button as TButton, Table as TTable, Tag as TTag, Pagination as TPagination, Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, Textarea as TTextarea, Space as TSpace, MessagePlugin } from "tdesign-vue-next";
88
- import ILucideRotateCw from "~icons/lucide/rotate-cw";
89
- import ILucideSend from "~icons/lucide/send";
90
- import ILucideCheckCircle from "~icons/lucide/check-circle";
91
- import DetailPanel from "@/components/DetailPanel.vue";
92
- import { $Http } from "@/plugins/http";
93
- import { withDefaultColumns } from "befly-vite/utils/withDefaultColumns";
94
-
95
- definePage({
96
- meta: {
97
- title: "邮件日志",
98
- order: 2
99
- }
100
- });
101
-
102
- const sendFormRef = $ref(null);
103
-
104
- // 响应式数据
105
- const $Data = $ref({
106
- tableData: [],
107
- loading: false,
108
- columns: withDefaultColumns([
109
- { colKey: "username", title: "发送人", fixed: "left" },
110
- { colKey: "id", title: "序号" },
111
- { colKey: "toEmail", title: "收件人" },
112
- { colKey: "subject", title: "主题" },
113
- { colKey: "sendTime", title: "发送时间" },
114
- { colKey: "sendResult", title: "发送结果" }
115
- ]),
116
- detailFields: [
117
- { colKey: "username", title: "发送人账号" },
118
- { colKey: "nickname", title: "发送人昵称" },
119
- { colKey: "toEmail", title: "收件人" },
120
- { colKey: "ccEmail", title: "抄送" },
121
- { colKey: "bccEmail", title: "密送" },
122
- { colKey: "subject", title: "主题" },
123
- { colKey: "content", title: "内容" },
124
- { colKey: "sendTime", title: "发送时间" },
125
- { colKey: "sendResult", title: "发送结果" },
126
- { colKey: "messageId", title: "消息ID" },
127
- { colKey: "failReason", title: "失败原因" }
128
- ],
129
- pagerConfig: {
130
- currentPage: 1,
131
- limit: 30,
132
- total: 0
133
- },
134
- currentRow: null,
135
- activeRowKeys: [],
136
- sendDialogVisible: false,
137
- sending: false,
138
- sendForm: {
139
- to: "",
140
- cc: "",
141
- subject: "",
142
- content: ""
143
- },
144
- sendRules: {
145
- to: [{ required: true, message: "请输入收件人邮箱", trigger: "blur" }],
146
- subject: [{ required: true, message: "请输入邮件主题", trigger: "blur" }],
147
- content: [{ required: true, message: "请输入邮件内容", trigger: "blur" }]
148
- }
149
- });
150
-
151
- // 方法
152
- const $Method = {
153
- async initData() {
154
- await $Method.apiEmailLogList();
155
- },
156
-
157
- // 加载邮件日志列表
158
- async apiEmailLogList() {
159
- $Data.loading = true;
160
- try {
161
- const res = await $Http("/addon/admin/email/logList", {
162
- page: $Data.pagerConfig.currentPage,
163
- limit: $Data.pagerConfig.limit
164
- });
165
- $Data.tableData = res.data.lists || [];
166
- $Data.pagerConfig.total = res.data.total || 0;
167
-
168
- if ($Data.tableData.length > 0) {
169
- $Data.currentRow = $Data.tableData[0];
170
- $Data.activeRowKeys = [$Data.tableData[0].id];
171
- } else {
172
- $Data.currentRow = null;
173
- $Data.activeRowKeys = [];
174
- }
175
- } catch (error) {
176
- MessagePlugin.error("加载数据失败");
177
- } finally {
178
- $Data.loading = false;
179
- }
180
- },
181
-
182
- // 打开发送弹框
183
- openSendDialog() {
184
- $Data.sendForm = {
185
- to: "",
186
- cc: "",
187
- subject: "",
188
- content: ""
189
- };
190
- $Data.sendDialogVisible = true;
191
- },
192
-
193
- // 发送邮件
194
- async onSend() {
195
- const valid = await sendFormRef?.validate();
196
- if (valid !== true) return;
197
-
198
- $Data.sending = true;
199
- try {
200
- const res = await $Http("/addon/admin/email/send", {
201
- to: $Data.sendForm.to,
202
- subject: $Data.sendForm.subject,
203
- content: $Data.sendForm.content,
204
- cc: $Data.sendForm.cc || undefined,
205
- isHtml: true
206
- });
207
-
208
- if (res.code === 0) {
209
- MessagePlugin.success("发送成功");
210
- $Data.sendDialogVisible = false;
211
- $Method.apiEmailLogList();
212
- } else {
213
- MessagePlugin.error(res.msg || "发送失败");
214
- }
215
- } catch (error) {
216
- MessagePlugin.error("发送失败");
217
- } finally {
218
- $Data.sending = false;
219
- }
220
- },
221
-
222
- // 验证配置
223
- async onVerify() {
224
- try {
225
- const res = await $Http("/addon/admin/email/verify");
226
- if (res.code === 0) {
227
- MessagePlugin.success("邮件服务配置正常");
228
- } else {
229
- MessagePlugin.error(res.msg || "配置异常");
230
- }
231
- } catch (error) {
232
- MessagePlugin.error("验证失败");
233
- }
234
- },
235
-
236
- // 刷新
237
- handleRefresh() {
238
- $Method.apiEmailLogList();
239
- },
240
-
241
- // 分页改变
242
- onPageChange(currentPage) {
243
- $Data.pagerConfig.currentPage = currentPage;
244
- $Method.apiEmailLogList();
245
- },
246
-
247
- // 每页条数改变
248
- handleSizeChange(pageSize) {
249
- $Data.pagerConfig.limit = pageSize;
250
- $Data.pagerConfig.currentPage = 1;
251
- $Method.apiEmailLogList();
252
- },
253
-
254
- // 高亮行变化
255
- onActiveChange(value, context) {
256
- if (value.length === 0 && $Data.activeRowKeys.length > 0) {
257
- return;
258
- }
259
- $Data.activeRowKeys = value;
260
- if (context.activeRowList && context.activeRowList.length > 0) {
261
- $Data.currentRow = context.activeRowList[0].row;
262
- }
263
- },
264
-
265
- // 格式化时间
266
- formatTime(timestamp) {
267
- if (!timestamp) return "-";
268
- const date = new Date(timestamp);
269
- const year = date.getFullYear();
270
- const month = String(date.getMonth() + 1).padStart(2, "0");
271
- const day = String(date.getDate()).padStart(2, "0");
272
- const hours = String(date.getHours()).padStart(2, "0");
273
- const minutes = String(date.getMinutes()).padStart(2, "0");
274
- const seconds = String(date.getSeconds()).padStart(2, "0");
275
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
276
- }
277
- };
278
-
279
- $Method.initData();
280
- </script>
281
-
282
- <style scoped lang="scss">
283
- .email-content {
284
- max-height: 300px;
285
- overflow-y: auto;
286
- padding: 8px;
287
- background: #f5f5f5;
288
- border-radius: 4px;
289
- font-size: 13px;
290
- line-height: 1.6;
291
- }
292
- </style>
@@ -1,12 +0,0 @@
1
- <template>
2
- <RouterView />
3
- </template>
4
-
5
- <script setup>
6
- definePage({
7
- meta: {
8
- title: "日志管理",
9
- order: 40
10
- }
11
- });
12
- </script>
@@ -1,187 +0,0 @@
1
- <template>
2
- <div class="page-login-log page-table">
3
- <div class="main-tool">
4
- <div class="left"></div>
5
- <div class="right">
6
- <TButton shape="circle" @click="$Method.handleRefresh">
7
- <template #icon>
8
- <ILucideRotateCw />
9
- </template>
10
- </TButton>
11
- </div>
12
- </div>
13
-
14
- <div class="main-content">
15
- <div class="main-table">
16
- <TTable :data="$Data.tableData" :columns="$Data.columns" :loading="$Data.loading" :active-row-keys="$Data.activeRowKeys" row-key="id" height="100%" active-row-type="single" @active-change="$Method.onActiveChange">
17
- <template #loginResult="{ row }">
18
- <TTag v-if="row.loginResult === 1" shape="round" theme="success" variant="light-outline">成功</TTag>
19
- <TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
20
- </template>
21
- <template #loginTime="{ row }">
22
- {{ $Method.formatTime(row.loginTime) }}
23
- </template>
24
- <template #deviceType="{ row }">
25
- <TTag shape="round" variant="light-outline">{{ row.deviceType || "desktop" }}</TTag>
26
- </template>
27
- </TTable>
28
- </div>
29
-
30
- <div class="main-detail">
31
- <DetailPanel :data="$Data.currentRow" :fields="$Data.detailFields">
32
- <template #loginResult="{ value }">
33
- <TTag v-if="value === 1" shape="round" theme="success" variant="light-outline">成功</TTag>
34
- <TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
35
- </template>
36
- <template #loginTime="{ value }">
37
- {{ $Method.formatTime(value) }}
38
- </template>
39
- <template #deviceType="{ value }">
40
- <TTag shape="round" variant="light-outline">{{ value || "desktop" }}</TTag>
41
- </template>
42
- </DetailPanel>
43
- </div>
44
- </div>
45
-
46
- <div class="main-page">
47
- <TPagination :current-page="$Data.pagerConfig.currentPage" :page-size="$Data.pagerConfig.limit" :total="$Data.pagerConfig.total" @current-change="$Method.onPageChange" @page-size-change="$Method.handleSizeChange" />
48
- </div>
49
- </div>
50
- </template>
51
-
52
- <script setup>
53
- import { Button as TButton, Table as TTable, Tag as TTag, Pagination as TPagination, MessagePlugin } from "tdesign-vue-next";
54
- import ILucideRotateCw from "~icons/lucide/rotate-cw";
55
- import DetailPanel from "@/components/DetailPanel.vue";
56
- import { $Http } from "@/plugins/http";
57
- import { withDefaultColumns } from "befly-vite/utils/withDefaultColumns";
58
-
59
- definePage({
60
- meta: {
61
- title: "登录日志",
62
- order: 1
63
- }
64
- });
65
-
66
- // 响应式数据
67
- const $Data = $ref({
68
- tableData: [],
69
- loading: false,
70
- columns: withDefaultColumns([
71
- { colKey: "username", title: "用户名", fixed: "left" },
72
- { colKey: "id", title: "序号" },
73
- { colKey: "ip", title: "登录IP" },
74
- { colKey: "browserName", title: "浏览器" },
75
- { colKey: "osName", title: "操作系统" },
76
- { colKey: "deviceType", title: "设备类型" },
77
- { colKey: "loginTime", title: "登录时间" },
78
- { colKey: "loginResult", title: "登录结果" }
79
- ]),
80
- // 详情面板显示更多字段
81
- detailFields: [
82
- { colKey: "username", title: "用户名" },
83
- { colKey: "nickname", title: "昵称" },
84
- { colKey: "ip", title: "登录IP" },
85
- { colKey: "browserName", title: "浏览器" },
86
- { colKey: "browserVersion", title: "浏览器版本" },
87
- { colKey: "osName", title: "操作系统" },
88
- { colKey: "osVersion", title: "系统版本" },
89
- { colKey: "deviceType", title: "设备类型" },
90
- { colKey: "deviceVendor", title: "设备厂商" },
91
- { colKey: "deviceModel", title: "设备型号" },
92
- { colKey: "engineName", title: "渲染引擎" },
93
- { colKey: "cpuArchitecture", title: "CPU架构" },
94
- { colKey: "loginTime", title: "登录时间" },
95
- { colKey: "loginResult", title: "登录结果" },
96
- { colKey: "failReason", title: "失败原因" }
97
- ],
98
- pagerConfig: {
99
- currentPage: 1,
100
- limit: 30,
101
- total: 0
102
- },
103
- currentRow: null,
104
- activeRowKeys: []
105
- });
106
-
107
- // 方法
108
- const $Method = {
109
- async initData() {
110
- await $Method.apiLoginLogList();
111
- },
112
-
113
- // 加载登录日志列表
114
- async apiLoginLogList() {
115
- $Data.loading = true;
116
- try {
117
- const res = await $Http("/addon/admin/loginLog/list", {
118
- page: $Data.pagerConfig.currentPage,
119
- limit: $Data.pagerConfig.limit
120
- });
121
- $Data.tableData = res.data.lists || [];
122
- $Data.pagerConfig.total = res.data.total || 0;
123
-
124
- // 自动高亮第一行
125
- if ($Data.tableData.length > 0) {
126
- $Data.currentRow = $Data.tableData[0];
127
- $Data.activeRowKeys = [$Data.tableData[0].id];
128
- } else {
129
- $Data.currentRow = null;
130
- $Data.activeRowKeys = [];
131
- }
132
- } catch (error) {
133
- MessagePlugin.error("加载数据失败");
134
- } finally {
135
- $Data.loading = false;
136
- }
137
- },
138
-
139
- // 刷新
140
- handleRefresh() {
141
- $Method.apiLoginLogList();
142
- },
143
-
144
- // 分页改变
145
- onPageChange(currentPage) {
146
- $Data.pagerConfig.currentPage = currentPage;
147
- $Method.apiLoginLogList();
148
- },
149
-
150
- // 每页条数改变
151
- handleSizeChange(pageSize) {
152
- $Data.pagerConfig.limit = pageSize;
153
- $Data.pagerConfig.currentPage = 1;
154
- $Method.apiLoginLogList();
155
- },
156
-
157
- // 高亮行变化
158
- onActiveChange(value, context) {
159
- if (value.length === 0 && $Data.activeRowKeys.length > 0) {
160
- return;
161
- }
162
- $Data.activeRowKeys = value;
163
- if (context.activeRowList && context.activeRowList.length > 0) {
164
- $Data.currentRow = context.activeRowList[0].row;
165
- }
166
- },
167
-
168
- // 格式化时间
169
- formatTime(timestamp) {
170
- if (!timestamp) return "-";
171
- const date = new Date(timestamp);
172
- const year = date.getFullYear();
173
- const month = String(date.getMonth() + 1).padStart(2, "0");
174
- const day = String(date.getDate()).padStart(2, "0");
175
- const hours = String(date.getHours()).padStart(2, "0");
176
- const minutes = String(date.getMinutes()).padStart(2, "0");
177
- const seconds = String(date.getSeconds()).padStart(2, "0");
178
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
179
- }
180
- };
181
-
182
- $Method.initData();
183
- </script>
184
-
185
- <style scoped lang="scss">
186
- // 样式继承自全局 page-table
187
- </style>