import { HeartHandshake, Sparkles, UserRoundCheck, UserRoundPlus } from "lucide-react"; import { type FormEvent, useEffect, useMemo, useState } from "react"; import { platformApiClient } from "../api/client"; import type { UserCreateRequest, UserResponse, UserStatus } from "../api/types"; import { EmptyState, ErrorState, LoadingState, ResultBadge } from "../components/StateViews"; import { PageFrame } from "../components/PageFrame"; import type { PageComponentProps } from "../contracts/page"; import { userAccess } from "../contracts/shell"; import { isPlatformAdmin } from "../contracts/workspace"; import { cx } from "../utils/classes"; const roleOptions = [ { value: "platform-admin", label: "平台管理员" }, { value: "server-owner", label: "服主" }, { value: "server-admin", label: "服务器管理员" } ]; const statusOptions: Array<{ value: UserStatus; label: string }> = [ { value: "active", label: "启用" }, { value: "pending", label: "待审核" }, { value: "disabled", label: "停用" } ]; const fallbackUsers: UserResponse[] = userAccess.map((user, index) => ({ id: user.id, displayName: user.displayName, email: `${user.id}@local.example.test`, status: user.status, roles: user.roles, profile: { phone: index === 0 ? "13800000000" : "", qq: index === 0 ? "10001" : "", contactNote: user.review }, createdAt: "2026-07-03T00:00:00Z", updatedAt: "2026-07-03T00:00:00Z" })); export function UsersPage({ session, operations }: PageComponentProps) { const [users, setUsers] = useState(fallbackUsers); const [loading, setLoading] = useState(true); const [source, setSource] = useState<"api" | "local">("local"); const [loadError, setLoadError] = useState(""); const [result, setResult] = useState<{ status: "pending" | "succeeded" | "failed"; label: string }>(); const [draft, setDraft] = useState({ displayName: "", email: "", roles: ["server-admin"], status: "pending", profile: { phone: "", qq: "", contactNote: "" } }); useEffect(() => { let cancelled = false; void platformApiClient .listUsers() .then((response) => { if (!cancelled) { setUsers(response.items); setSource("api"); setLoadError(""); } }) .catch(() => { if (!cancelled) { setUsers(fallbackUsers); setSource("local"); setLoadError("账号 API 加载失败,当前显示本地样例;创建与状态更新仍会尝试平台 API。"); } }) .finally(() => { if (!cancelled) { setLoading(false); } }); return () => { cancelled = true; }; }, []); const counts = useMemo( () => ({ active: users.filter((user) => user.status === "active").length, pending: users.filter((user) => user.status === "pending").length, roleCount: new Set(users.flatMap((user) => user.roles)).size }), [users] ); async function createUser(event: FormEvent) { event.preventDefault(); const request: UserCreateRequest = { ...draft, displayName: draft.displayName.trim(), email: draft.email?.trim(), roles: draft.roles.length ? draft.roles : ["server-admin"], profile: { phone: draft.profile?.phone?.trim(), qq: draft.profile?.qq?.trim(), contactNote: draft.profile?.contactNote?.trim() } }; const operationId = operations.begin({ intent: "创建用户", targetKind: "platform", targetId: "users", requester: session.displayName }); setResult({ status: "pending", label: `正在创建用户 ${operationId}` }); try { const created = await platformApiClient.createUser(request); setUsers((current) => [created, ...current.filter((user) => user.id !== created.id)]); operations.succeed(operationId, `用户已创建:${created.id}`); setSource("api"); setLoadError(""); setResult({ status: "succeeded", label: `已创建 ${created.displayName}` }); } catch (error) { operations.fail(operationId, error instanceof Error ? error.message : "用户创建失败"); setResult({ status: "failed", label: "用户创建失败,未写入数据库" }); } setDraft({ displayName: "", email: "", roles: ["server-admin"], status: "pending", profile: { phone: "", qq: "", contactNote: "" } }); } async function setUserStatus(user: UserResponse, status: UserStatus) { const operationId = operations.begin({ intent: "更新用户状态", targetKind: "platform", targetId: user.id, requester: session.displayName }); setResult({ status: "pending", label: `正在更新 ${user.displayName}` }); try { const updated = await platformApiClient.updateUser(user.id, { status }); setUsers((current) => current.map((item) => (item.id === updated.id ? updated : item))); operations.succeed(operationId, `用户状态已更新:${updated.id}`); setSource("api"); setLoadError(""); setResult({ status: "succeeded", label: `${updated.displayName} 已${statusLabel(updated.status)}` }); } catch (error) { operations.fail(operationId, error instanceof Error ? error.message : "用户状态更新失败"); setResult({ status: "failed", label: "状态更新失败,未写入数据库" }); } } function toggleRole(role: string) { setDraft((current) => { const nextRoles = current.roles.includes(role) ? current.roles.filter((item) => item !== role) : [...current.roles, role]; return { ...current, roles: nextRoles }; }); } if (!isPlatformAdmin(session)) { return (
当前账号不能管理用户

服务器用户不会看到用户管理导航;直接访问该页时应返回角色默认工作区。

); } return (
{loading && } {loadError && }

创建用户

{loading ? : result && }
{roleOptions.map((role) => ( ))}

访问列表

{source === "api" ? "平台数据" : "本地样例 / 待同步"}
{users.length === 0 ? ( ) : (
{users.map((user) => (
{user.displayName} {user.email ?? user.id}
{statusLabel(user.status)} {user.roles.map(roleLabel).join(" / ")} {profileSummary(user)}
{statusOptions.map((option) => ( ))}
))}
)}
); } function statusLabel(status: UserStatus): string { return status === "active" ? "启用" : status === "pending" ? "待审核" : "停用"; } function statusClass(status: UserStatus): string { return status === "active" ? "status-active" : status === "pending" ? "status-pending" : "status-disabled"; } function roleLabel(role: string): string { const matched = roleOptions.find((option) => option.value === role || option.value.replace("-", "") === role.toLowerCase()); return matched?.label ?? role; } function profileSummary(user: UserResponse): string { const parts = [user.profile?.phone, user.profile?.qq ? `QQ ${user.profile.qq}` : undefined, user.profile?.contactNote].filter(Boolean); return parts.length > 0 ? parts.join(" · ") : "暂无联系方式"; }