2025-07-04 15:49:22 +08:00
|
|
|
|
import React, { useEffect } from 'react';
|
|
|
|
|
|
import { useNavigate, useLocation } from 'react-router-dom';
|
2025-07-05 16:34:19 +08:00
|
|
|
|
import { useAuth } from '@/contexts/AuthContext';
|
2025-07-04 15:49:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 不需要登录的公共页面路径
|
|
|
|
|
|
const PUBLIC_PATHS = [
|
|
|
|
|
|
'/login',
|
|
|
|
|
|
'/register',
|
|
|
|
|
|
'/forgot-password',
|
|
|
|
|
|
'/reset-password',
|
|
|
|
|
|
'/404',
|
|
|
|
|
|
'/500'
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
interface ProtectedRouteProps {
|
|
|
|
|
|
children: React.ReactNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default function ProtectedRoute({ children }: ProtectedRouteProps) {
|
|
|
|
|
|
const { isAuthenticated, isLoading } = useAuth();
|
|
|
|
|
|
const navigate = useNavigate();
|
|
|
|
|
|
const location = useLocation();
|
|
|
|
|
|
|
|
|
|
|
|
// 检查当前路径是否是公共页面
|
|
|
|
|
|
const isPublicPath = PUBLIC_PATHS.some(path =>
|
|
|
|
|
|
location.pathname.startsWith(path)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
// 如果正在加载,不进行任何跳转
|
|
|
|
|
|
if (isLoading) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果未登录且不是公共页面,重定向到登录页面
|
|
|
|
|
|
if (!isAuthenticated && !isPublicPath) {
|
|
|
|
|
|
// 保存当前URL,登录后可以重定向回来
|
|
|
|
|
|
const returnUrl = encodeURIComponent(window.location.href);
|
|
|
|
|
|
navigate(`/login?returnUrl=${returnUrl}`, { replace: true });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果已登录且在登录页面,重定向到首页
|
|
|
|
|
|
if (isAuthenticated && location.pathname === '/login') {
|
|
|
|
|
|
navigate('/', { replace: true });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [isAuthenticated, isLoading, location.pathname, navigate, isPublicPath]);
|
|
|
|
|
|
|
|
|
|
|
|
// 如果正在加载,显示加载状态
|
|
|
|
|
|
if (isLoading) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="flex h-screen w-screen items-center justify-center">
|
|
|
|
|
|
<div className="text-gray-500">加载中...</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果未登录且不是公共页面,不渲染内容(等待重定向)
|
|
|
|
|
|
if (!isAuthenticated && !isPublicPath) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果已登录且在登录页面,不渲染内容(等待重定向)
|
|
|
|
|
|
if (isAuthenticated && location.pathname === '/login') {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 其他情况正常渲染
|
|
|
|
|
|
return <>{children}</>;
|
|
|
|
|
|
}
|