feat(评论管理): 添加评论地址字段并改进状态选择方式
在评论管理功能中新增postSlug字段,用于存储评论所属文章的地址 将状态切换按钮改为下拉选择框,提升用户体验 同时调整了相关字体大小和样式
This commit is contained in:
@@ -115,6 +115,7 @@ export function updateComment(data: {
|
|||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
url?: string | null;
|
url?: string | null;
|
||||||
|
postSlug?: string;
|
||||||
contentText: string;
|
contentText: string;
|
||||||
status?: string;
|
status?: string;
|
||||||
}): Promise<{ message: string }> {
|
}): Promise<{ message: string }> {
|
||||||
@@ -123,6 +124,7 @@ export function updateComment(data: {
|
|||||||
name: data.name,
|
name: data.name,
|
||||||
email: data.email,
|
email: data.email,
|
||||||
url: data.url ?? null,
|
url: data.url ?? null,
|
||||||
|
postSlug: data.postSlug,
|
||||||
content: data.contentText,
|
content: data.contentText,
|
||||||
status: data.status
|
status: data.status
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -82,27 +82,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="table-cell table-cell-actions">
|
<div class="table-cell table-cell-actions">
|
||||||
<div class="table-actions">
|
<div class="table-actions">
|
||||||
<button
|
<select
|
||||||
class="table-action"
|
class="status-select"
|
||||||
@click="changeStatus(item, 'approved')"
|
:value="item.status"
|
||||||
:disabled="item.status === 'approved'"
|
@change="handleStatusChange(item, $event)"
|
||||||
>
|
>
|
||||||
通过
|
<option value="approved">通过</option>
|
||||||
</button>
|
<option value="pending">待审</option>
|
||||||
<button
|
<option value="rejected">拒绝</option>
|
||||||
class="table-action"
|
</select>
|
||||||
@click="changeStatus(item, 'pending')"
|
|
||||||
:disabled="item.status === 'pending'"
|
|
||||||
>
|
|
||||||
待审
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="table-action"
|
|
||||||
@click="changeStatus(item, 'rejected')"
|
|
||||||
:disabled="item.status === 'rejected'"
|
|
||||||
>
|
|
||||||
拒绝
|
|
||||||
</button>
|
|
||||||
<button class="table-action" @click="openEdit(item)">编辑</button>
|
<button class="table-action" @click="openEdit(item)">编辑</button>
|
||||||
<button
|
<button
|
||||||
class="table-action table-action-danger"
|
class="table-action table-action-danger"
|
||||||
@@ -204,6 +192,10 @@
|
|||||||
<label class="form-label">访客网址</label>
|
<label class="form-label">访客网址</label>
|
||||||
<input v-model="editForm.url" class="form-input" type="text" />
|
<input v-model="editForm.url" class="form-input" type="text" />
|
||||||
</div>
|
</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">
|
<div class="form-item">
|
||||||
<label class="form-label">评论内容</label>
|
<label class="form-label">评论内容</label>
|
||||||
<textarea
|
<textarea
|
||||||
@@ -272,6 +264,7 @@ const editForm = ref<{
|
|||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
postSlug: string;
|
||||||
contentText: string;
|
contentText: string;
|
||||||
status: string;
|
status: string;
|
||||||
} | null>(null);
|
} | 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) {
|
async function removeComment(item: CommentItem) {
|
||||||
if (!window.confirm(`确认删除评论 ${item.id} 吗`)) {
|
if (!window.confirm(`确认删除评论 ${item.id} 吗`)) {
|
||||||
return;
|
return;
|
||||||
@@ -438,6 +440,7 @@ function openEdit(item: CommentItem) {
|
|||||||
name: item.name,
|
name: item.name,
|
||||||
email: item.email,
|
email: item.email,
|
||||||
url: item.url || "",
|
url: item.url || "",
|
||||||
|
postSlug: item.postSlug || "",
|
||||||
contentText: item.contentText,
|
contentText: item.contentText,
|
||||||
status: item.status,
|
status: item.status,
|
||||||
};
|
};
|
||||||
@@ -457,7 +460,15 @@ async function submitEdit() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const current = editForm.value;
|
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 = "昵称、邮箱和内容不能为空";
|
error.value = "昵称、邮箱和内容不能为空";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -466,20 +477,21 @@ async function submitEdit() {
|
|||||||
try {
|
try {
|
||||||
await updateComment({
|
await updateComment({
|
||||||
id: current.id,
|
id: current.id,
|
||||||
name: current.name.trim(),
|
name: trimmedName,
|
||||||
email: current.email.trim(),
|
email: trimmedEmail,
|
||||||
url: current.url.trim() || null,
|
url: trimmedUrl || null,
|
||||||
contentText: current.contentText,
|
postSlug: newPostSlug,
|
||||||
|
contentText: trimmedContent,
|
||||||
status: current.status,
|
status: current.status,
|
||||||
});
|
});
|
||||||
const index = comments.value.findIndex((c) => c.id === current.id);
|
if (commentIndex !== -1) {
|
||||||
if (index !== -1) {
|
comments.value[commentIndex] = {
|
||||||
comments.value[index] = {
|
...comments.value[commentIndex],
|
||||||
...comments.value[index],
|
name: trimmedName,
|
||||||
name: current.name.trim(),
|
email: trimmedEmail,
|
||||||
email: current.email.trim(),
|
url: trimmedUrl || null,
|
||||||
url: current.url.trim() || null,
|
postSlug: newPostSlug,
|
||||||
contentText: current.contentText,
|
contentText: trimmedContent,
|
||||||
status: current.status,
|
status: current.status,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -707,7 +719,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cell-path {
|
.cell-path {
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
color: #2774cb;
|
color: #2774cb;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -764,6 +776,14 @@ onMounted(() => {
|
|||||||
background-color: #ffebe9;
|
background-color: #ffebe9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-select {
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #d0d7de;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.table-actions {
|
.table-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
@@ -775,7 +795,7 @@ onMounted(() => {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #d0d7de;
|
border: 1px solid #d0d7de;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const existing = await c.env.CWD_DB.prepare(
|
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)
|
.bind(id)
|
||||||
.first<{ id: number; status: string }>();
|
.first<{ id: number; status: string; post_slug: string }>();
|
||||||
|
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
return c.json({ message: 'Comment not found' }, 404);
|
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 rawEmail = typeof body.email === 'string' ? body.email : '';
|
||||||
const rawUrl = typeof body.url === 'string' ? body.url : '';
|
const rawUrl = typeof body.url === 'string' ? body.url : '';
|
||||||
const rawStatus = typeof body.status === 'string' ? body.status : existing.status;
|
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 =
|
const contentSource =
|
||||||
typeof body.content === 'string'
|
typeof body.content === 'string'
|
||||||
@@ -50,6 +59,9 @@ export const updateComment = async (c: Context<{ Bindings: Bindings }>) => {
|
|||||||
const email = rawEmail.trim();
|
const email = rawEmail.trim();
|
||||||
const url = rawUrl.trim() || null;
|
const url = rawUrl.trim() || null;
|
||||||
const status = rawStatus.trim();
|
const status = rawStatus.trim();
|
||||||
|
const postSlug = hasPostSlugField
|
||||||
|
? (rawPostSlug.trim() || existing.post_slug)
|
||||||
|
: existing.post_slug;
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return c.json({ message: '昵称不能为空' }, 400);
|
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(
|
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();
|
.run();
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|||||||
Reference in New Issue
Block a user