import React, { useEffect, useState } from 'react' import { useSelector, useDispatch } from 'react-redux' import { Spin } from 'antd' import type { AppDispatch } from '../store/store' import { login, verifyToken, restoreAuthState, clearError, clearAuthState, selectIsAuthenticated, selectAuthLoading, selectAuthError, selectToken } from '../store/slices/authSlice' import LoginPage from './LoginPage' import InstallPage from './InstallPage' import apiClient from '../services/apiClient' interface AuthGuardProps { children: React.ReactNode } /** * 认证守卫组件 * 负责验证用户登录状态,未登录时显示登录页面 */ const AuthGuard: React.FC = ({ children }) => { const dispatch = useDispatch() const isAuthenticated = useSelector(selectIsAuthenticated) const authLoading = useSelector(selectAuthLoading) const authError = useSelector(selectAuthError) const token = useSelector(selectToken) const [isInitializing, setIsInitializing] = useState(true) const [loginError, setLoginError] = useState(null) const [systemInitialized, setSystemInitialized] = useState(null) // 调试:监听认证状态变化 useEffect(() => { console.log('🔐 AuthGuard - 认证状态变化:', { isAuthenticated, authLoading, token: token ? '***' : null, isInitializing, systemInitialized }) }, [isAuthenticated, authLoading, token, isInitializing, systemInitialized]) // 组件挂载时检查系统初始化状态 useEffect(() => { const initializeAuth = async () => { try { console.log('🔐 检查系统初始化状态...') // 首先检查系统是否已初始化 // const initResult = await apiClient.get('/') const initResult = await apiClient.get('/api/auth/check-initialization') if (initResult.success) { setSystemInitialized(initResult.isInitialized) console.log(`🔐 系统初始化状态: ${initResult.isInitialized ? '已初始化' : '未初始化'}`) // 如果系统已初始化,继续认证流程 if (initResult.isInitialized) { console.log('🔐 初始化认证状态...') // 先尝试从本地存储恢复状态 dispatch(restoreAuthState()) // 等待一个tick让状态更新 await new Promise(resolve => setTimeout(resolve, 0)) // 获取恢复后的token const currentToken = localStorage.getItem('auth_token') if (currentToken) { console.log('🔐 找到本地token,验证有效性...') // 验证token是否仍然有效 try { const result = await dispatch(verifyToken(currentToken)) if (verifyToken.fulfilled.match(result)) { console.log('✅ Token验证成功') } else { console.log('❌ Token验证失败:', result.payload) setLoginError('登录已过期,请重新登录') } } catch (error) { console.log('❌ Token验证出错:', error) setLoginError('登录验证失败,请重新登录') } } else { console.log('🔐 未找到本地token') } } } else { console.error('检查系统初始化状态失败') setSystemInitialized(false) // 默认为未初始化 } } catch (error) { console.error('初始化检查失败:', error) setSystemInitialized(false) // 出错时默认为未初始化 } finally { setIsInitializing(false) } } initializeAuth() }, [dispatch]) // 监听token过期事件 useEffect(() => { const handleTokenExpired = () => { console.log('🔐 Token过期,清除认证状态') dispatch(clearAuthState()) setLoginError('登录已过期,请重新登录') } window.addEventListener('auth:token-expired', handleTokenExpired) return () => { window.removeEventListener('auth:token-expired', handleTokenExpired) } }, [dispatch]) // 处理登录 const handleLogin = async (username: string, password: string) => { try { console.log('🔐 尝试登录:', username) setLoginError(null) dispatch(clearError()) const result = await dispatch(login({ username, password })) if (login.fulfilled.match(result)) { console.log('✅ 登录成功') setLoginError(null) } else if (login.rejected.match(result)) { const errorMessage = result.payload || '登录失败' console.log('❌ 登录失败:', errorMessage) setLoginError(errorMessage) throw new Error(errorMessage) } } catch (error: any) { console.error('登录过程出错:', error) throw error // 重新抛出错误,让LoginPage显示加载状态 } } // 清除登录错误 useEffect(() => { if (authError && authError !== loginError) { setLoginError(authError) } }, [authError, loginError]) // 处理安装完成 const handleInstallComplete = () => { console.log('🔐 安装完成,刷新初始化状态') setSystemInitialized(true) setLoginError(null) } // 初始化加载中 if (isInitializing || systemInitialized === null) { return (
) } // 系统未初始化,显示安装页面 if (!systemInitialized) { return ( ) } // 系统已初始化但未登录,显示登录页面 if (!isAuthenticated) { return ( ) } // 已登录,显示主应用 return <>{children} } export default AuthGuard