import React, { useState, useEffect } from 'react'; import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom'; import { ConfigProvider, theme, App as AntdApp } from 'antd'; import zhCN from 'antd/locale/zh_CN'; import apiClient from './utils/apiClient'; import { buildApiUrl, API_ENDPOINTS } from './config/api'; import HomePage from './pages/HomePage'; import Dashboard from './pages/Dashboard'; import AdminDashboard from './pages/AdminDashboard'; import MeetingDetails from './pages/MeetingDetails'; import MeetingPreview from './pages/MeetingPreview'; import AdminManagement from './pages/AdminManagement'; import PromptManagementPage from './pages/PromptManagementPage'; import PromptConfigPage from './pages/PromptConfigPage'; import KnowledgeBasePage from './pages/KnowledgeBasePage'; import EditKnowledgeBase from './pages/EditKnowledgeBase'; import ClientDownloadPage from './pages/ClientDownloadPage'; import AccountSettings from './pages/AccountSettings'; import MeetingCenterPage from './pages/MeetingCenterPage'; import MainLayout from './components/MainLayout'; import menuService from './services/menuService'; import configService from './utils/configService'; import './App.css'; import './styles/console-theme.css'; // Layout Wrapper to inject user and handleLogout const AuthenticatedLayout = ({ user, handleLogout }) => { // 如果还在加载中或用户不存在,不渲染,避免闪烁 if (!user) return null; return ( ); }; const DefaultMenuRedirect = ({ user }) => { const [targetPath, setTargetPath] = useState(null); useEffect(() => { let active = true; const resolveDefaultPath = async () => { try { const path = await menuService.getDefaultPath(); if (active) { setTargetPath(path || '/dashboard'); } } catch (error) { console.error('Resolve default menu path failed:', error); if (active) { setTargetPath('/dashboard'); } } }; if (user) { resolveDefaultPath(); } return () => { active = false; }; }, [user]); if (!user) { return ; } if (!targetPath) { return (

加载菜单中...

); } return ; }; function App() { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); // Load user from localStorage on app start useEffect(() => { const savedAuth = localStorage.getItem('iMeetingUser'); if (savedAuth && savedAuth !== "undefined" && savedAuth !== "null") { try { const authData = JSON.parse(savedAuth); // 如果数据包含 user 字段,则提取 user 字段(适应新结构) // 否则使用整个对象(兼容旧结构) const userData = authData.user || authData; if (userData && typeof userData === 'object' && (userData.user_id || userData.id)) { setUser(userData); } else { localStorage.removeItem('iMeetingUser'); } } catch (error) { console.error('Error parsing saved user:', error); localStorage.removeItem('iMeetingUser'); } } setIsLoading(false); }, []); useEffect(() => { let active = true; configService.getBrandingConfig().then((branding) => { if (active && branding?.app_name) { document.title = branding.app_name; } }).catch(() => {}); return () => { active = false; }; }, []); const handleLogin = (authData) => { if (authData) { menuService.clearCache(); // 提取用户信息用于 UI 展示 const userData = authData.user || authData; setUser(userData); // 存入完整 auth 数据(包含 token)供拦截器使用 localStorage.setItem('iMeetingUser', JSON.stringify(authData)); } }; const handleLogout = async () => { try { await apiClient.post(buildApiUrl(API_ENDPOINTS.AUTH.LOGOUT)); } catch (error) { console.error('Logout API error:', error); } finally { setUser(null); localStorage.removeItem('iMeetingUser'); menuService.clearCache(); window.location.href = '/'; } }; if (isLoading) { return (

加载中...

); } return (
{/* Public Routes */} : } /> } /> } /> {/* Authenticated Routes */} : }> : } /> : } /> } /> } /> } /> } /> : } /> : } /> : } /> } /> : } /> } /> } /> } /> {/* Catch all */} } />
); } export default App;