'use client'; import { useEffect } from 'react'; import { usePathname, useRouter, useSearchParams } from 'next/navigation'; import { buildAuthPortalUrl } from '@/lib/auth-portal'; import { AUTH_CLEARED_EVENT, clearTokens, getMe, isLoggedIn } from '@/lib/api'; import { pickAppText } from '@/lib/i18n/core'; import { useAppI18n } from '@/lib/i18n/provider'; import { useChatStore } from '@/lib/store'; export default function AuthGuard({ children, minHeightClassName = 'min-h-[calc(100vh-3.5rem)]', }: { children: React.ReactNode; minHeightClassName?: string; }) { const { locale } = useAppI18n(); const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const user = useChatStore((s) => s.user); const setUser = useChatStore((s) => s.setUser); const setIsAuthLoading = useChatStore((s) => s.setIsAuthLoading); const isAuthLoading = useChatStore((s) => s.isAuthLoading); useEffect(() => { let cancelled = false; const init = async () => { if (!isLoggedIn()) { setUser(null); if (!cancelled) { setIsAuthLoading(false); } return; } if (useChatStore.getState().user) { if (!cancelled) { setIsAuthLoading(false); } return; } setIsAuthLoading(true); try { const me = await getMe(); if (cancelled) return; setUser(me); } catch { clearTokens(); if (cancelled) return; setUser(null); } finally { if (!cancelled) { setIsAuthLoading(false); } } }; init(); return () => { cancelled = true; }; }, [setIsAuthLoading, setUser]); useEffect(() => { const handleAuthCleared = () => { setUser(null); setIsAuthLoading(false); }; window.addEventListener(AUTH_CLEARED_EVENT, handleAuthCleared); return () => { window.removeEventListener(AUTH_CLEARED_EVENT, handleAuthCleared); }; }, [setIsAuthLoading, setUser]); useEffect(() => { if (isAuthLoading) { return; } const isPublicRoute = pathname === '/login' || pathname === '/register'; const loggedIn = isLoggedIn(); if (!loggedIn && !isPublicRoute) { const search = searchParams?.toString(); const nextPath = search ? `${pathname}?${search}` : pathname; window.location.replace(buildAuthPortalUrl('/login', nextPath)); return; } if (loggedIn && user && isPublicRoute) { router.replace('/'); } }, [isAuthLoading, pathname, router, searchParams, user]); if (isAuthLoading) { return (
{pickAppText(locale, '加载中...', 'Loading...')}
); } const isPublicRoute = pathname === '/login' || pathname === '/register'; if (!isPublicRoute && (!isLoggedIn() || !user)) { return null; } return <>{children}; }