/**
|
* @author 韩天尊
|
* @time 2024-01-15
|
* @version 1.0.0
|
* @description 路由守卫组件,检查用户登录状态
|
*/
|
import React, { useEffect } from 'react';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useAppContext } from '../context/AppContext';
|
|
interface ProtectedRouteProps {
|
children: React.ReactNode;
|
}
|
|
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children }) => {
|
const navigate = useNavigate();
|
const location = useLocation();
|
const { state } = useAppContext();
|
const [isInitialized, setIsInitialized] = React.useState(false);
|
|
// 检查是否已完成初始化
|
useEffect(() => {
|
const token = localStorage.getItem('token');
|
const user = localStorage.getItem('user');
|
|
// 如果有token和user信息,说明可能正在初始化,等待一下
|
if (token && user) {
|
const timer = setTimeout(() => {
|
setIsInitialized(true);
|
}, 200);
|
return () => clearTimeout(timer);
|
} else {
|
// 没有token和user,立即标记为已初始化
|
setIsInitialized(true);
|
}
|
}, []);
|
|
useEffect(() => {
|
// 只有在初始化完成后才进行跳转检查
|
if (isInitialized && !state.user && location.pathname !== '/login') {
|
navigate('/login', { replace: true });
|
}
|
}, [isInitialized, state.user, location.pathname, navigate]);
|
|
// 如果未初始化完成,显示加载状态
|
if (!isInitialized) {
|
return (
|
<div style={{
|
display: 'flex',
|
justifyContent: 'center',
|
alignItems: 'center',
|
height: '100vh',
|
background: '#f5f5f5'
|
}}>
|
<div style={{ textAlign: 'center', color: '#666' }}>
|
<div style={{
|
width: '40px',
|
height: '40px',
|
border: '3px solid #f3f3f3',
|
borderTop: '3px solid #ff6b6b',
|
borderRadius: '50%',
|
animation: 'spin 1s linear infinite',
|
margin: '0 auto 20px'
|
}}></div>
|
<p>加载中...</p>
|
</div>
|
</div>
|
);
|
}
|
|
// 如果用户未登录,不渲染子组件
|
if (!state.user && location.pathname !== '/login') {
|
return null;
|
}
|
|
return <>{children}</>;
|
};
|
|
export default ProtectedRoute;
|