Files
lotteryAdmin/src/components/admin/auth-gate.tsx
kang a550c418e5 refactor(layout, i18n, admin): 优化布局结构与多语言支持
调整 AdminShell 组件的子组件顺序,提升代码可读性。更新 admin-breadcrumb 组件,简化导航标签翻译逻辑,确保多语言支持的一致性。重构 admin-language-switcher 组件,优化语言切换的用户体验,增强界面交互性。更新多语言配置,新增登录界面的副标题,提升用户体验。
2026-05-30 17:46:27 +08:00

89 lines
2.0 KiB
TypeScript

"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<GateStatus>("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 <AdminAuthCheckingScreen variant="shell" />;
}
if (status === "guest") {
return null;
}
return children;
}