feat(moderation): 帖评删除占位感知与硬删清场
管理删帖须填类型与理由并展示专用页;评论软删占位、版主可硬删不占楼。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { apiMe, apiDeletePost, apiTogglePin, apiToggleRecommend, apiAdminApprove
|
||||
import { canModerateBoard, isAdminOrAbove } from "@/lib/roles";
|
||||
import { toast } from "@/lib/toast";
|
||||
import ConfirmDialog from "@/components/ConfirmDialog";
|
||||
import StaffDeletePostModal from "@/components/StaffDeletePostModal";
|
||||
|
||||
interface PostActionsProps {
|
||||
postId: string;
|
||||
@@ -17,6 +18,8 @@ interface PostActionsProps {
|
||||
recommended: boolean;
|
||||
/** 帖子审核状态:pending 时对可审者显示「通过评审」 */
|
||||
status: string;
|
||||
/** 供删除确认展示 */
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export default function PostActions({
|
||||
@@ -26,6 +29,7 @@ export default function PostActions({
|
||||
pinned,
|
||||
recommended,
|
||||
status,
|
||||
title,
|
||||
}: PostActionsProps) {
|
||||
const router = useRouter();
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
@@ -35,6 +39,7 @@ export default function PostActions({
|
||||
const [isRecommended, setIsRecommended] = useState(recommended);
|
||||
const [acting, setActing] = useState(false);
|
||||
const [confirmDelete, setConfirmDelete] = useState(false);
|
||||
const [staffDeleteOpen, setStaffDeleteOpen] = useState(false);
|
||||
const menuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -43,7 +48,6 @@ export default function PostActions({
|
||||
.catch(() => setUser(null));
|
||||
}, []);
|
||||
|
||||
// 点击外部 / Esc 关闭菜单(与通知铃铛同一交互模式)
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
const onDown = (e: MouseEvent) => {
|
||||
@@ -60,17 +64,20 @@ export default function PostActions({
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
// 作者本人或有该板块审核权的管理团队可管理;置顶/加精仅管理员及以上
|
||||
const canManage = !!user && (user.id === authorId || canModerateBoard(user, boardId));
|
||||
const isAdmin = !!user && isAdminOrAbove(user.role);
|
||||
const canApprove = !!user && status === "pending" && canModerateBoard(user, boardId);
|
||||
// staff 删他人帖:走类型+理由;作者自删:简单确认
|
||||
const staffDeletingOther =
|
||||
!!user && user.id !== authorId && canModerateBoard(user, boardId);
|
||||
|
||||
const handleDelete = async () => {
|
||||
const runDelete = async (opts?: { delete_type?: string; delete_reason?: string }) => {
|
||||
setDeleting(true);
|
||||
try {
|
||||
const res = await apiDeletePost(postId);
|
||||
const res = await apiDeletePost(postId, opts);
|
||||
if (res.message) {
|
||||
setConfirmDelete(false);
|
||||
setStaffDeleteOpen(false);
|
||||
router.push("/");
|
||||
toast("帖子已删除", "ok");
|
||||
} else {
|
||||
@@ -217,7 +224,8 @@ export default function PostActions({
|
||||
role="menuitem"
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
setConfirmDelete(true);
|
||||
if (staffDeletingOther) setStaffDeleteOpen(true);
|
||||
else setConfirmDelete(true);
|
||||
}}
|
||||
disabled={deleting}
|
||||
className={`${itemCls} items-center`}
|
||||
@@ -232,13 +240,21 @@ export default function PostActions({
|
||||
<ConfirmDialog
|
||||
open={confirmDelete}
|
||||
title="删除帖子"
|
||||
message="确定要删除这篇帖子吗?此操作不可恢复。"
|
||||
message="确定要删除这篇帖子吗?列表将不再展示,打开原链接会提示已删除。"
|
||||
confirmLabel="确认删除"
|
||||
danger
|
||||
busy={deleting}
|
||||
onConfirm={handleDelete}
|
||||
onConfirm={() => void runDelete()}
|
||||
onCancel={() => setConfirmDelete(false)}
|
||||
/>
|
||||
|
||||
<StaffDeletePostModal
|
||||
open={staffDeleteOpen}
|
||||
title={title}
|
||||
busy={deleting}
|
||||
onClose={() => setStaffDeleteOpen(false)}
|
||||
onConfirm={(opts) => void runDelete(opts)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user