feat(评论管理): 添加评论地址字段并改进状态选择方式

在评论管理功能中新增postSlug字段,用于存储评论所属文章的地址
将状态切换按钮改为下拉选择框,提升用户体验
同时调整了相关字体大小和样式
This commit is contained in:
anghunk
2026-01-21 17:38:36 +08:00
parent 27afa2db4f
commit 0c327864d7
3 changed files with 73 additions and 39 deletions

View File

@@ -115,6 +115,7 @@ export function updateComment(data: {
name: string;
email: string;
url?: string | null;
postSlug?: string;
contentText: string;
status?: string;
}): Promise<{ message: string }> {
@@ -123,6 +124,7 @@ export function updateComment(data: {
name: data.name,
email: data.email,
url: data.url ?? null,
postSlug: data.postSlug,
content: data.contentText,
status: data.status
});

View File

@@ -82,27 +82,15 @@
</div>
<div class="table-cell table-cell-actions">
<div class="table-actions">
<button
class="table-action"
@click="changeStatus(item, 'approved')"
:disabled="item.status === 'approved'"
<select
class="status-select"
:value="item.status"
@change="handleStatusChange(item, $event)"
>
通过
</button>
<button
class="table-action"
@click="changeStatus(item, 'pending')"
:disabled="item.status === 'pending'"
>
待审
</button>
<button
class="table-action"
@click="changeStatus(item, 'rejected')"
:disabled="item.status === 'rejected'"
>
拒绝
</button>
<option value="approved">通过</option>
<option value="pending">待审</option>
<option value="rejected">拒绝</option>
</select>
<button class="table-action" @click="openEdit(item)">编辑</button>
<button
class="table-action table-action-danger"
@@ -204,6 +192,10 @@
<label class="form-label">访客网址</label>
<input v-model="editForm.url" class="form-input" type="text" />
</div>
<div class="form-item">
<label class="form-label">评论地址</label>
<input v-model="editForm.postSlug" class="form-input" type="text" />
</div>
<div class="form-item">
<label class="form-label">评论内容</label>
<textarea
@@ -272,6 +264,7 @@ const editForm = ref<{
name: string;
email: string;
url: string;
postSlug: string;
contentText: string;
status: string;
} | null>(null);
@@ -390,6 +383,15 @@ async function changeStatus(item: CommentItem, status: string) {
}
}
function handleStatusChange(item: CommentItem, event: Event) {
const target = event.target as HTMLSelectElement;
const status = target.value;
if (!status || status === item.status) {
return;
}
changeStatus(item, status);
}
async function removeComment(item: CommentItem) {
if (!window.confirm(`确认删除评论 ${item.id} 吗`)) {
return;
@@ -438,6 +440,7 @@ function openEdit(item: CommentItem) {
name: item.name,
email: item.email,
url: item.url || "",
postSlug: item.postSlug || "",
contentText: item.contentText,
status: item.status,
};
@@ -457,7 +460,15 @@ async function submitEdit() {
return;
}
const current = editForm.value;
if (!current.name.trim() || !current.email.trim() || !current.contentText.trim()) {
const trimmedName = current.name.trim();
const trimmedEmail = current.email.trim();
const trimmedContent = current.contentText.trim();
const trimmedUrl = current.url.trim();
const trimmedPostSlug = current.postSlug.trim();
const commentIndex = comments.value.findIndex((c) => c.id === current.id);
const existingComment = commentIndex !== -1 ? comments.value[commentIndex] : null;
const newPostSlug = trimmedPostSlug || existingComment?.postSlug || "";
if (!trimmedName || !trimmedEmail || !trimmedContent) {
error.value = "昵称、邮箱和内容不能为空";
return;
}
@@ -466,20 +477,21 @@ async function submitEdit() {
try {
await updateComment({
id: current.id,
name: current.name.trim(),
email: current.email.trim(),
url: current.url.trim() || null,
contentText: current.contentText,
name: trimmedName,
email: trimmedEmail,
url: trimmedUrl || null,
postSlug: newPostSlug,
contentText: trimmedContent,
status: current.status,
});
const index = comments.value.findIndex((c) => c.id === current.id);
if (index !== -1) {
comments.value[index] = {
...comments.value[index],
name: current.name.trim(),
email: current.email.trim(),
url: current.url.trim() || null,
contentText: current.contentText,
if (commentIndex !== -1) {
comments.value[commentIndex] = {
...comments.value[commentIndex],
name: trimmedName,
email: trimmedEmail,
url: trimmedUrl || null,
postSlug: newPostSlug,
contentText: trimmedContent,
status: current.status,
};
}
@@ -707,7 +719,7 @@ onMounted(() => {
}
.cell-path {
font-size: 12px;
font-size: 13px;
color: #2774cb;
white-space: nowrap;
overflow: hidden;
@@ -764,6 +776,14 @@ onMounted(() => {
background-color: #ffebe9;
}
.status-select {
padding: 3px 8px;
border-radius: 4px;
border: 1px solid #d0d7de;
font-size: 13px;
cursor: pointer;
}
.table-actions {
display: flex;
gap: 4px;
@@ -775,7 +795,7 @@ onMounted(() => {
border-radius: 4px;
border: 1px solid #d0d7de;
background-color: #ffffff;
font-size: 12px;
font-size: 13px;
cursor: pointer;
}

View File

@@ -25,10 +25,10 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => {
}
const existing = await c.env.CWD_DB.prepare(
'SELECT id, status FROM Comment WHERE id = ?'
'SELECT id, status, post_slug FROM Comment WHERE id = ?'
)
.bind(id)
.first<{ id: number; status: string }>();
.first<{ id: number; status: string; post_slug: string }>();
if (!existing) {
return c.json({ message: 'Comment not found' }, 404);
@@ -38,6 +38,15 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => {
const rawEmail = typeof body.email === 'string' ? body.email : '';
const rawUrl = typeof body.url === 'string' ? body.url : '';
const rawStatus = typeof body.status === 'string' ? body.status : existing.status;
const hasPostSlugField =
Object.prototype.hasOwnProperty.call(body, 'postSlug') ||
Object.prototype.hasOwnProperty.call(body, 'post_slug');
const rawPostSlug =
typeof body.postSlug === 'string'
? body.postSlug
: typeof body.post_slug === 'string'
? body.post_slug
: '';
const contentSource =
typeof body.content === 'string'
@@ -50,6 +59,9 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => {
const email = rawEmail.trim();
const url = rawUrl.trim() || null;
const status = rawStatus.trim();
const postSlug = hasPostSlugField
? (rawPostSlug.trim() || existing.post_slug)
: existing.post_slug;
if (!name) {
return c.json({ message: '昵称不能为空' }, 400);
@@ -78,9 +90,9 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => {
});
const { success } = await c.env.CWD_DB.prepare(
'UPDATE Comment SET name = ?, email = ?, url = ?, content_text = ?, content_html = ?, status = ? WHERE id = ?'
'UPDATE Comment SET name = ?, email = ?, url = ?, content_text = ?, content_html = ?, status = ?, post_slug = ? WHERE id = ?'
)
.bind(name, email, url, contentText, contentHtml, status, id)
.bind(name, email, url, contentText, contentHtml, status, postSlug, id)
.run();
if (!success) {