import { useEffect, useRef, useState, type ReactNode } from 'react'; import { Navigate, useLocation } from 'react-router-dom'; import { portalSessionApi } from '@/api/adminApi'; import { clearSession, readSession, saveSessionRecovery, writeSession, type LoginSession, type Portal, } from '@/api/session'; type PortalSessionBoundaryProps = { portal: Portal; children(session: LoginSession): ReactNode; }; export function PortalSessionBoundary({ portal, children }: PortalSessionBoundaryProps) { const location = useLocation(); const targetRoute = useRef(`${location.pathname}${location.search}${location.hash}`); const [state, setState] = useState<{ checking: boolean; session: LoginSession | null }>({ checking: true, session: readSession(portal), }); useEffect(() => { let active = true; setState((current) => ({ ...current, checking: true })); portalSessionApi.current(portal) .then((session) => { if (!active) return; writeSession(session); setState({ checking: false, session }); }) .catch((error: unknown) => { if (!active) return; clearSession(portal); saveSessionRecovery(portal, { returnUrl: targetRoute.current, message: error instanceof Error ? error.message : '登录会话已失效,请重新登录', }); setState({ checking: false, session: null }); }); return () => { active = false; }; }, [portal]); if (state.checking) { return (

正在恢复登录会话…

); } if (!state.session) return ; return children(state.session); }