import { RefreshCw, ShieldAlert, UsersRound } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { platformApiClient } from "../api/client"; import type { GamePlayerProfileResponse, GamePlayerResponse } from "../api/types"; import { ErrorState, LoadingState } from "./StateViews"; type State = { status: "loading" } | { status: "error"; reason: string } | { status: "ready"; players: GamePlayerResponse[]; selected?: GamePlayerProfileResponse }; export function GamePlayerIntelligencePanel({ serverInstanceId }: { serverInstanceId: string }) { const [state, setState] = useState({ status: "loading" }); const load = useCallback(async () => { setState({ status: "loading" }); try { const result = await platformApiClient.listGamePlayers(serverInstanceId); setState({ status: "ready", players: result.items }); } catch (error) { setState({ status: "error", reason: error instanceof Error ? error.message : "玩家档案读取失败。" }); } }, [serverInstanceId]); useEffect(() => { void load(); }, [load]); async function select(player: GamePlayerResponse) { try { const selected = await platformApiClient.getGamePlayerProfile(serverInstanceId, player.id); setState((current) => current.status === "ready" ? { ...current, selected } : current); } catch (error) { setState({ status: "error", reason: error instanceof Error ? error.message : "玩家档案读取失败。" }); } } if (state.status === "loading") return ; if (state.status === "error") return void load()} />; const profile = state.selected; return

本地玩家档案与登录轨迹

游戏身份独立于平台账号;网络数据仅用于服务器内不可逆关联,绝不展示或持久化原始值。

{state.players.length ? state.players.map((player) => ) :

暂无已投影的成功登录记录。

}
{profile &&

{profile.player.displayName} 的审阅记录

别名 {profile.aliases.length} · 会话 {profile.sessions.length}
别名{profile.aliases.map((alias) => alias.alias).join(" / ") || "无"}
{profile.sessions.slice(0, 10).map((session) =>
会话{formatTime(session.startedAt)} → {session.endedAt ? formatTime(session.endedAt) : "仍在线"} {session.endReason ? `(${session.endReason})` : ""}
)}
{profile.securitySignals.length ? profile.securitySignals.map((signal) =>
) :

未发现需要人工审核的风险信号。

}
{profile.accessAttempts.length > 0 &&

失败尝试:{profile.accessAttempts.length} 条(仅显示结果与时间,不显示网络标识)。

}
}
; } function formatTime(value: string) { const date = new Date(value); return Number.isNaN(date.valueOf()) ? "--" : date.toLocaleString("zh-CN", { hour12: false }); }