feat(comments): 软删占位、理由与恢复,管理删仅对访客打码

自删/管理删差异文案与理由可见性,评论者与管理员免马赛克,并支持恢复与处理人链接。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 07:43:48 +08:00
parent 5052bcd805
commit c6fdbb7193
11 changed files with 941 additions and 141 deletions

View File

@@ -315,6 +315,18 @@ export interface Comment {
user: User;
/** 软删占位 */
deleted?: boolean;
/** 管理删除(DeletedBy≠评论者) */
staff_deleted?: boolean;
delete_type?: string;
delete_reason?: string;
deleted_by?: number;
/** 管理删执行者(公开,用于主页快捷入口) */
deleted_by_user?: {
id: number;
username: string;
nickname: string;
avatar: string;
};
}
// 评论树节点:主评论为根,replies 为其全部子回复(时间正序,全量 SSR 直出)
@@ -1105,9 +1117,26 @@ export async function apiToggleLike(postId: string) {
return res.json();
}
export async function apiDeleteComment(postId: string, commentId: number) {
export async function apiDeleteComment(
postId: string,
commentId: number,
opts: { delete_type?: string; delete_reason: string }
) {
const res = await fetchWithRefresh(`/api/posts/${postId}/comments/${commentId}`, {
method: "DELETE",
headers: clientHeaders({ "Content-Type": "application/json" }),
body: JSON.stringify({
delete_type: opts.delete_type || "",
delete_reason: opts.delete_reason || "",
}),
});
return res.json();
}
/** 恢复软删评论(自删作者或版主) */
export async function apiRestoreComment(postId: string, commentId: number) {
const res = await fetchWithRefresh(`/api/posts/${postId}/comments/${commentId}/restore`, {
method: "PUT",
headers: clientHeaders(),
});
return res.json();
@@ -1735,8 +1764,10 @@ export const apiAdminRestorePost = (id: number) =>
contentAction(`/api/admin/content/posts/${id}/restore`, "PUT");
export const apiAdminPurgePost = (id: number) =>
contentAction(`/api/admin/content/posts/${id}/purge`, "DELETE");
export const apiAdminSoftDeleteComment = (id: number) =>
contentAction(`/api/admin/content/comments/${id}`, "DELETE");
export const apiAdminSoftDeleteComment = (
id: number,
opts: { delete_type: string; delete_reason: string }
) => contentAction(`/api/admin/content/comments/${id}`, "DELETE", opts);
export const apiAdminRestoreComment = (id: number) =>
contentAction(`/api/admin/content/comments/${id}/restore`, "PUT");
export const apiAdminPurgeComment = (id: number) =>