diff --git a/frontend/src/components/layout/Header.tsx b/frontend/src/components/layout/Header.tsx index 9f410da..923ba25 100644 --- a/frontend/src/components/layout/Header.tsx +++ b/frontend/src/components/layout/Header.tsx @@ -1,7 +1,5 @@ import { useNavigate } from 'react-router-dom' import { useAuth } from '../../hooks/useAuth' -import Badge from '../ui/Badge' -import SearchBox from '../ui/SearchBox' export interface HeaderProps { breadcrumb?: string @@ -18,7 +16,6 @@ export default function Header({ breadcrumb, onlineCount = 0, runningCount = 0, - offlineCount = 0, onSearch, onSearchNavigate, theme, @@ -28,76 +25,142 @@ export default function Header({ const { user, logout } = useAuth() const initial = user?.id ? user.id.charAt(0).toUpperCase() : '?' + const handleSearchKeyDown = (e: React.KeyboardEvent) => { + const value = (e.target as HTMLInputElement).value.trim() + if (e.key === 'Enter' && onSearchNavigate) { + onSearchNavigate(value) + } + if (e.key === 'Enter' && onSearch) { + onSearch(value) + } + } + return (
+ {/* Logo */} + + 🐝 知微蜂巢 + + {/* Breadcrumb */} -
- {breadcrumb && ( - <> - navigate('/dashboard')} - > - 首页 - - / - {breadcrumb} - - )} -
+ + / {breadcrumb || '蜂群总览'} + {/* Spacer */} -
+
{/* Search */} - {onSearch && ( - - )} + { e.currentTarget.style.borderColor = 'var(--honey)' }} + onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--border)' }} + /> {/* Status badges */} - 在线 {onlineCount} - 运行中 {runningCount} - 离线 {offlineCount} + + 🟢 {onlineCount} online + + + 🟡 {runningCount} running + {/* Theme toggle */} - {/* User avatar + role */} + {/* User avatar */}
{initial}
- - {user?.role} - - {/* Dropdown */}
{ e.currentTarget.style.display = 'block' }} + onMouseLeave={(e) => { e.currentTarget.style.display = 'none' }} > diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index c24b417..9e0d963 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -1,6 +1,5 @@ import { useEffect, useState } from 'react' import { useAuth } from '../../hooks/useAuth' -import Badge from '../ui/Badge' import { getDashboardSummary } from '../../api/dashboard' interface NavItem { @@ -8,7 +7,8 @@ interface NavItem { icon: string path: string badge?: number - requiredRole?: string // viewer can see all by default + isNew?: boolean + requiredRole?: string } interface NavSection { @@ -21,8 +21,8 @@ const sections: NavSection[] = [ title: '蜂群态势', items: [ { label: '蜂群总览', icon: '📊', path: '/dashboard' }, - { label: 'Gateway', icon: '📡', path: '/gateway', requiredRole: 'operator' }, - { label: '健康分', icon: '🏥', path: '/health' }, + { label: 'Gateway 健康', icon: '📡', path: '/gateway', isNew: true }, + { label: 'Profile 健康分', icon: '🏥', path: '/health', isNew: true }, { label: '工蜂列表', icon: '🤖', path: '/workers' }, ], }, @@ -30,35 +30,40 @@ const sections: NavSection[] = [ title: '任务编排', items: [ { label: '看板追踪', icon: '📋', path: '/kanban' }, - { label: 'Cron 管理', icon: '⏰', path: '/cron', requiredRole: 'operator' }, - { label: '事件管理', icon: '🔔', path: '/events' }, + { label: 'Cron 管理', icon: '⏰', path: '/cron', badge: 1 }, + { label: '事件管理', icon: '🔔', path: '/events', badge: 3 }, ], }, { title: '通信频道', - items: [{ label: '频道配置', icon: '📶', path: '/channels' }], + items: [ + { label: '频道配置', icon: '📡', path: '/channels' }, + { label: '频道监控', icon: '📶', path: '/channel-monitor', isNew: true }, + ], }, { title: '运维工具', items: [ - { label: '密钥', icon: '🔑', path: '/keys', requiredRole: 'operator' }, - { label: '文件', icon: '📁', path: '/files' }, - { label: '终端', icon: '💻', path: '/terminal' }, - { label: '日志', icon: '📜', path: '/logs' }, - { label: 'MCP接入', icon: '🔌', path: '/mcp-in' }, - { label: 'MCP对外', icon: '📤', path: '/mcp-out' }, + { label: '密钥管理', icon: '🔑', path: '/keys' }, + { label: '文件浏览', icon: '📁', path: '/files', isNew: true }, + { label: 'Web 终端', icon: '💻', path: '/terminal', isNew: true }, + { label: '蜂群日志', icon: '📜', path: '/logs', isNew: true }, + { label: 'MCP 接入管理', icon: '🔌', path: '/mcp-in', isNew: true }, + { label: 'MCP 对外服务', icon: '📤', path: '/mcp-out', isNew: true }, ], }, { title: '知识库管理', - items: [{ label: '事件档案', icon: '📚', path: '/archive' }], + items: [ + { label: '事件档案管理', icon: '📚', path: '/archive', isNew: true }, + ], }, { title: '系统', items: [ { label: '用户管理', icon: '👥', path: '/users', requiredRole: 'owner' }, { label: '审计日志', icon: '📋', path: '/audit', requiredRole: 'owner' }, - { label: '设置', icon: '⚙', path: '/settings' }, + { label: '系统设置', icon: '⚙', path: '/settings' }, ], }, ] @@ -68,7 +73,6 @@ export interface SidebarProps { onNavigate: (path: string) => void } -/** Check whether the current user's role satisfies the required role level. */ function hasAccess(userRole: string | undefined, requiredRole?: string): boolean { if (!requiredRole) return true const hierarchy: Record = { viewer: 0, operator: 1, owner: 2 } @@ -94,61 +98,140 @@ export default function Sidebar({ activePath, onNavigate }: SidebarProps) { }, []) return ( -