"use client";
import { useCallback, useEffect, useState } from "react";
import Link from "next/link";
import {
ArrowLeft,
ChevronLeft,
ChevronRight,
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";
type TabKey = "posts" | "comments" | "messages";
const TABS: { key: TabKey; label: string; icon: React.ReactNode }[] = [
{ key: "posts", label: "帖子", icon: },
{ key: "comments", label: "评论", icon: },
{ key: "messages", label: "私信与群消息", icon: },
];
const PAGE_SIZE = 20;
function StatusChip({
status,
deleted,
recalled,
}: {
status?: string;
deleted?: boolean;
recalled?: boolean;
}) {
const chips: { label: string; color: string; soft: string }[] = [];
if (deleted) chips.push({ label: "已删除", color: "var(--danger)", soft: "var(--danger-soft)" });
if (recalled) chips.push({ label: "已撤回", color: "var(--ink-3)", soft: "var(--tint)" });
if (status === "pending") chips.push({ label: "待审", color: "var(--gold)", soft: "var(--gold-soft)" });
if (status === "rejected") chips.push({ label: "已驳回", color: "var(--danger)", soft: "var(--danger-soft)" });
if (status === "published" && !deleted) {
chips.push({ label: "已发布", color: "var(--ok)", soft: "var(--ok-soft)" });
}
if (chips.length === 0 && !recalled) {
chips.push({ label: "正常", color: "var(--ink-3)", soft: "var(--tint)" });
}
return (
{chips.map((c) => (
{c.label}
))}
);
}
function Pager({
page,
total,
onChange,
loading,
}: {
page: number;
total: number;
onChange: (p: number) => void;
loading?: boolean;
}) {
const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
if (pages <= 1) return null;
return (
{page} / {pages}
);
}
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;
};
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}
))}
{TABS.map((t) => {
const active = tab === t.key;
return (
);
})}
{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)}
))}
);
}