feat(admin): 添加博主显示开关功能
在评论系统设置中添加管理员显示开关,允许控制博主标识的显示 更新前后端接口以支持新功能,包括数据库存储和界面切换组件
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
VITE_API_BASE_URL=https://api.example.com
|
VITE_API_BASE_URL=https://api.example.com
|
||||||
VITE_ADMIN_NAME=anghunk@example.com
|
VITE_ADMIN_NAME=admin@example.com
|
||||||
VITE_ADMIN_PASSWORD=123456
|
VITE_ADMIN_PASSWORD=123456
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export type CommentSettingsResponse = {
|
|||||||
adminEmail: string | null;
|
adminEmail: string | null;
|
||||||
adminBadge: string | null;
|
adminBadge: string | null;
|
||||||
avatarPrefix: string | null;
|
avatarPrefix: string | null;
|
||||||
|
adminEnabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function loginAdmin(name: string, password: string): Promise<string> {
|
export async function loginAdmin(name: string, password: string): Promise<string> {
|
||||||
@@ -78,6 +79,7 @@ export function saveCommentSettings(data: {
|
|||||||
adminEmail?: string;
|
adminEmail?: string;
|
||||||
adminBadge?: string;
|
adminBadge?: string;
|
||||||
avatarPrefix?: string;
|
avatarPrefix?: string;
|
||||||
|
adminEnabled?: boolean;
|
||||||
}): Promise<{ message: string }> {
|
}): Promise<{ message: string }> {
|
||||||
return put<{ message: string }>('/admin/settings/comments', data);
|
return put<{ message: string }>('/admin/settings/comments', data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,7 +428,7 @@ onMounted(() => {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #d0d7de;
|
border: 1px solid #d0d7de;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,13 @@
|
|||||||
<label class="form-label">博主标签文字</label>
|
<label class="form-label">博主标签文字</label>
|
||||||
<input v-model="commentAdminBadge" class="form-input" type="text" />
|
<input v-model="commentAdminBadge" class="form-input" type="text" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label class="form-label">是否开启博主显示</label>
|
||||||
|
<label class="switch">
|
||||||
|
<input v-model="commentAdminEnabled" type="checkbox" />
|
||||||
|
<span class="slider" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
<label class="form-label">头像前缀(Gravatar/Cravatar)</label>
|
<label class="form-label">头像前缀(Gravatar/Cravatar)</label>
|
||||||
<input v-model="avatarPrefix" class="form-input" type="text" />
|
<input v-model="avatarPrefix" class="form-input" type="text" />
|
||||||
@@ -64,6 +71,7 @@ const email = ref("");
|
|||||||
const commentAdminEmail = ref("");
|
const commentAdminEmail = ref("");
|
||||||
const commentAdminBadge = ref("");
|
const commentAdminBadge = ref("");
|
||||||
const avatarPrefix = ref("");
|
const avatarPrefix = ref("");
|
||||||
|
const commentAdminEnabled = ref(false);
|
||||||
const savingEmail = ref(false);
|
const savingEmail = ref(false);
|
||||||
const savingComment = ref(false);
|
const savingComment = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@@ -81,6 +89,7 @@ async function load() {
|
|||||||
commentAdminEmail.value = commentRes.adminEmail || "";
|
commentAdminEmail.value = commentRes.adminEmail || "";
|
||||||
commentAdminBadge.value = commentRes.adminBadge || "博主";
|
commentAdminBadge.value = commentRes.adminBadge || "博主";
|
||||||
avatarPrefix.value = commentRes.avatarPrefix || "";
|
avatarPrefix.value = commentRes.avatarPrefix || "";
|
||||||
|
commentAdminEnabled.value = !!commentRes.adminEnabled;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
message.value = e.message || "加载失败";
|
message.value = e.message || "加载失败";
|
||||||
messageType.value = "error";
|
messageType.value = "error";
|
||||||
@@ -117,6 +126,7 @@ async function saveComment() {
|
|||||||
adminEmail: commentAdminEmail.value,
|
adminEmail: commentAdminEmail.value,
|
||||||
adminBadge: commentAdminBadge.value,
|
adminBadge: commentAdminBadge.value,
|
||||||
avatarPrefix: avatarPrefix.value,
|
avatarPrefix: avatarPrefix.value,
|
||||||
|
adminEnabled: commentAdminEnabled.value,
|
||||||
});
|
});
|
||||||
message.value = res.message || "保存成功";
|
message.value = res.message || "保存成功";
|
||||||
messageType.value = "success";
|
messageType.value = "success";
|
||||||
@@ -184,6 +194,53 @@ onMounted(() => {
|
|||||||
box-shadow: 0 0 0 1px rgba(9, 105, 218, 0.2);
|
box-shadow: 0 0 0 1px rgba(9, 105, 218, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
width: 40px;
|
||||||
|
height: 22px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch input {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #d0d7de;
|
||||||
|
transition: 0.2s;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider::before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
left: 3px;
|
||||||
|
top: 3px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
transition: 0.2s;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 1px 2px rgba(27, 31, 36, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch input:checked + .slider {
|
||||||
|
background-color: #0969da;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch input:checked + .slider::before {
|
||||||
|
transform: translateX(16px);
|
||||||
|
}
|
||||||
|
|
||||||
.card-actions {
|
.card-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|||||||
@@ -19,12 +19,18 @@ const VERSION = 'v0.0.1';
|
|||||||
const COMMENT_ADMIN_EMAIL_KEY = 'comment_admin_email';
|
const COMMENT_ADMIN_EMAIL_KEY = 'comment_admin_email';
|
||||||
const COMMENT_ADMIN_BADGE_KEY = 'comment_admin_badge';
|
const COMMENT_ADMIN_BADGE_KEY = 'comment_admin_badge';
|
||||||
const COMMENT_AVATAR_PREFIX_KEY = 'comment_avatar_prefix';
|
const COMMENT_AVATAR_PREFIX_KEY = 'comment_avatar_prefix';
|
||||||
|
const COMMENT_ADMIN_ENABLED_KEY = 'comment_admin_enabled';
|
||||||
|
|
||||||
async function loadCommentSettings(env: Bindings) {
|
async function loadCommentSettings(env: Bindings) {
|
||||||
await env.CWD_DB.prepare(
|
await env.CWD_DB.prepare(
|
||||||
'CREATE TABLE IF NOT EXISTS Settings (key TEXT PRIMARY KEY, value TEXT NOT NULL)'
|
'CREATE TABLE IF NOT EXISTS Settings (key TEXT PRIMARY KEY, value TEXT NOT NULL)'
|
||||||
).run();
|
).run();
|
||||||
const keys = [COMMENT_ADMIN_EMAIL_KEY, COMMENT_ADMIN_BADGE_KEY, COMMENT_AVATAR_PREFIX_KEY];
|
const keys = [
|
||||||
|
COMMENT_ADMIN_EMAIL_KEY,
|
||||||
|
COMMENT_ADMIN_BADGE_KEY,
|
||||||
|
COMMENT_AVATAR_PREFIX_KEY,
|
||||||
|
COMMENT_ADMIN_ENABLED_KEY
|
||||||
|
];
|
||||||
const { results } = await env.CWD_DB.prepare(
|
const { results } = await env.CWD_DB.prepare(
|
||||||
'SELECT key, value FROM Settings WHERE key IN (?, ?, ?)'
|
'SELECT key, value FROM Settings WHERE key IN (?, ?, ?)'
|
||||||
)
|
)
|
||||||
@@ -38,16 +44,25 @@ async function loadCommentSettings(env: Bindings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const enabledRaw = map.get(COMMENT_ADMIN_ENABLED_KEY) ?? null;
|
||||||
|
const adminEnabled = enabledRaw === '1';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
adminEmail: map.get(COMMENT_ADMIN_EMAIL_KEY) ?? null,
|
adminEmail: map.get(COMMENT_ADMIN_EMAIL_KEY) ?? null,
|
||||||
adminBadge: map.get(COMMENT_ADMIN_BADGE_KEY) ?? null,
|
adminBadge: map.get(COMMENT_ADMIN_BADGE_KEY) ?? null,
|
||||||
avatarPrefix: map.get(COMMENT_AVATAR_PREFIX_KEY) ?? null
|
avatarPrefix: map.get(COMMENT_AVATAR_PREFIX_KEY) ?? null,
|
||||||
|
adminEnabled
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveCommentSettings(
|
async function saveCommentSettings(
|
||||||
env: Bindings,
|
env: Bindings,
|
||||||
settings: { adminEmail?: string; adminBadge?: string; avatarPrefix?: string }
|
settings: {
|
||||||
|
adminEmail?: string;
|
||||||
|
adminBadge?: string;
|
||||||
|
avatarPrefix?: string;
|
||||||
|
adminEnabled?: boolean;
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
await env.CWD_DB.prepare(
|
await env.CWD_DB.prepare(
|
||||||
'CREATE TABLE IF NOT EXISTS Settings (key TEXT PRIMARY KEY, value TEXT NOT NULL)'
|
'CREATE TABLE IF NOT EXISTS Settings (key TEXT PRIMARY KEY, value TEXT NOT NULL)'
|
||||||
@@ -56,7 +71,16 @@ async function saveCommentSettings(
|
|||||||
const entries: { key: string; value: string | null | undefined }[] = [
|
const entries: { key: string; value: string | null | undefined }[] = [
|
||||||
{ key: COMMENT_ADMIN_EMAIL_KEY, value: settings.adminEmail },
|
{ key: COMMENT_ADMIN_EMAIL_KEY, value: settings.adminEmail },
|
||||||
{ key: COMMENT_ADMIN_BADGE_KEY, value: settings.adminBadge },
|
{ key: COMMENT_ADMIN_BADGE_KEY, value: settings.adminBadge },
|
||||||
{ key: COMMENT_AVATAR_PREFIX_KEY, value: settings.avatarPrefix }
|
{ key: COMMENT_AVATAR_PREFIX_KEY, value: settings.avatarPrefix },
|
||||||
|
{
|
||||||
|
key: COMMENT_ADMIN_ENABLED_KEY,
|
||||||
|
value:
|
||||||
|
typeof settings.adminEnabled === 'boolean'
|
||||||
|
? settings.adminEnabled
|
||||||
|
? '1'
|
||||||
|
: '0'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
@@ -138,10 +162,15 @@ app.put('/admin/settings/comments', async (c) => {
|
|||||||
const rawAdminEmail = typeof body.adminEmail === 'string' ? body.adminEmail : '';
|
const rawAdminEmail = typeof body.adminEmail === 'string' ? body.adminEmail : '';
|
||||||
const rawAdminBadge = typeof body.adminBadge === 'string' ? body.adminBadge : '';
|
const rawAdminBadge = typeof body.adminBadge === 'string' ? body.adminBadge : '';
|
||||||
const rawAvatarPrefix = typeof body.avatarPrefix === 'string' ? body.avatarPrefix : '';
|
const rawAvatarPrefix = typeof body.avatarPrefix === 'string' ? body.avatarPrefix : '';
|
||||||
|
const rawAdminEnabled = body.adminEnabled;
|
||||||
|
|
||||||
const adminEmail = rawAdminEmail.trim();
|
const adminEmail = rawAdminEmail.trim();
|
||||||
const adminBadge = rawAdminBadge.trim();
|
const adminBadge = rawAdminBadge.trim();
|
||||||
const avatarPrefix = rawAvatarPrefix.trim();
|
const avatarPrefix = rawAvatarPrefix.trim();
|
||||||
|
const adminEnabled =
|
||||||
|
typeof rawAdminEnabled === 'boolean'
|
||||||
|
? rawAdminEnabled
|
||||||
|
: rawAdminEnabled === '1' || rawAdminEnabled === 1;
|
||||||
|
|
||||||
if (adminEmail && !isValidEmail(adminEmail)) {
|
if (adminEmail && !isValidEmail(adminEmail)) {
|
||||||
return c.json({ message: '邮箱格式不正确' }, 400);
|
return c.json({ message: '邮箱格式不正确' }, 400);
|
||||||
@@ -150,7 +179,8 @@ app.put('/admin/settings/comments', async (c) => {
|
|||||||
await saveCommentSettings(c.env, {
|
await saveCommentSettings(c.env, {
|
||||||
adminEmail,
|
adminEmail,
|
||||||
adminBadge,
|
adminBadge,
|
||||||
avatarPrefix
|
avatarPrefix,
|
||||||
|
adminEnabled
|
||||||
});
|
});
|
||||||
|
|
||||||
return c.json({ message: '保存成功' });
|
return c.json({ message: '保存成功' });
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ async function loadServerCommentConfig(apiBaseUrl) {
|
|||||||
return {
|
return {
|
||||||
adminEmail: data.adminEmail || '',
|
adminEmail: data.adminEmail || '',
|
||||||
adminBadge: data.adminBadge || '',
|
adminBadge: data.adminBadge || '',
|
||||||
|
adminEnabled: !!data.adminEnabled,
|
||||||
avatarPrefix: data.avatarPrefix || '',
|
avatarPrefix: data.avatarPrefix || '',
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -119,8 +120,12 @@ async function initWidget() {
|
|||||||
theme: config.theme,
|
theme: config.theme,
|
||||||
avatarPrefix: serverConfig.avatarPrefix || config.avatarPrefix,
|
avatarPrefix: serverConfig.avatarPrefix || config.avatarPrefix,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
...(serverConfig.adminEmail ? { adminEmail: serverConfig.adminEmail } : {}),
|
...(serverConfig.adminEnabled && serverConfig.adminEmail
|
||||||
...(serverConfig.adminBadge ? { adminBadge: serverConfig.adminBadge } : {}),
|
? { adminEmail: serverConfig.adminEmail }
|
||||||
|
: {}),
|
||||||
|
...(serverConfig.adminEnabled && serverConfig.adminBadge
|
||||||
|
? { adminBadge: serverConfig.adminBadge }
|
||||||
|
: {}),
|
||||||
});
|
});
|
||||||
widgetInstance.mount();
|
widgetInstance.mount();
|
||||||
console.log('[CWDComments] Widget 初始化成功', config);
|
console.log('[CWDComments] Widget 初始化成功', config);
|
||||||
|
|||||||
Reference in New Issue
Block a user