// ============================================================ // NavBar — 自定义顶部导航栏(替代系统菜单) // // 逻辑: // - 所有导航项默认全部显示(不再按登录状态隐藏) // - 未登录时点击需登录的项 → 弹出提示"请先登录"并触发登录 Modal // - 登录/注册 与 退出登录 仍按登录状态互斥显示 // ============================================================ import {useState, useCallback, useMemo} from 'react'; import {App} from 'antd'; import {useAppContext} from '@/app/providers/AppProvider'; import {useTheme} from '@/app/providers/ThemeProvider'; import {emit, EVENTS, safeIpcSend} from '@/shared/utils/bus'; import {RENDERER_TO_MAIN_CANVAS} from '@shared/constants/ipc'; import {useAnnouncements} from '@/shared/hooks/use-announcements'; import {NavItem} from './NavItem'; import {AnnouncementDrawer} from '@/modules/announcement/views/AnnouncementDrawer'; import {personalLeft, personalRight, enterpriseLeft, enterpriseRight} from '../settings/nav-config'; import type {NavItemConfig} from '../model/types'; const NAVBAR_HEIGHT = 56; export function NavBar() { const {platform, edition, isLoggedIn, logout} = useAppContext(); const {isDark} = useTheme(); const {message} = App.useApp(); const [drawerOpen, setDrawerOpen] = useState(false); // 公告轮询 + 未读缓存 const { announcements, unreadCount, loading: announcementsLoading, markAsRead, refetch: refetchAnnouncements } = useAnnouncements(); // 根据版本选择导航项 const {leftItems, rightItems} = useMemo(() => { const isEnterprise = edition === 'enterprise'; return { leftItems: isEnterprise ? enterpriseLeft : personalLeft, rightItems: isEnterprise ? enterpriseRight : personalRight, }; }, [edition]); // 过滤规则: // requireGuest → 仅未登录时可见(登录/注册) // "退出登录" → 仅已登录时可见 // 其他所有项 → 始终可见,未登录点击时弹"请先登录" const visibleLeft = useMemo( () => leftItems.filter((item) => { if (item.requireGuest && isLoggedIn) return false; return !(item.key === 'logout' && !isLoggedIn); }), [leftItems, isLoggedIn], ); const visibleRight: NavItemConfig[] = useMemo( () => rightItems.filter((item) => { if (item.requireGuest && isLoggedIn) return false; return !(item.key === 'logout' && !isLoggedIn); }), [rightItems, isLoggedIn], ); // 点击导航项 const handleNavClick = useCallback( (item: NavItemConfig) => { // 需要登录但未登录 → 提示并弹出登录 Modal if (item.requireLogin && !isLoggedIn) { message.warning('请先登录'); emit(EVENTS.SHOW_LOGIN); return; } switch (item.action) { case 'drawer': if (item.key === 'announcements') { setDrawerOpen(true); refetchAnnouncements(); markAsRead(); } break; case 'button': if (item.key === 'logout') { logout(); } else if (item.key === 'settings') { emit(EVENTS.OPEN_SETTINGS); } else if (item.key === 'auth') { emit(EVENTS.SHOW_LOGIN); } break; case 'external': if (item.target) { window.open(item.target, '_blank'); } break; case 'page': // 项目管理 → 打开独立画布窗口(新 BrowserWindow,非主窗口内叠加层) if (item.key === 'project-management') { console.log('[NavBar] 🖼️ 点击"项目管理" → 发送 OPEN_CANVAS_WINDOW IPC'); safeIpcSend(RENDERER_TO_MAIN_CANVAS.OPEN_CANVAS_WINDOW); return; } if (item.target) { emit(EVENTS.OPEN_PAGE, { target: item.target, modalType: item.modalType ?? 'floating', label: item.label, }); } break; } }, [isLoggedIn, logout, message, markAsRead, refetchAnnouncements], ); const macPaddingLeft = platform === 'darwin' ? 80 : 12; return ( <>