import type { Metadata } from "next"; import { cookies } from "next/headers"; import { authCookieHeader } from "@/lib/cookies"; import { fetchAdminUsers, type AdminUsersResponse } from "@/lib/api"; import { getMeCached } from "@/lib/serverData"; import { isSuperOrOwner } from "@/lib/roles"; import Forbidden from "../Forbidden"; import UsersAdmin, { type UserFilter, type UserSortKey } from "./UsersAdmin"; export const metadata: Metadata = { title: "用户管理", }; const SORT_KEYS = ["id", "role", "status", "points", "last_login", "counts", "created_at", "online"] as const; function parseSort(raw?: string): UserSortKey { return (SORT_KEYS as readonly string[]).includes(raw || "") ? (raw as UserSortKey) : "id"; } interface UsersPageProps { searchParams: Promise<{ q?: string; filter?: string; page?: string; sort?: string; order?: string }>; } // 筛选项映射为后端查询参数:管理团队走 role=staff,封禁走 status,其余不过滤 function filterToQuery(filter: UserFilter): { role?: string; status?: string } { if (filter === "staff") return { role: "staff" }; if (filter === "banned") return { status: "banned" }; return {}; } // 管理员鉴权由 app/admin/layout.tsx 统一承担;列表首屏 SSR 直出,F5 无骨架闪动 export default async function AdminUsersPage({ searchParams }: UsersPageProps) { const sp = await searchParams; const q = sp.q?.trim() || ""; const filter: UserFilter = sp.filter === "staff" || sp.filter === "banned" ? sp.filter : "all"; const page = Math.max(1, parseInt(sp.page || "1", 10) || 1); const sort = parseSort(sp.sort); const order: "asc" | "desc" = sp.order === "asc" ? "asc" : "desc"; const cookie = authCookieHeader(await cookies()); const me = await getMeCached(cookie || undefined); // 仅超级管理员与站长可管理用户与角色 if (!me.user || !isSuperOrOwner(me.user.role)) { return ; } let initial: AdminUsersResponse | null = null; let initError = ""; try { initial = await fetchAdminUsers({ page, q, sort, order, ...filterToQuery(filter) }, cookie || undefined); } catch (e) { initError = e instanceof Error ? e.message : "获取用户列表失败"; } return ( ); }