import { useEffect, useMemo, useState } from 'react' import { Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom' import { Button, Result, Spin, Typography, message } from 'antd' import { useAuth } from '@/app/providers/auth-context' import { AuthLayout } from '@/layouts' import { parseOAuthCallbackHash, sanitizeAuthRedirect } from '@/lib/auth/oauth' import { getErrorMessage } from '@/lib/errors' import { exchangeOAuthHandoff } from '@/services/auth' const { Paragraph } = Typography export function OAuthCallbackPage() { const [status, setStatus] = useState<'loading' | 'success' | 'error'>('loading') const [errorMessage, setErrorMessage] = useState('') const [searchParams] = useSearchParams() const location = useLocation() const navigate = useNavigate() const { onLoginSuccess } = useAuth() const redirect = sanitizeAuthRedirect(searchParams.get('redirect')) const callbackPayload = useMemo(() => parseOAuthCallbackHash(location.hash), [location.hash]) useEffect(() => { let cancelled = false const consumeHandoff = async () => { if (callbackPayload.status === 'error') { if (!cancelled) { setStatus('error') setErrorMessage(callbackPayload.message || '第三方登录失败,请重试') } return } if (!callbackPayload.code) { if (!cancelled) { setStatus('error') setErrorMessage('缺少OAuth登录交接码,请重新发起登录') } return } try { const tokenBundle = await exchangeOAuthHandoff(callbackPayload.code) await onLoginSuccess(tokenBundle) if (!cancelled) { setStatus('success') message.success('第三方登录成功') navigate(redirect, { replace: true }) } } catch (error) { if (!cancelled) { setStatus('error') setErrorMessage(getErrorMessage(error, '第三方登录失败,请重试')) } } } void consumeHandoff() return () => { cancelled = true } }, [callbackPayload.code, callbackPayload.message, callbackPayload.status, navigate, onLoginSuccess, redirect]) if (status === 'loading') { return (
正在完成第三方登录...
) } if (status === 'success') { return ( ) } return ( , ]} /> ) }