blob: 2764f5ae1c750740ea72e61282a71c987e31109b [file] [log] [blame] [edit]
// src/routes/ProtectedRoute.tsx
import React, { useEffect, useState } from 'react';
import { useAppSelector, useAppDispatch } from '../store/hooks';
import { useNavigate } from 'react-router';
import { refreshToken } from '../feature/auth/authSlice';
import { Spin } from 'antd';
interface ProtectedRouteProps {
children: React.ReactNode;
}
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children }) => {
const { isAuth, token } = useAppSelector((state) => state.auth);
const navigate = useNavigate();
const dispatch = useAppDispatch();
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const tryRefreshToken = async () => {
// 如果没有token,直接跳转到登录页
if (!token) {
navigate('/login', { replace: true });
return;
}
// 如果有token但未认证,尝试刷新token
if (!isAuth && token) {
setIsLoading(true);
try {
await dispatch(refreshToken(token)).unwrap();
} catch (error) {
console.error('Token refresh failed:', error);
navigate('/login', { replace: true });
} finally {
setIsLoading(false);
}
}
};
tryRefreshToken();
}, [isAuth, token, dispatch, navigate]);
// 显示加载状态
if (isLoading) {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh'
}}>
<Spin size="large" tip="验证身份中..." />
</div>
);
}
// 如果没有token,返回null(会触发导航)
if (!token) {
return null;
}
// 如果已认证,渲染children
if (isAuth) {
return <>{children}</>;
}
// 如果有token但还在验证中,显示加载状态
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh'
}}>
<Spin size="large" tip="验证身份中..." />
</div>
);
};
export default ProtectedRoute;