feat: 交付官方 Docker 运行时,外观改背景图并下线自定义 CSS/JS

站点/后台分轨背景与用户列表排序一并落地;生产 CORS 改走 SITE_URL,健康检查带版本号。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-18 05:27:33 +08:00
parent 5f7193042f
commit d784b0ea7a
68 changed files with 2588 additions and 768 deletions

View File

@@ -5,14 +5,20 @@ 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 } from "./UsersAdmin";
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 }>;
searchParams: Promise<{ q?: string; filter?: string; page?: string; sort?: string; order?: string }>;
}
// 筛选项映射为后端查询参数:管理团队走 role=staff,封禁走 status,其余不过滤
@@ -28,6 +34,8 @@ export default async function AdminUsersPage({ searchParams }: UsersPageProps) {
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);
@@ -40,7 +48,7 @@ export default async function AdminUsersPage({ searchParams }: UsersPageProps) {
let initial: AdminUsersResponse | null = null;
let initError = "";
try {
initial = await fetchAdminUsers({ page, q, ...filterToQuery(filter) }, cookie || undefined);
initial = await fetchAdminUsers({ page, q, sort, order, ...filterToQuery(filter) }, cookie || undefined);
} catch (e) {
initError = e instanceof Error ? e.message : "获取用户列表失败";
}
@@ -49,7 +57,7 @@ export default async function AdminUsersPage({ searchParams }: UsersPageProps) {
<UsersAdmin
initial={initial}
initError={initError}
initialQuery={{ q, filter, page }}
initialQuery={{ q, filter, page, sort, order }}
currentUserId={me.user?.id ?? 0}
currentUserRole={me.user?.role ?? ""}
/>