@befly-addon/admin 1.8.2 → 1.8.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.
- package/adminViews/403_1/index.vue +9 -10
- package/adminViews/config/dict/components/edit.vue +39 -36
- package/adminViews/config/dict/index.vue +127 -206
- package/adminViews/config/dictType/components/edit.vue +38 -36
- package/adminViews/config/dictType/index.vue +105 -197
- package/adminViews/config/system/components/edit.vue +75 -70
- package/adminViews/config/system/index.vue +134 -235
- package/adminViews/index/components/userInfo.vue +67 -77
- package/adminViews/log/email/index.vue +154 -230
- package/adminViews/log/login/index.vue +66 -157
- package/adminViews/log/operate/index.vue +110 -196
- package/adminViews/login_1/index.vue +29 -39
- package/adminViews/people/admin/components/edit.vue +61 -70
- package/adminViews/people/admin/index.vue +88 -204
- package/adminViews/permission/api/index.vue +52 -62
- package/adminViews/permission/menu/index.vue +43 -53
- package/adminViews/permission/role/components/api.vue +168 -169
- package/adminViews/permission/role/components/edit.vue +43 -45
- package/adminViews/permission/role/components/menu.vue +143 -151
- package/adminViews/permission/role/index.vue +129 -224
- package/adminViews/tsconfig.json +14 -0
- package/package.json +3 -3
|
@@ -1,130 +1,109 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
</
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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>
|
|
2
|
+
<PagedTableDetail class="page-email page-table" :columns="$Data.columns" :endpoints="$Data.endpoints" :table-slot-names="['sendResult', 'sendTime']">
|
|
3
|
+
<template #toolLeft>
|
|
4
|
+
<TButton theme="primary" @click="openSendDialog">
|
|
5
|
+
<template #icon>
|
|
6
|
+
<ILucideSend />
|
|
7
|
+
</template>
|
|
8
|
+
发送邮件
|
|
9
|
+
</TButton>
|
|
10
|
+
<TButton variant="outline" @click="onVerify">
|
|
11
|
+
<template #icon>
|
|
12
|
+
<ILucideCheckCircle />
|
|
13
|
+
</template>
|
|
14
|
+
验证配置
|
|
15
|
+
</TButton>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<template #toolRight="scope">
|
|
19
|
+
<TButton shape="circle" @click="onReload(scope.reload)">
|
|
20
|
+
<template #icon>
|
|
21
|
+
<ILucideRotateCw />
|
|
22
|
+
</template>
|
|
23
|
+
</TButton>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<template #sendResult="{ row }">
|
|
27
|
+
<TTag v-if="row.sendResult === 1" shape="round" theme="success" variant="light-outline">成功</TTag>
|
|
28
|
+
<TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<template #sendTime="{ row }">
|
|
32
|
+
{{ formatTime(row.sendTime) }}
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<template #detail="scope">
|
|
36
|
+
<DetailPanel :data="scope.row" :fields="$Data.columns">
|
|
37
|
+
<template #sendResult="slotScope">
|
|
38
|
+
<TTag v-if="slotScope.value === 1" shape="round" theme="success" variant="light-outline">成功</TTag>
|
|
39
|
+
<TTag v-else shape="round" theme="danger" variant="light-outline">失败</TTag>
|
|
40
|
+
</template>
|
|
41
|
+
<template #sendTime="slotScope">
|
|
42
|
+
{{ formatTime(slotScope.value) }}
|
|
43
|
+
</template>
|
|
44
|
+
<template #content="slotScope">
|
|
45
|
+
<div class="email-content" v-html="slotScope.value"></div>
|
|
46
|
+
</template>
|
|
47
|
+
</DetailPanel>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<template #dialogs="scope">
|
|
51
|
+
<PageDialog v-model="$Data.sendDialogVisible" title="发送邮件" :confirm-loading="$Data.sending" @confirm="(context) => onSend(scope.reload, context)" @cancel="onCancelSend" @close="onCancelSend">
|
|
52
|
+
<TForm :ref="(el) => ($From.sendForm = el)" :data="$Data.sendForm" :rules="$Data.sendRules" label-width="80px">
|
|
53
|
+
<TFormItem label="收件人" name="to">
|
|
54
|
+
<TInput v-model="$Data.sendForm.to" placeholder="请输入收件人邮箱" />
|
|
55
|
+
</TFormItem>
|
|
56
|
+
<TFormItem label="抄送" name="cc">
|
|
57
|
+
<TInput v-model="$Data.sendForm.cc" placeholder="多个邮箱用逗号分隔(可选)" />
|
|
58
|
+
</TFormItem>
|
|
59
|
+
<TFormItem label="主题" name="subject">
|
|
60
|
+
<TInput v-model="$Data.sendForm.subject" placeholder="请输入邮件主题" />
|
|
61
|
+
</TFormItem>
|
|
62
|
+
<TFormItem label="内容" name="content">
|
|
63
|
+
<TTextarea v-model="$Data.sendForm.content" placeholder="请输入邮件内容(支持HTML)" :autosize="{ minRows: 6, maxRows: 12 }" />
|
|
64
|
+
</TFormItem>
|
|
65
|
+
</TForm>
|
|
66
|
+
</PageDialog>
|
|
67
|
+
</template>
|
|
68
|
+
</PagedTableDetail>
|
|
84
69
|
</template>
|
|
85
70
|
|
|
86
71
|
<script setup lang="ts">
|
|
87
|
-
import { Button as TButton,
|
|
72
|
+
import { Button as TButton, Form as TForm, FormItem as TFormItem, Input as TInput, MessagePlugin, Space as TSpace, Tag as TTag, Textarea as TTextarea } from "tdesign-vue-next";
|
|
88
73
|
import ILucideRotateCw from "~icons/lucide/rotate-cw";
|
|
89
74
|
import ILucideSend from "~icons/lucide/send";
|
|
90
75
|
import ILucideCheckCircle from "~icons/lucide/check-circle";
|
|
91
|
-
import
|
|
76
|
+
import PageDialog from "@/components/pageDialog.vue";
|
|
77
|
+
import DetailPanel from "@/components/detailPanel.vue";
|
|
92
78
|
import { $Http } from "@/plugins/http";
|
|
79
|
+
import PagedTableDetail from "@/components/pagedTableDetail.vue";
|
|
93
80
|
import { withDefaultColumns } from "befly-shared/utils/withDefaultColumns";
|
|
94
81
|
|
|
95
|
-
const
|
|
82
|
+
const $From = $shallowRef({
|
|
83
|
+
sendForm: null
|
|
84
|
+
});
|
|
96
85
|
|
|
97
86
|
// 响应式数据
|
|
98
87
|
const $Data = $ref({
|
|
99
|
-
tableData: [],
|
|
100
|
-
loading: false,
|
|
101
88
|
columns: withDefaultColumns([
|
|
102
89
|
{ colKey: "username", title: "发送人", fixed: "left" },
|
|
103
90
|
{ colKey: "toEmail", title: "收件人" },
|
|
104
91
|
{ colKey: "subject", title: "主题" },
|
|
105
92
|
{ colKey: "sendTime", title: "发送时间" },
|
|
106
|
-
{ colKey: "sendResult", title: "发送结果" }
|
|
107
|
-
]),
|
|
108
|
-
detailFields: [
|
|
109
|
-
{ colKey: "username", title: "发送人账号" },
|
|
110
|
-
{ colKey: "nickname", title: "发送人昵称" },
|
|
111
|
-
{ colKey: "toEmail", title: "收件人" },
|
|
112
|
-
{ colKey: "ccEmail", title: "抄送" },
|
|
113
|
-
{ colKey: "bccEmail", title: "密送" },
|
|
114
|
-
{ colKey: "subject", title: "主题" },
|
|
115
|
-
{ colKey: "content", title: "内容" },
|
|
116
|
-
{ colKey: "sendTime", title: "发送时间" },
|
|
117
93
|
{ colKey: "sendResult", title: "发送结果" },
|
|
118
|
-
{ colKey: "
|
|
119
|
-
{ colKey: "
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
94
|
+
{ colKey: "nickname", title: "发送人昵称", detail: true },
|
|
95
|
+
{ colKey: "ccEmail", title: "抄送", detail: true },
|
|
96
|
+
{ colKey: "bccEmail", title: "密送", detail: true },
|
|
97
|
+
{ colKey: "content", title: "内容", detail: true },
|
|
98
|
+
{ colKey: "messageId", title: "消息ID", detail: true },
|
|
99
|
+
{ colKey: "failReason", title: "失败原因", detail: true }
|
|
100
|
+
]),
|
|
101
|
+
endpoints: {
|
|
102
|
+
list: {
|
|
103
|
+
path: "/addon/admin/email/logList",
|
|
104
|
+
dropValues: [""]
|
|
105
|
+
}
|
|
125
106
|
},
|
|
126
|
-
currentRow: null,
|
|
127
|
-
activeRowKeys: [],
|
|
128
107
|
sendDialogVisible: false,
|
|
129
108
|
sending: false,
|
|
130
109
|
sendForm: {
|
|
@@ -140,141 +119,86 @@ const $Data = $ref({
|
|
|
140
119
|
}
|
|
141
120
|
});
|
|
142
121
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
await $Method.apiEmailLogList();
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
// 加载邮件日志列表
|
|
150
|
-
async apiEmailLogList() {
|
|
151
|
-
$Data.loading = true;
|
|
152
|
-
try {
|
|
153
|
-
const res = await $Http.post(
|
|
154
|
-
"/addon/admin/email/logList",
|
|
155
|
-
{
|
|
156
|
-
page: $Data.pagerConfig.currentPage,
|
|
157
|
-
limit: $Data.pagerConfig.limit
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
dropValues: [""]
|
|
161
|
-
}
|
|
162
|
-
);
|
|
163
|
-
$Data.tableData = res.data.lists || [];
|
|
164
|
-
$Data.pagerConfig.total = res.data.total || 0;
|
|
165
|
-
|
|
166
|
-
if ($Data.tableData.length > 0) {
|
|
167
|
-
$Data.currentRow = $Data.tableData[0];
|
|
168
|
-
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
169
|
-
} else {
|
|
170
|
-
$Data.currentRow = null;
|
|
171
|
-
$Data.activeRowKeys = [];
|
|
172
|
-
}
|
|
173
|
-
} catch (error) {
|
|
174
|
-
MessagePlugin.error("加载数据失败");
|
|
175
|
-
} finally {
|
|
176
|
-
$Data.loading = false;
|
|
177
|
-
}
|
|
178
|
-
},
|
|
122
|
+
function onReload(reload: (options: { keepSelection?: boolean }) => void): void {
|
|
123
|
+
reload({ keepSelection: true });
|
|
124
|
+
}
|
|
179
125
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
to: "",
|
|
184
|
-
cc: "",
|
|
185
|
-
subject: "",
|
|
186
|
-
content: ""
|
|
187
|
-
};
|
|
188
|
-
$Data.sendDialogVisible = true;
|
|
189
|
-
},
|
|
126
|
+
function onCancelSend(): void {
|
|
127
|
+
$Data.sendDialogVisible = false;
|
|
128
|
+
}
|
|
190
129
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
130
|
+
function openSendDialog(): void {
|
|
131
|
+
$Data.sendForm = {
|
|
132
|
+
to: "",
|
|
133
|
+
cc: "",
|
|
134
|
+
subject: "",
|
|
135
|
+
content: ""
|
|
136
|
+
};
|
|
137
|
+
$Data.sendDialogVisible = true;
|
|
138
|
+
}
|
|
195
139
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
to: $Data.sendForm.to,
|
|
200
|
-
subject: $Data.sendForm.subject,
|
|
201
|
-
content: $Data.sendForm.content,
|
|
202
|
-
cc: $Data.sendForm.cc || undefined,
|
|
203
|
-
isHtml: true
|
|
204
|
-
});
|
|
140
|
+
type PageDialogEventContext = {
|
|
141
|
+
close: () => void;
|
|
142
|
+
};
|
|
205
143
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
144
|
+
async function onSend(reload: ((options: { keepSelection?: boolean; resetPage?: boolean }) => void) | null, context?: PageDialogEventContext): Promise<void> {
|
|
145
|
+
const valid = await $From.sendForm?.validate();
|
|
146
|
+
if (valid !== true) return;
|
|
147
|
+
|
|
148
|
+
$Data.sending = true;
|
|
149
|
+
try {
|
|
150
|
+
const res = await $Http.post("/addon/admin/email/send", {
|
|
151
|
+
to: $Data.sendForm.to,
|
|
152
|
+
subject: $Data.sendForm.subject,
|
|
153
|
+
content: $Data.sendForm.content,
|
|
154
|
+
cc: $Data.sendForm.cc || undefined,
|
|
155
|
+
isHtml: true
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
if (res.code === 0) {
|
|
159
|
+
MessagePlugin.success("发送成功");
|
|
160
|
+
if (context && typeof context.close === "function") {
|
|
161
|
+
context.close();
|
|
210
162
|
} else {
|
|
211
|
-
|
|
163
|
+
$Data.sendDialogVisible = false;
|
|
212
164
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
} finally {
|
|
216
|
-
$Data.sending = false;
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
|
|
220
|
-
// 验证配置
|
|
221
|
-
async onVerify() {
|
|
222
|
-
try {
|
|
223
|
-
const res = await $Http.post("/addon/admin/email/verify");
|
|
224
|
-
if (res.code === 0) {
|
|
225
|
-
MessagePlugin.success("邮件服务配置正常");
|
|
226
|
-
} else {
|
|
227
|
-
MessagePlugin.error(res.msg || "配置异常");
|
|
165
|
+
if (reload) {
|
|
166
|
+
reload({ keepSelection: false, resetPage: true });
|
|
228
167
|
}
|
|
229
|
-
}
|
|
230
|
-
MessagePlugin.error("
|
|
168
|
+
} else {
|
|
169
|
+
MessagePlugin.error(res.msg || "发送失败");
|
|
231
170
|
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// 分页改变
|
|
240
|
-
onPageChange(currentPage) {
|
|
241
|
-
$Data.pagerConfig.currentPage = currentPage;
|
|
242
|
-
$Method.apiEmailLogList();
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
// 每页条数改变
|
|
246
|
-
handleSizeChange(pageSize) {
|
|
247
|
-
$Data.pagerConfig.limit = pageSize;
|
|
248
|
-
$Data.pagerConfig.currentPage = 1;
|
|
249
|
-
$Method.apiEmailLogList();
|
|
250
|
-
},
|
|
171
|
+
} catch (error) {
|
|
172
|
+
MessagePlugin.error("发送失败");
|
|
173
|
+
} finally {
|
|
174
|
+
$Data.sending = false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
251
177
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
178
|
+
async function onVerify(): Promise<void> {
|
|
179
|
+
try {
|
|
180
|
+
const res = await $Http.post("/addon/admin/email/verify");
|
|
181
|
+
if (res.code === 0) {
|
|
182
|
+
MessagePlugin.success("邮件服务配置正常");
|
|
183
|
+
} else {
|
|
184
|
+
MessagePlugin.error(res.msg || "配置异常");
|
|
256
185
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
$Data.currentRow = context.activeRowList[0].row;
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
// 格式化时间
|
|
264
|
-
formatTime(timestamp) {
|
|
265
|
-
if (!timestamp) return "-";
|
|
266
|
-
const date = new Date(timestamp);
|
|
267
|
-
const year = date.getFullYear();
|
|
268
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
269
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
270
|
-
const hours = String(date.getHours()).padStart(2, "0");
|
|
271
|
-
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
272
|
-
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
273
|
-
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
186
|
+
} catch (error) {
|
|
187
|
+
MessagePlugin.error("验证失败");
|
|
274
188
|
}
|
|
275
|
-
}
|
|
189
|
+
}
|
|
276
190
|
|
|
277
|
-
|
|
191
|
+
function formatTime(timestamp: unknown): string {
|
|
192
|
+
if (!timestamp) return "-";
|
|
193
|
+
const date = new Date(timestamp as never);
|
|
194
|
+
const year = date.getFullYear();
|
|
195
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
196
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
197
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
198
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
199
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
200
|
+
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
201
|
+
}
|
|
278
202
|
</script>
|
|
279
203
|
|
|
280
204
|
<style scoped lang="scss">
|