feat(admin): 添加管理员密钥验证功能

- 新增管理员密钥设置及验证流程
- 实现前端验证弹窗及本地存储加密
- 修改评论提交接口支持管理员验证
- 添加相关样式和文档说明
This commit is contained in:
anghunk
2026-01-20 16:46:42 +08:00
parent a41d783326
commit ab67bfb40e
14 changed files with 554 additions and 12 deletions

View File

@@ -40,6 +40,8 @@ export type CommentSettingsResponse = {
avatarPrefix: string | null;
adminEnabled: boolean;
allowedDomains?: string[];
adminKey?: string | null;
adminKeySet?: boolean;
};
export type EmailNotifySettingsResponse = {
@@ -132,6 +134,7 @@ export function saveCommentSettings(data: {
avatarPrefix?: string;
adminEnabled?: boolean;
allowedDomains?: string[];
adminKey?: string;
}): Promise<{ message: string }> {
return put<{ message: string }>('/admin/settings/comments', data);
}
@@ -143,4 +146,3 @@ export function exportComments(): Promise<any[]> {
export function importComments(data: any[]): Promise<{ message: string }> {
return post<{ message: string }>('/admin/comments/import', data);
}

View File

@@ -32,9 +32,7 @@
<input v-model="avatarPrefix" class="form-input" type="text" />
</div>
<div class="form-item">
<label class="form-label"
>允许调用的域名多个域名用逗号分隔留空则不限制</label
>
<label class="form-label">允许调用的域名多个域名用逗号分隔留空则不限制</label>
<textarea
v-model="allowedDomains"
class="form-input"
@@ -42,6 +40,18 @@
placeholder="例如: example.com, test.com"
></textarea>
</div>
<div class="form-item">
<label class="form-label">管理员评论密钥</label>
<div class="form-hint" style="margin-bottom: 4px;">
设置后前台使用管理员邮箱评论需输入此密钥
</div>
<input
v-model="commentAdminKey"
class="form-input"
placeholder="输入密钥以设置或修改"
autocomplete="new-password"
/>
</div>
<div class="card-actions">
<button class="card-button" :disabled="savingComment" @click="saveComment">
<span v-if="savingComment">保存中...</span>
@@ -287,6 +297,8 @@ const commentAdminBadge = ref("");
const avatarPrefix = ref("");
const commentAdminEnabled = ref(false);
const allowedDomains = ref("");
const commentAdminKey = ref("");
const adminKeySet = ref(false);
const savingEmail = ref(false);
const testingEmail = ref(false);
const savingComment = ref(false);
@@ -344,6 +356,8 @@ async function load() {
allowedDomains.value = commentRes.allowedDomains
? commentRes.allowedDomains.join(", ")
: "";
commentAdminKey.value = commentRes.adminKey || "";
adminKeySet.value = !!commentRes.adminKeySet;
emailGlobalEnabled.value = !!emailNotifyRes.globalEnabled;
if (emailNotifyRes.templates) {
@@ -472,7 +486,9 @@ async function saveComment() {
.split(/[,\n]/)
.map((d) => d.trim())
.filter(Boolean),
adminKey: commentAdminKey.value || undefined,
});
showToast(res.message || "保存成功", "success");
} catch (e: any) {
message.value = e.message || "保存失败";