import { useAuth } from '@/hooks/use-auth'; import { authEvents } from '@/lib/api/client'; import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'; import { LoginModal } from './login-modal'; export interface AuthContextType { requireAuth: (callback?: () => void) => boolean; showLoginModal: boolean; setShowLoginModal: (show: boolean) => void; pendingCallback: (() => void) | null; } const AuthContext = createContext(undefined); export { AuthContext }; export function AuthProvider({ children }: { children: React.ReactNode }) { const { isAuthenticated, isLoading } = useAuth(); const [showLoginModal, setShowLoginModal] = useState(false); const [pendingCallback, setPendingCallback] = useState<(() => void) | null>(null); // 认证拦截函数 const requireAuth = useCallback((callback?: () => void): boolean => { if (isLoading) { // 如果认证状态还在加载中,不执行任何操作 return false; } if (!isAuthenticated) { // 未登录,保存回调并显示登录Modal setPendingCallback(() => callback || null); setShowLoginModal(true); return false; } // 已登录,执行回调 if (callback) { callback(); } return true; }, [isAuthenticated, isLoading]); // 监听登录状态变化 useEffect(() => { if (isAuthenticated && showLoginModal) { // 登录成功,自动关闭Modal并执行回调 if (pendingCallback) { pendingCallback(); setPendingCallback(null); } setShowLoginModal(false); } }, [isAuthenticated, showLoginModal, pendingCallback]); // 监听 401 未授权事件 useEffect(() => { const unsubscribe = authEvents.onUnauthorized(() => { if (!isLoading && !isAuthenticated) { setShowLoginModal(true); } }); return unsubscribe; }, [isLoading, isAuthenticated]); const value = { requireAuth, showLoginModal, setShowLoginModal, pendingCallback, }; return ( {children} { setShowLoginModal(false); setPendingCallback(null); }} /> ); } export function useAuthGuard() { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuthGuard must be used within an AuthProvider'); } return context; }