import { useEffect, useState } from 'react'; import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import { checkAuth, logout, setUnauthorizedHandler } from './api/client'; import { clearAllStoredSessionIds } from './utils/sessionStorage'; import { loadBlockedWords } from './utils/wordFilter'; import { AuthView } from './components/AuthView'; import { ChatView } from './components/ChatView'; import { MindSpaceView } from './components/MindSpaceView'; import { ChatProvider } from './context/ChatProvider'; import { PREVIEW_USER } from './dev/mindspacePreviewData'; import { MindSpaceRoute } from './routes/MindSpaceRoute'; import { FeedbackRoutes } from './routes/FeedbackRoute'; import type { CapabilityMap, PortalUser } from './types'; function isMindSpacePreview() { return ( import.meta.env.DEV && new URLSearchParams(window.location.search).get('preview') === 'mindspace' ); } function MindSpaceAuthGate({ user, onLogout, }: { user: PortalUser | null; onLogout: () => void; }) { const location = useLocation(); if (!user) { const params = new URLSearchParams(); params.set('return_to', `${location.pathname}${location.search}`); const utmSource = new URLSearchParams(location.search).get('utm_source'); if (utmSource) params.set('utm_source', utmSource); return ; } return ; } function AuthenticatedApp({ user, capabilities, grantedSkills, onUserUpdate, onLogout, }: { user: PortalUser | null; capabilities?: CapabilityMap; grantedSkills?: string[]; onUserUpdate: (user: PortalUser) => void; onLogout: () => void; }) { const navigate = useNavigate(); const handleLogout = () => { clearAllStoredSessionIds(); void logout().finally(() => { onLogout(); navigate('/', { replace: true }); }); }; const chatElement = ( { if (target?.pageId) { navigate(`/space/page/${target.pageId}`); return; } if (target?.categoryCode) { navigate(`/space?category=${target.categoryCode}`); return; } navigate('/space'); } : undefined } onOpenPage={user ? (pageId) => navigate(`/space/page/${pageId}`) : undefined} onOpenAdmin={ user?.role === 'admin' ? () => { window.location.href = import.meta.env.VITE_ADMIN_APP_URL ?? '/admin-app'; } : undefined } onOpenFeedback={() => navigate('/feedback')} onLogout={handleLogout} /> ); return ( } /> } /> } /> ); } export function App() { const mindSpacePreview = isMindSpacePreview(); const navigate = useNavigate(); const [authed, setAuthed] = useState(null); const [user, setUser] = useState(null); const [capabilities, setCapabilities] = useState(); const [grantedSkills, setGrantedSkills] = useState(); const [legacyMode, setLegacyMode] = useState(false); const [authUnavailable, setAuthUnavailable] = useState(null); useEffect(() => { if (mindSpacePreview) return; setUnauthorizedHandler(() => { setAuthed(false); setUser(null); if (window.location.pathname !== '/') { navigate('/', { replace: true }); } }); void checkAuth().then((status) => { if (status.mode === 'unavailable') { setAuthUnavailable(status.message ?? '用户认证服务暂时不可用,请稍后刷新'); setAuthed(false); return; } setAuthUnavailable(null); setLegacyMode(status.mode === 'legacy'); setAuthed(status.authenticated); setUser(status.user ?? null); setCapabilities(status.capabilities); setGrantedSkills(status.grantedSkills); if (status.authenticated) void loadBlockedWords(); }); return () => setUnauthorizedHandler(null); }, [mindSpacePreview, navigate]); if (mindSpacePreview) { return ( { window.location.href = '/'; }} onLogout={() => { window.location.href = '/'; }} /> ); } if (authed === null) { return
正在验证登录状态…
; } if (authUnavailable) { return (
{authUnavailable}
); } if (!authed) { return ( { const params = new URLSearchParams(window.location.search); const returnTo = params.get('return_to') ?? null; if (returnTo) { try { const url = new URL(returnTo, window.location.origin); if (url.origin === window.location.origin) { window.location.href = url.toString(); return; } } catch { // ignore invalid URLs } } setAuthed(true); setUser(nextUser ?? null); setCapabilities(nextCapabilities); setGrantedSkills(nextSkills); }} /> ); } return ( { clearAllStoredSessionIds(); setAuthed(false); setUser(null); }} /> ); }