91 lines
1.8 KiB
TypeScript
91 lines
1.8 KiB
TypeScript
import React, { useEffect, useRef, useState } from 'react';
|
||
import { Spin } from 'antd';
|
||
import { useAuth } from '../hooks/useAuth';
|
||
|
||
interface AuthGuardProps {
|
||
children: React.ReactNode;
|
||
}
|
||
|
||
const AuthGuard: React.FC<AuthGuardProps> = ({ children }) => {
|
||
const {
|
||
isAuthenticated,
|
||
initAuth,
|
||
loginUrl,
|
||
redirectToLogin,
|
||
loading,
|
||
logout,
|
||
} = useAuth();
|
||
|
||
const initedRef = useRef(false);
|
||
const [booting, setBooting] = useState(true);
|
||
|
||
// 调试信息
|
||
console.log('🔐 [AuthGuard] 状态:', {
|
||
booting,
|
||
isAuthenticated,
|
||
loading,
|
||
hasLoginUrl: !!loginUrl,
|
||
});
|
||
|
||
useEffect(() => {
|
||
if (initedRef.current) {
|
||
setBooting(false);
|
||
return;
|
||
}
|
||
initedRef.current = true;
|
||
(async () => {
|
||
try {
|
||
await initAuth();
|
||
} finally {
|
||
setBooting(false);
|
||
}
|
||
})();
|
||
}, [initAuth]);
|
||
|
||
// 未认证时,主动触发SSO登录流程
|
||
useEffect(() => {
|
||
if (!booting && !isAuthenticated && !loading) {
|
||
redirectToLogin();
|
||
}
|
||
}, [booting, isAuthenticated, loading, redirectToLogin]);
|
||
|
||
if (booting) {
|
||
return (
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
height: '100vh',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
}}
|
||
>
|
||
<Spin tip="Loading...">
|
||
<div className="w-[200px]" />
|
||
</Spin>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (!isAuthenticated) {
|
||
// 未认证时显示加载,等待自动跳转SSO
|
||
return (
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
height: '100vh',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
}}
|
||
>
|
||
<Spin tip="Redirecting to SSO...">
|
||
<div className="w-[200px]" />
|
||
</Spin>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return <>{children}</>;
|
||
};
|
||
|
||
export default AuthGuard;
|