"use client"; import { useCallback, useEffect, useState } from "react"; import { ChevronDown, ChevronUp, Pin } from "lucide-react"; import { apiAdminPinnedPosts, apiAdminSavePinOrder, type AdminPinnedPost, } from "@/lib/api"; import AdminPageHeader from "@/components/admin/AdminPageHeader"; import AdminEmpty from "@/components/admin/AdminEmpty"; import { toast } from "@/lib/toast"; interface BoardOpt { id: number; name: string; } interface PinnedAdminProps { boards: BoardOpt[]; /** 管理员及以上:可排全站置顶 */ canGlobal: boolean; } type Level = 1 | 2; export default function PinnedAdmin({ boards, canGlobal }: PinnedAdminProps) { const [level, setLevel] = useState(canGlobal ? 2 : 1); const [boardId, setBoardId] = useState(boards[0]?.id ?? 0); const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); const [busy, setBusy] = useState(false); const [error, setError] = useState(""); const load = useCallback(async (lv: Level, bid: number) => { setLoading(true); setError(""); try { const r = await apiAdminPinnedPosts(lv, lv === 1 ? bid : undefined); setPosts(r.posts ?? []); } catch (e) { setPosts([]); setError(e instanceof Error ? e.message : "获取置顶列表失败"); } finally { setLoading(false); } }, []); useEffect(() => { void load(level, boardId); }, [level, boardId, load]); const switchLevel = (lv: Level) => { if (lv === level) return; setLevel(lv); setPosts([]); }; // 上移/下移:乐观交换后整体保存顺序,失败回滚 const move = async (idx: number, dir: -1 | 1) => { const target = idx + dir; if (target < 0 || target >= posts.length || busy) return; const prev = posts; const next = [...posts]; const tmp = next[idx]; next[idx] = next[target]; next[target] = tmp; setPosts(next); setBusy(true); setError(""); try { await apiAdminSavePinOrder(level, level === 1 ? boardId : 0, next.map((p) => p.id)); } catch (e) { setPosts(prev); setError(e instanceof Error ? e.message : "保存顺序失败"); } finally { setBusy(false); } }; const tabCls = (active: boolean) => `px-3.5 py-2 text-[13px] font-semibold rounded-[var(--r-sm)] transition-colors ${ active ? "" : "hover:bg-[var(--panel-2)]" }`; return (
{error && (
{error}
)} {/* 层级切换 + 板块选择 */}
{canGlobal && ( )}
{level === 1 && ( )}
{loading ? (

加载中…

) : posts.length === 0 ? ( } title={level === 2 ? "暂无全站置顶帖" : "该板块暂无置顶帖"} description="在帖子页的「管理」菜单中可将帖子设为置顶。" /> ) : (
    {posts.map((p, i) => (
  • {i + 1}
    {p.title}

    {p.board_name} · {new Date(p.created_at).toLocaleDateString("zh-CN")}

  • ))}
)}
); }