'use client'; import React, { useState, useRef, useEffect } from 'react'; import { AppBar, Toolbar, Box, IconButton, useTheme as useMuiTheme, Tooltip, useMediaQuery, LinearProgress } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { usePathname, useRouter } from 'next/navigation'; import { useTheme } from 'next-themes'; import MenuIcon from '@mui/icons-material/Menu'; // 样式 import * as styles from './styles'; // 子组件 import Logo from './Logo'; import ActionButtons from './ActionButtons'; import NavigationTabs from './NavigationTabs'; import MobileDrawer from './MobileDrawer'; import DesktopMenus from './DesktopMenus'; import ContextBar from './ContextBar'; export default function Navbar({ projects = [], currentProject }) { const { t } = useTranslation(); const pathname = usePathname(); const router = useRouter(); const theme = useMuiTheme(); const { resolvedTheme, setTheme } = useTheme(); const isProjectDetail = pathname.includes('/projects/') && pathname.split('/').length > 3; // 检测移动设备 const isMobile = useMediaQuery(theme.breakpoints.down('lg')); // 移动端抽屉状态 const [drawerOpen, setDrawerOpen] = useState(false); const [expandedMenu, setExpandedMenu] = useState(null); // 桌面端菜单状态 const [menuState, setMenuState] = useState({ anchorEl: null, menuType: null }); const [navLoading, setNavLoading] = useState(false); const navLoadingTimeoutRef = useRef(null); // ContextBar 悬浮状态 const [contextBarHovered, setContextBarHovered] = useState(false); const contextTriggerRef = useRef(null); const contextBarRef = useRef(null); useEffect(() => { if (!contextBarHovered) return; const handleOutsideClick = event => { if (contextBarRef.current?.contains(event.target)) return; if (contextTriggerRef.current?.contains(event.target)) return; const projectMenuEl = document.getElementById('project-menu'); if (projectMenuEl?.contains(event.target)) return; setContextBarHovered(false); }; document.addEventListener('pointerdown', handleOutsideClick, true); return () => { document.removeEventListener('pointerdown', handleOutsideClick, true); }; }, [contextBarHovered]); useEffect(() => { if (!menuState.menuType) return; const handleOutsideMenuClick = event => { if (menuState.anchorEl?.contains(event.target)) return; if (event.target?.closest?.('.MuiMenu-root')) return; setMenuState({ anchorEl: null, menuType: null }); }; document.addEventListener('pointerdown', handleOutsideMenuClick, true); return () => { document.removeEventListener('pointerdown', handleOutsideMenuClick, true); }; }, [menuState.anchorEl, menuState.menuType]); useEffect(() => { setNavLoading(false); if (navLoadingTimeoutRef.current) { clearTimeout(navLoadingTimeoutRef.current); navLoadingTimeoutRef.current = null; } }, [pathname]); useEffect(() => { if (!isProjectDetail || !currentProject) return; const prefetchRoutes = [ `/projects/${currentProject}/multi-turn`, `/projects/${currentProject}/eval-datasets`, `/projects/${currentProject}/eval-tasks` ]; prefetchRoutes.forEach(route => router.prefetch(route)); }, [router, currentProject, isProjectDetail]); useEffect(() => { return () => { if (navLoadingTimeoutRef.current) { clearTimeout(navLoadingTimeoutRef.current); } }; }, []); const handleNavigateStart = () => { setNavLoading(true); if (navLoadingTimeoutRef.current) { clearTimeout(navLoadingTimeoutRef.current); } navLoadingTimeoutRef.current = setTimeout(() => { setNavLoading(false); navLoadingTimeoutRef.current = null; }, 12000); }; const handleMenuOpen = (event, menuType) => { setMenuState({ anchorEl: event.currentTarget, menuType }); }; const handleMenuClose = () => { setMenuState({ anchorEl: null, menuType: null }); }; const isMenuOpen = menuType => menuState.menuType === menuType; const toggleDrawer = () => { setDrawerOpen(!drawerOpen); setExpandedMenu(null); }; const toggleMobileSubmenu = menuType => { setExpandedMenu(expandedMenu === menuType ? null : menuType); }; const toggleTheme = () => { setTheme(resolvedTheme === 'dark' ? 'light' : 'dark'); }; return ( <> {/* 左侧: 汉堡菜单(移动端) + Logo */} isProjectDetail && setContextBarHovered(true)} > {/* 汉堡菜单按钮 */} {isProjectDetail && isMobile && ( )} {/* Logo 组件 */} {/* 中间导航 - 仅桌面端 */} {isProjectDetail && !isMobile && ( )} {/* 右侧操作区 */} {isProjectDetail && ( )} {/* ContextBar - 在 Logo 或 ContextBar 悬浮时展示 */} {isProjectDetail && contextBarHovered && ( setContextBarHovered(false)}> setContextBarHovered(false)} /> )} {/* 移动端抽屉组件 */} {/* 桌面端菜单组件 */} ); }