import { useState, useEffect, useMemo } from 'react'; import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import { LayoutDashboard, Database, Server, Zap, Leaf, Code2, FileEdit, Users, ShieldCheck, FolderLock, Shield, GitBranch, Bell, LogOut, Settings, Timer, ScrollText, Megaphone, Sun, Moon, BookOpen, ChevronRight, Monitor } from 'lucide-react'; import { menuSections, menuItems } from '@/constants/menu'; import { useAuth } from '@/hooks/useAuth'; import { useTheme, THEME_OPTIONS } from '@/hooks/useTheme'; import request from '@/api/request'; const iconMap: Record = { LayoutDashboard, Database, Server, Zap, Leaf, Code2, FileEdit, Users, ShieldCheck, FolderLock, Shield, GitBranch, Bell, Settings, Timer, ScrollText, Megaphone, BookOpen, }; export default function Layout() { const { user, logout, visibleMenuItems } = useAuth(); const { theme, toggleTheme } = useTheme(); const location = useLocation(); const navigate = useNavigate(); const currentPath = location.pathname.split('/')[1] || 'dashboard'; const [pendingCount, setPendingCount] = useState(0); useEffect(() => { request.get('/dashboard/stats') .then((data: any) => setPendingCount(data?.ticket_pending ?? 0)) .catch(() => {}); }, [location.pathname]); // Build breadcrumb info from current path const breadcrumbInfo = useMemo(() => { const currentItem = menuItems.find(m => m.id === currentPath); if (!currentItem) { return { sectionLabel: '', pageLabel: '仪表盘' }; } const section = menuSections.find(s => s.id === currentItem.section); return { sectionLabel: section?.label || '', pageLabel: currentItem.label, }; }, [currentPath]); const themeOption = useMemo(() => THEME_OPTIONS.find(o => o.id === theme), [theme]); const themeIcon = useMemo(() => { if (!themeOption) return ; if (themeOption.isDark === 'system') return ; if (themeOption.isDark) return ; return ; }, [themeOption]); return (
{/* 侧边栏 — z-[200] 永远在弹框之上 */} {/* 主内容区 */}
{/* 顶部栏 — z-[200] 永远在弹框之上 */}
{/* Breadcrumb area */}
OpsxSQL {breadcrumbInfo.sectionLabel && ( {breadcrumbInfo.sectionLabel} )} {breadcrumbInfo.pageLabel}
{/* Right actions */}
{/* Theme toggle with tooltip */} {/* Notification bell */}
{/* User area */}
{user.avatar}
{user.username}
{/* 页面内容 */}
{/* Keyframe animation for active indicator */}
); }