"use client"; import { useRouter } from "next/navigation"; import { useEffect, useState, type ReactNode } from "react"; import { AdminAuthCheckingScreen } from "@/components/admin/admin-auth-checking"; import { verifyStoredAdminSession } from "@/lib/admin-session-verify"; import { useAdminSessionStore } from "@/stores/admin-session"; import { readToken } from "@/stores/admin-token"; type ShellAuthGateProps = { children: ReactNode; }; type GateStatus = "pending" | "authed" | "guest"; function hasAdminToken(bearerToken: string | null): boolean { const token = bearerToken ?? readToken(); return token != null && token.trim() !== ""; } /** * Shell 路由守卫:无 Token 或 `/auth/me` 校验失败时跳转登录页。 */ export function ShellAuthGate({ children }: ShellAuthGateProps) { const router = useRouter(); const bearerToken = useAdminSessionStore((s) => s.bearerToken); const [status, setStatus] = useState("pending"); const setShellAuthPending = useAdminSessionStore((s) => s.setShellAuthPending); useEffect(() => { let cancelled = false; setShellAuthPending(true); async function run() { if (!hasAdminToken(bearerToken)) { if (!cancelled) { setStatus("guest"); } return; } if (!cancelled) { setStatus("pending"); } const ok = await verifyStoredAdminSession(); if (cancelled) { return; } if (ok) { setStatus("authed"); return; } setStatus("guest"); } void run().finally(() => { if (!cancelled) { setShellAuthPending(false); } }); return () => { cancelled = true; setShellAuthPending(false); }; }, [bearerToken, setShellAuthPending]); useEffect(() => { if (status === "guest") { router.replace("/admin/login"); } }, [status, router]); if (status === "pending") { return ; } if (status === "guest") { return null; } return children; }