"use client"; import { useCallback, useEffect, useState } from "react"; import Link from "next/link"; import { ArrowLeft, ExternalLink, FileText, Loader2, MessageCircle, MessagesSquare, } from "lucide-react"; import { apiAdminUserAuditComments, apiAdminUserAuditMessages, apiAdminUserAuditPosts, type AdminAuditCommentItem, type AdminAuditMessageItem, type AdminAuditPostItem, type AdminUserAuditProfile, } from "@/lib/api"; import { formatDate, formatRelative } from "@/lib/format"; import Avatar from "@/components/Avatar"; import RoleBadge from "@/components/RoleBadge"; import { AdminEmpty, AdminPager, AdminSegmented, AdminStatusChip, type AdminStatusTone, } from "@/components/admin"; type TabKey = "posts" | "comments" | "messages"; const PAGE_SIZE = 20; /** 内容/消息状态粒:可叠加(如已删除 + 待审) */ function StatusChips({ status, deleted, recalled, }: { status?: string; deleted?: boolean; recalled?: boolean; }) { const chips: { label: string; tone: AdminStatusTone }[] = []; if (deleted) chips.push({ label: "已删除", tone: "danger" }); if (recalled) chips.push({ label: "已撤回", tone: "muted" }); if (status === "pending") chips.push({ label: "待审", tone: "warn" }); if (status === "rejected") chips.push({ label: "已驳回", tone: "danger" }); if (status === "published" && !deleted) { chips.push({ label: "已发布", tone: "ok" }); } if (chips.length === 0 && !recalled) { chips.push({ label: "正常", tone: "muted" }); } return ( {chips.map((c) => ( {c.label} ))} ); } export default function UserAuditClient({ userId, initial, }: { userId: number; initial: AdminUserAuditProfile; }) { const [profile] = useState(initial); const [tab, setTab] = useState("posts"); const [page, setPage] = useState(1); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [posts, setPosts] = useState([]); const [comments, setComments] = useState([]); const [messages, setMessages] = useState([]); const [total, setTotal] = useState(0); const u = profile.user; const load = useCallback( async (t: TabKey, p: number) => { setLoading(true); setError(""); try { if (t === "posts") { const res = await apiAdminUserAuditPosts(userId, p); setPosts(res.items || []); setTotal(res.total); } else if (t === "comments") { const res = await apiAdminUserAuditComments(userId, p); setComments(res.items || []); setTotal(res.total); } else { const res = await apiAdminUserAuditMessages(userId, p); setMessages(res.items || []); setTotal(res.total); } } catch (e) { setError(e instanceof Error ? e.message : "加载失败"); } finally { setLoading(false); } }, [userId] ); useEffect(() => { load(tab, page); }, [tab, page, load]); const switchTab = (t: TabKey) => { setTab(t); setPage(1); }; const tabCount = (t: TabKey) => { if (t === "posts") return profile.posts_total; if (t === "comments") return profile.comments_total; return profile.messages_total; }; const emptyIcon = tab === "posts" ? ( ) : tab === "comments" ? ( ) : ( ); return (
返回用户列表

{u.nickname}

{u.banned && 已封禁}

@{u.username}

注册于 {formatDate(u.created_at)} · 已发布帖 {profile.published_posts} / 评{" "} {profile.published_comments}

主页
{[ { label: "全部帖子", value: profile.posts_total }, { label: "全部评论", value: profile.comments_total }, { label: "全部消息", value: profile.messages_total }, ].map((c) => (

{c.value.toLocaleString("zh-CN")}

{c.label}

))}
ariaLabel="内容分类" value={tab} onChange={switchTab} options={[ { key: "posts", label: "帖子", icon: , count: tabCount("posts"), }, { key: "comments", label: "评论", icon: , count: tabCount("comments"), }, { key: "messages", label: "私信与群消息", icon: , count: tabCount("messages"), }, ]} />
{error && (

{error}

)} {!error && loading && posts.length + comments.length + messages.length === 0 && (
)} {!error && !loading && total === 0 && ( )} {tab === "posts" && posts.map((p) => (
{p.board_name && ( {p.board_name} )}
{p.deleted ? (

{p.title || "(无标题)"}

) : ( {p.title || "(无标题)"} )} {p.content && (

{p.content}

)}
{formatRelative(p.created_at)}
))} {tab === "comments" && comments.map((c) => (
{c.deleted ? ( 帖子 #{c.post_id} ) : ( 帖子 #{c.post_id} )}

{c.content || "(空)"}

{formatRelative(c.created_at)}
))} {tab === "messages" && messages.map((m) => (
{m.room_name} {m.room_type === "direct" ? " · 私聊" : m.room_type === "group" ? " · 群聊" : ""}

{m.content || "(空)"}

{formatRelative(m.created_at)}
))}
); }