diff --git a/src/components/AuthProvider.tsx b/src/components/AuthProvider.tsx index 590ac9b..381e276 100644 --- a/src/components/AuthProvider.tsx +++ b/src/components/AuthProvider.tsx @@ -1,7 +1,11 @@ 'use client'; import { usePathname, useRouter } from 'next/navigation'; -import { useEffect } from 'react'; +import { useCallback, useEffect, useState } from 'react'; + +import { ThemeToggle } from '@/components/ThemeToggle'; + +import { useSite } from './SiteProvider'; interface Props { children: React.ReactNode; @@ -10,37 +14,73 @@ interface Props { export default function AuthProvider({ children }: Props) { const router = useRouter(); const pathname = usePathname(); + const [isAuthenticated, setIsAuthenticated] = useState(null); + const { siteName } = useSite(); + const authenticate = useCallback(async () => { + // 登录页 + if (pathname.startsWith('/login') || pathname.startsWith('/api/login')) { + setIsAuthenticated(true); + return; + } - useEffect(() => { - // 登录页或 API 路径不做校验,避免死循环 - if (pathname.startsWith('/login')) return; - + // 从localStorage获取密码 const password = localStorage.getItem('password'); const fullPath = typeof window !== 'undefined' ? window.location.pathname + window.location.search : pathname; - // 有密码时验证 - (async () => { - try { - const res = await fetch('/api/login', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ password }), - }); + // 没有密码直接跳转 + if (!password) { + router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`); + setIsAuthenticated(false); + return; + } - if (!res.ok) { - // 校验未通过,清理并跳转登录 - localStorage.removeItem('password'); - router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`); - } - } catch (error) { - // 网络错误等也认为未登录 - router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`); - } - })(); + // 尝试认证 + try { + const res = await fetch('/api/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ password }), + }); + + if (!res.ok) throw new Error('认证失败'); + + setIsAuthenticated(true); + } catch (error) { + // 认证失败,清理并跳转登录 + setIsAuthenticated(false); + localStorage.removeItem('password'); + router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`); + } }, [pathname, router]); - return <>{children}; + useEffect(() => { + authenticate(); + }, [pathname, authenticate]); + + // 认证状态未知时显示加载状态 + if (!isAuthenticated) { + return ( +
+
+ +
+
+

+ {siteName} +

+
+
+
+

+ 正在验证您的身份,请稍候... +

+
+
+ ); + } else { + return <>{children}; + } }