import React, { useState, useEffect, Suspense, lazy } from 'react'; import { Layout, Menu, theme, Button, Dropdown, Avatar, message, Space, Divider, ConfigProvider as AntdConfigProvider, } from 'antd'; import { BarChartOutlined, DatabaseOutlined, CloudServerOutlined, MenuUnfoldOutlined, MenuFoldOutlined, EyeOutlined, BuildOutlined, HomeOutlined, ShoppingCartOutlined, InboxOutlined, ImportOutlined, FileTextOutlined, UserOutlined, LogoutOutlined, HistoryOutlined, AuditOutlined, ToolOutlined, ScheduleOutlined, SettingOutlined, ApiOutlined, PartitionOutlined, CodepenOutlined, CloudUploadOutlined, } from '@ant-design/icons'; import { BrowserRouter as Router, Routes, Route, Link, Navigate, useLocation, useNavigate, } from 'react-router-dom'; import { useAuth } from './context/AuthContext'; import { ConfigProvider, useConfig } from './context/ConfigContext'; import { Scene3DProvider } from './context/Scene3DContext'; import { useDesignTokens } from './hooks/useDesignTokens'; import useIdleTimeout from './hooks/useIdleTimeout'; import { SWRConfig, swrConfig } from './hooks/useSWR'; import axios from 'axios'; import { Spin } from 'antd'; import ErrorBoundary from './components/ErrorBoundary'; const Dashboard = lazy(() => import('./pages/Dashboard')); const DeviceManagement = lazy(() => import('./pages/DeviceManagement')); const RackManagement = lazy(() => import('./pages/RackManagement')); const RoomManagement = lazy(() => import('./pages/RoomManagement')); const DeviceFieldManagement = lazy(() => import('./pages/DeviceFieldManagement')); const Rack3DVisualization = lazy(() => import('./pages/Rack3DVisualization')); const ConsumableManagement = lazy(() => import('./pages/ConsumableManagement')); const ConsumableStatistics = lazy(() => import('./pages/ConsumableStatistics')); const ConsumableLogs = lazy(() => import('./pages/ConsumableLogs')); const CategoryManagement = lazy(() => import('./pages/CategoryManagement')); const UserManagement = lazy(() => import('./pages/UserManagement')); const Login = lazy(() => import('./pages/Login')); const TicketManagement = lazy(() => import('./pages/TicketManagement')); const TicketCategoryManagement = lazy(() => import('./pages/TicketCategoryManagement')); const TicketStatistics = lazy(() => import('./pages/TicketStatistics')); const TicketFieldManagement = lazy(() => import('./pages/TicketFieldManagement')); const SystemSettings = lazy(() => import('./pages/SystemSettings')); const CableManagement = lazy(() => import('./pages/CableManagement')); const PortManagement = lazy(() => import('./pages/PortManagement')); const InventoryManagement = lazy(() => import('./pages/InventoryManagement')); const InventoryTaskExecution = lazy(() => import('./pages/InventoryTaskExecution')); const PendingDeviceManagement = lazy(() => import('./pages/PendingDeviceManagement')); const BackupManagement = lazy(() => import('./pages/BackupManagement')); const AutoBackupSettings = lazy(() => import('./pages/AutoBackupSettings')); const ErrorBoundaryTest = lazy(() => import('./pages/ErrorBoundaryTest')); const { Header, Content, Sider } = Layout; const PageLoading = () => (
正在加载页面...
); const AuthLoading = () => (
正在加载认证状态...
); const PrivateRoute = ({ children }) => { const { token, initialized, loading } = useAuth(); const location = useLocation(); if (!initialized) { return ; } if (!token) { return ; } return {children}; }; const ProtectedRoute = ({ component: Component }) => ( ); // 默认空闲超时配置 const DEFAULT_IDLE_CONFIG = { timeout: 30 * 60 * 1000, // 30分钟 warningTime: 60 * 1000, // 60秒 }; const AppLayout = ({ children }) => { const [collapsed, setCollapsed] = useState(false); const [activeKey, setActiveKey] = useState('dashboard'); const [idleConfig, setIdleConfig] = useState(DEFAULT_IDLE_CONFIG); const { user, logout } = useAuth(); const { config } = useConfig(); const navigate = useNavigate(); const location = useLocation(); const designTokens = useDesignTokens(); // 获取空闲超时配置 useEffect(() => { const fetchIdleConfig = async () => { try { const response = await axios.get('/api/system-settings/idle-timeout'); setIdleConfig({ timeout: response.data.timeout, warningTime: response.data.warningTime, }); } catch (error) { console.warn('获取空闲超时配置失败,使用默认配置:', error); } }; fetchIdleConfig(); }, []); // 启用空闲超时检测 useIdleTimeout({ timeout: idleConfig.timeout, warningTime: idleConfig.warningTime, onLogout: logout, enabled: true, }); const handleLogout = () => { logout(); message.success('已退出登录'); navigate('/login'); }; const getSelectedKey = () => { const path = location.pathname; if (path === '/') return 'dashboard'; if (path.startsWith('/visualization-3d')) return 'visualization-3d'; if (path.startsWith('/rooms') || path.startsWith('/racks')) return 'room-management'; if ( path.startsWith('/devices') || path.startsWith('/fields') || path.startsWith('/cables') || path.startsWith('/ports') ) return 'asset-management'; if (path.startsWith('/consumables')) return 'consumables-management'; if ( path.startsWith('/users') || path.startsWith('/login-history') || path.startsWith('/operation-logs') || path.startsWith('/settings') || path.startsWith('/backup') ) return 'system-management'; if (path.startsWith('/tickets')) return 'ticket-management'; if (path.startsWith('/inventory') || path.startsWith('/pending-devices')) return 'inventory-management'; return 'dashboard'; }; const menuItems = [ { key: 'dashboard', icon: , label: 仪表盘, }, { key: 'room-management', icon: , label: '机房管理', children: [ { key: 'rooms', icon: , label: 机房管理, }, { key: 'racks', icon: , label: 机柜管理, }, { key: 'visualization-3d', icon: , label: 3D机柜可视化, }, ], }, { key: 'asset-management', icon: , label: '资产管理', children: [ { key: 'devices', icon: , label: 设备管理, }, { key: 'fields', icon: , label: 字段管理, }, { key: 'cables', icon: , label: 接线管理, }, { key: 'ports', icon: , label: 端口管理, }, ], }, { key: 'consumables-management', icon: , label: '耗材管理', children: [ { key: 'consumables-stats', icon: , label: 耗材统计, }, { key: 'consumables', icon: , label: 耗材列表, }, { key: 'consumables-categories', icon: , label: 分类管理, }, { key: 'consumables-logs', icon: , label: 操作日志, }, ], }, { key: 'ticket-management', icon: , label: '工单管理', children: [ { key: 'tickets', icon: , label: 工单列表, }, { key: 'ticket-categories', icon: , label: 故障分类, }, { key: 'ticket-statistics', icon: , label: 统计报表, }, { key: 'ticket-fields', icon: , label: 字段管理, }, ], }, { key: 'inventory-management', icon: , label: '资产盘点', children: [ { key: 'inventory', icon: , label: 盘点计划, }, { key: 'pending-devices', icon: , label: 暂存设备, }, ], }, { key: 'system-management', icon: , label: '系统管理', children: [ { key: 'users', icon: , label: 用户管理, }, { key: 'system-settings', icon: , label: 系统设置, }, { key: 'backup', icon: , label: 数据备份, }, ], }, ]; return (
{!collapsed && (
{config.site_name || 'IDC管理'}
数据中心管理平台
)}
{user && (
} /> {user.username}
)}
{children}
); }; const routeConfig = [ { path: '/', component: Dashboard }, { path: '/devices', component: DeviceManagement }, { path: '/racks', component: RackManagement }, { path: '/rooms', component: RoomManagement }, { path: '/fields', component: DeviceFieldManagement }, { path: '/consumables', component: ConsumableManagement }, { path: '/consumables-categories', component: CategoryManagement }, { path: '/consumables-stats', component: ConsumableStatistics }, { path: '/consumables-logs', component: ConsumableLogs }, { path: '/users', component: UserManagement }, { path: '/tickets', component: TicketManagement }, { path: '/ticket-categories', component: TicketCategoryManagement }, { path: '/ticket-statistics', component: TicketStatistics }, { path: '/ticket-fields', component: TicketFieldManagement }, { path: '/settings', component: SystemSettings }, { path: '/cables', component: CableManagement }, { path: '/inventory', component: InventoryManagement }, { path: '/inventory/execution', component: InventoryTaskExecution }, { path: '/pending-devices', component: PendingDeviceManagement }, { path: '/ports', component: PortManagement }, { path: '/backup', component: BackupManagement }, { path: '/auto-backup-settings', component: AutoBackupSettings }, { path: '/error-boundary-test', component: ErrorBoundaryTest }, ]; const ThemeConfig = () => { const designTokens = useDesignTokens(); const renderRoute = (path, Component, needsErrorBoundary = true) => { const element = ( ); if (needsErrorBoundary) { return ( {element} } /> ); } return ; }; return ( }> } /> {routeConfig.map(({ path, component: Component }) => renderRoute(path, Component) )} } /> } /> ); }; function App() { return ( ); } export default App;