diff --git a/frontend/src/admin/AdminLayout.tsx b/frontend/src/admin/AdminLayout.tsx index 55e194a..89c5e5f 100644 --- a/frontend/src/admin/AdminLayout.tsx +++ b/frontend/src/admin/AdminLayout.tsx @@ -1,11 +1,13 @@ /** * Admin 后台 - 布局组件 * - * 提供管理界面的基本结构:顶栏 + 侧边栏 + 内容区 + * 响应式布局: 移动端汉堡菜单 + 可折叠侧边栏 + * 桌面端: 固定侧边栏 + 内容区 * 暗色主题,参考线性风格设计 */ -import { NavLink, Outlet } from 'react-router-dom' +import { useState, useEffect, useCallback } from 'react' +import { NavLink, Outlet, useLocation } from 'react-router-dom' const NAV_ITEMS = [ { to: '/admin', label: '仪表盘', icon: '◇', end: true }, @@ -13,22 +15,72 @@ const NAV_ITEMS = [ { to: '/admin/predictions', label: '预测管理', icon: '◆' }, { to: '/admin/backtest', label: '回测管理', icon: '◉' }, { to: '/admin/monitoring', label: '监控面板', icon: '◐' }, - { to: '/admin/config', label: '配置管理', icon: '◑' }, + { to: '/admin/data-sources', label: '数据源', icon: '◫' }, + { to: '/admin/llm-config', label: 'LLM 配置', icon: '◬' }, + { to: '/admin/config', label: '系统配置', icon: '◑' }, ] export default function AdminLayout() { + const [sidebarOpen, setSidebarOpen] = useState(false) + const location = useLocation() + + // 路由变化时关闭移动端菜单 + const closeSidebar = useCallback(() => setSidebarOpen(false), []) + + useEffect(() => { + closeSidebar() + }, [location.pathname, closeSidebar]) + + // ESC 键关闭菜单 + useEffect(() => { + const handler = (e: KeyboardEvent) => { + if (e.key === 'Escape') setSidebarOpen(false) + } + document.addEventListener('keydown', handler) + return () => document.removeEventListener('keydown', handler) + }, []) + return (
+ {/* ── 移动端遮罩层 ── */} + {sidebarOpen && ( +
setSidebarOpen(false)} + aria-hidden="true" + /> + )} + {/* ── 侧边栏 ── */} -