refactor(admin): 重构设置页面并添加全局 toast 提示
- 将通知邮箱设置卡片移至评论配置下方 - 添加全局 toast 提示组件替代原有表单消息 - 简化错误消息显示逻辑 - 更新数据库查询语句以匹配新增设置项
This commit is contained in:
@@ -1,31 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<h2 class="page-title">系统设置</h2>
|
<h2 class="page-title">系统设置</h2>
|
||||||
|
<div
|
||||||
|
v-if="toastVisible"
|
||||||
|
class="toast"
|
||||||
|
:class="toastType === 'error' ? 'toast-error' : 'toast-success'"
|
||||||
|
>
|
||||||
|
{{ toastMessage }}
|
||||||
|
</div>
|
||||||
<div v-if="loading" class="page-hint">加载中...</div>
|
<div v-if="loading" class="page-hint">加载中...</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="card">
|
|
||||||
<h3 class="card-title">通知邮箱设置</h3>
|
|
||||||
<div class="form-item">
|
|
||||||
<label class="form-label">管理员通知邮箱</label>
|
|
||||||
<input v-model="email" class="form-input" type="email" />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="message"
|
|
||||||
:class="[
|
|
||||||
'form-message',
|
|
||||||
messageType === 'error' ? 'form-message-error' : 'form-message-success',
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
{{ message }}
|
|
||||||
</div>
|
|
||||||
<div class="card-actions">
|
|
||||||
<button class="card-button" :disabled="savingEmail" @click="saveEmail">
|
|
||||||
<span v-if="savingEmail">保存中...</span>
|
|
||||||
<span v-else>保存</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3 class="card-title">评论显示配置</h3>
|
<h3 class="card-title">评论显示配置</h3>
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
@@ -54,6 +38,26 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="card-title">通知邮箱设置</h3>
|
||||||
|
<div class="form-item">
|
||||||
|
<label class="form-label">管理员通知邮箱</label>
|
||||||
|
<input v-model="email" class="form-input" type="email" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="message && messageType === 'error'"
|
||||||
|
class="form-message form-message-error"
|
||||||
|
>
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
<div class="card-actions">
|
||||||
|
<button class="card-button" :disabled="savingEmail" @click="saveEmail">
|
||||||
|
<span v-if="savingEmail">保存中...</span>
|
||||||
|
<span v-else>保存</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -77,6 +81,18 @@ const savingComment = ref(false);
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const message = ref("");
|
const message = ref("");
|
||||||
const messageType = ref<"success" | "error">("success");
|
const messageType = ref<"success" | "error">("success");
|
||||||
|
const toastMessage = ref("");
|
||||||
|
const toastType = ref<"success" | "error">("success");
|
||||||
|
const toastVisible = ref(false);
|
||||||
|
|
||||||
|
function showToast(msg: string, type: "success" | "error" = "success") {
|
||||||
|
toastMessage.value = msg;
|
||||||
|
toastType.value = type;
|
||||||
|
toastVisible.value = true;
|
||||||
|
window.setTimeout(() => {
|
||||||
|
toastVisible.value = false;
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@@ -108,8 +124,7 @@ async function saveEmail() {
|
|||||||
message.value = "";
|
message.value = "";
|
||||||
try {
|
try {
|
||||||
const res = await saveAdminEmail(email.value);
|
const res = await saveAdminEmail(email.value);
|
||||||
message.value = res.message || "保存成功";
|
showToast(res.message || "保存成功", "success");
|
||||||
messageType.value = "success";
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
message.value = e.message || "保存失败";
|
message.value = e.message || "保存失败";
|
||||||
messageType.value = "error";
|
messageType.value = "error";
|
||||||
@@ -128,8 +143,7 @@ async function saveComment() {
|
|||||||
avatarPrefix: avatarPrefix.value,
|
avatarPrefix: avatarPrefix.value,
|
||||||
adminEnabled: commentAdminEnabled.value,
|
adminEnabled: commentAdminEnabled.value,
|
||||||
});
|
});
|
||||||
message.value = res.message || "保存成功";
|
showToast(res.message || "保存成功", "success");
|
||||||
messageType.value = "success";
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
message.value = e.message || "保存失败";
|
message.value = e.message || "保存失败";
|
||||||
messageType.value = "error";
|
messageType.value = "error";
|
||||||
@@ -162,6 +176,7 @@ onMounted(() => {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: 1px solid #d0d7de;
|
border: 1px solid #d0d7de;
|
||||||
padding: 16px 18px;
|
padding: 16px 18px;
|
||||||
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
@@ -194,6 +209,30 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toast {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
min-width: 220px;
|
||||||
|
max-width: 320px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
box-shadow: 0 8px 24px rgba(140, 149, 159, 0.2);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-success {
|
||||||
|
background-color: #1a7f37;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-error {
|
||||||
|
background-color: #d1242f;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
.switch {
|
.switch {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async function loadCommentSettings(env: Bindings) {
|
|||||||
COMMENT_ADMIN_ENABLED_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 (?, ?, ?, ?)'
|
||||||
)
|
)
|
||||||
.bind(...keys)
|
.bind(...keys)
|
||||||
.all<{ key: string; value: string }>();
|
.all<{ key: string; value: string }>();
|
||||||
|
|||||||
Reference in New Issue
Block a user