/** * @license * SPDX-License-Identifier: Apache-2.0 */ /** * @license * SPDX-License-Identifier: Apache-2.0 */ import React, { useState, useEffect, useRef } from 'react'; import { AnimatePresence, motion } from 'motion/react'; import Login from './components/Login'; import Sidebar from './components/Sidebar'; import Overview from './components/Overview'; import ProjectLibrary from './components/ProjectLibrary'; import ReverseWorkspace from './components/ReverseWorkspace'; import UserManagement from './components/UserManagement'; import { ViewType } from './types'; import { api } from './lib/api'; export default function App() { const [isAuthenticated, setIsAuthenticated] = useState(false); const [sessionLoading, setSessionLoading] = useState(true); const [activeView, setActiveView] = useState(ViewType.OVERVIEW); const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [activeProjectId, setActiveProjectId] = useState('head-ct-demo'); const [projectLibraryInitialView, setProjectLibraryInitialView] = useState<'dicom' | 'model' | 'mask'>('dicom'); const workspaceLeaveGuardRef = useRef<(() => Promise) | null>(null); const bootSessionResetRef = useRef(false); // Automatically collapse main sidebar when entering Project Library or Workspace useEffect(() => { if (activeView === ViewType.PROJECTS || activeView === ViewType.WORKSPACE) { setSidebarCollapsed(true); } else { setSidebarCollapsed(false); } }, [activeView]); useEffect(() => { let mounted = true; const syncSession = async () => { try { if (!bootSessionResetRef.current) { bootSessionResetRef.current = true; const session = await api.logout(); if (!mounted) { return; } setIsAuthenticated(session.authenticated); setActiveView(ViewType.OVERVIEW); return; } const session = await api.getSession(); if (!mounted) { return; } setIsAuthenticated(session.authenticated); if (!session.authenticated) { setActiveView(ViewType.OVERVIEW); } } catch { if (mounted) { setIsAuthenticated(false); } } finally { if (mounted) { setSessionLoading(false); } } }; syncSession(); const interval = window.setInterval(syncSession, 2500); return () => { mounted = false; window.clearInterval(interval); }; }, []); const handleLogin = () => { setIsAuthenticated(true); }; const requestActiveView = (nextView: ViewType) => { if (nextView === activeView) { return; } const leaveWorkspace = activeView === ViewType.WORKSPACE && nextView !== ViewType.WORKSPACE; const switchView = () => { if (leaveWorkspace && nextView === ViewType.PROJECTS) { setProjectLibraryInitialView('mask'); } setActiveView(nextView); }; if (!leaveWorkspace || !workspaceLeaveGuardRef.current) { switchView(); return; } workspaceLeaveGuardRef.current() .then((canLeave) => { if (canLeave) { switchView(); } }) .catch(() => undefined); }; const handleLogout = async () => { if (activeView === ViewType.WORKSPACE && workspaceLeaveGuardRef.current) { const canLeave = await workspaceLeaveGuardRef.current(); if (!canLeave) { return; } } await api.logout(); setIsAuthenticated(false); setActiveView(ViewType.OVERVIEW); }; if (sessionLoading) { return (
正在同步登录状态...
); } if (!isAuthenticated) { return ; } return (
{/* Top Navigation */}
{activeView === ViewType.OVERVIEW && '总体概况'} {activeView === ViewType.PROJECTS && '项目库'} {activeView === ViewType.WORKSPACE && '逆向工作区'} {activeView === ViewType.SYSTEM && '系统管理工作区'}
{/* Content Area */}
{activeView === ViewType.OVERVIEW && } {activeView === ViewType.PROJECTS && ( { setActiveProjectId(projectId); setActiveView(ViewType.WORKSPACE); }} /> )} {activeView === ViewType.WORKSPACE && ( { workspaceLeaveGuardRef.current = handler; }} /> )} {activeView === ViewType.SYSTEM && }
); }