feat(邮件通知): 重构邮件通知系统并增加配置选项
- 移除 Cloudflare Email 绑定,改为支持外部邮件网关 - 新增邮件通知全局开关及管理员/用户通知独立配置 - 在管理后台添加邮件通知配置界面 - 优化邮件发送逻辑,增加错误处理和日志记录 - 更新相关文档说明
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -40,6 +40,12 @@ export type CommentSettingsResponse = {
|
||||
adminEnabled: boolean;
|
||||
};
|
||||
|
||||
export type EmailNotifySettingsResponse = {
|
||||
globalEnabled: boolean;
|
||||
adminEnabled: boolean;
|
||||
userEnabled: boolean;
|
||||
};
|
||||
|
||||
export async function loginAdmin(name: string, password: string): Promise<string> {
|
||||
const res = await post<AdminLoginResponse>('/admin/login', { name, password });
|
||||
const key = res.data.key;
|
||||
@@ -71,6 +77,18 @@ export function saveAdminEmail(email: string): Promise<{ message: string }> {
|
||||
return put<{ message: string }>('/admin/settings/email', { email });
|
||||
}
|
||||
|
||||
export function fetchEmailNotifySettings(): Promise<EmailNotifySettingsResponse> {
|
||||
return get<EmailNotifySettingsResponse>('/admin/settings/email-notify');
|
||||
}
|
||||
|
||||
export function saveEmailNotifySettings(data: {
|
||||
globalEnabled?: boolean;
|
||||
adminEnabled?: boolean;
|
||||
userEnabled?: boolean;
|
||||
}): Promise<{ message: string }> {
|
||||
return put<{ message: string }>('/admin/settings/email-notify', data);
|
||||
}
|
||||
|
||||
export function fetchCommentSettings(): Promise<CommentSettingsResponse> {
|
||||
return get<CommentSettingsResponse>('/admin/settings/comments');
|
||||
}
|
||||
|
||||
@@ -41,6 +41,27 @@
|
||||
|
||||
<div class="card">
|
||||
<h3 class="card-title">通知邮箱设置</h3>
|
||||
<div class="form-item">
|
||||
<label class="form-label">开启邮件通知</label>
|
||||
<label class="switch">
|
||||
<input v-model="emailGlobalEnabled" type="checkbox" />
|
||||
<span class="slider" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">新评论通知管理员</label>
|
||||
<label class="switch">
|
||||
<input v-model="emailAdminEnabled" type="checkbox" />
|
||||
<span class="slider" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">评论回复通知用户</label>
|
||||
<label class="switch">
|
||||
<input v-model="emailUserEnabled" type="checkbox" />
|
||||
<span class="slider" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">管理员通知邮箱</label>
|
||||
<input v-model="email" class="form-input" type="email" />
|
||||
@@ -69,9 +90,14 @@ import {
|
||||
saveAdminEmail,
|
||||
fetchCommentSettings,
|
||||
saveCommentSettings,
|
||||
fetchEmailNotifySettings,
|
||||
saveEmailNotifySettings,
|
||||
} from "../api/admin";
|
||||
|
||||
const email = ref("");
|
||||
const emailGlobalEnabled = ref(true);
|
||||
const emailAdminEnabled = ref(true);
|
||||
const emailUserEnabled = ref(true);
|
||||
const commentAdminEmail = ref("");
|
||||
const commentAdminBadge = ref("");
|
||||
const avatarPrefix = ref("");
|
||||
@@ -97,15 +123,19 @@ function showToast(msg: string, type: "success" | "error" = "success") {
|
||||
async function load() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const [notifyRes, commentRes] = await Promise.all([
|
||||
const [notifyRes, commentRes, emailNotifyRes] = await Promise.all([
|
||||
fetchAdminEmail(),
|
||||
fetchCommentSettings(),
|
||||
fetchEmailNotifySettings(),
|
||||
]);
|
||||
email.value = notifyRes.email || "";
|
||||
commentAdminEmail.value = commentRes.adminEmail || "";
|
||||
commentAdminBadge.value = commentRes.adminBadge || "博主";
|
||||
avatarPrefix.value = commentRes.avatarPrefix || "";
|
||||
commentAdminEnabled.value = !!commentRes.adminEnabled;
|
||||
emailGlobalEnabled.value = !!emailNotifyRes.globalEnabled;
|
||||
emailAdminEnabled.value = !!emailNotifyRes.adminEnabled;
|
||||
emailUserEnabled.value = !!emailNotifyRes.userEnabled;
|
||||
} catch (e: any) {
|
||||
message.value = e.message || "加载失败";
|
||||
messageType.value = "error";
|
||||
@@ -123,8 +153,15 @@ async function saveEmail() {
|
||||
savingEmail.value = true;
|
||||
message.value = "";
|
||||
try {
|
||||
const res = await saveAdminEmail(email.value);
|
||||
showToast(res.message || "保存成功", "success");
|
||||
const [emailRes] = await Promise.all([
|
||||
saveAdminEmail(email.value),
|
||||
saveEmailNotifySettings({
|
||||
globalEnabled: emailGlobalEnabled.value,
|
||||
adminEnabled: emailAdminEnabled.value,
|
||||
userEnabled: emailUserEnabled.value,
|
||||
}),
|
||||
]);
|
||||
showToast(emailRes.message || "保存成功", "success");
|
||||
} catch (e: any) {
|
||||
message.value = e.message || "保存失败";
|
||||
messageType.value = "error";
|
||||
|
||||
Reference in New Issue
Block a user