"use client"; import React from "react"; import AppBar from "@mui/material/AppBar"; import Box from "@mui/material/Box"; import Toolbar from "@mui/material/Toolbar"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Menu from "@mui/material/Menu"; import MenuItem from "@mui/material/MenuItem"; import Container from "@mui/material/Container"; import { ThemeProvider, createTheme } from "@mui/material/styles"; import CssBaseline from "@mui/material/CssBaseline"; import { styled } from "@mui/material/styles"; import ListSubheader from "@mui/material/ListSubheader"; import useScrollTrigger from "@mui/material/useScrollTrigger"; import Drawer from "@mui/material/Drawer"; import IconButton from "@mui/material/IconButton"; import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemText from "@mui/material/ListItemText"; import Divider from "@mui/material/Divider"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; function colorLog(message: string, color: 'reset' | 'red' | 'green' | 'yellow' | 'blue') { const colors = { reset: '\x1b[0m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m' }; console.log(`${colors[color]}%s${colors.reset}`, message); } // 自定义内容标题样式 const StyledListHeader = styled(ListSubheader)({ backgroundImage: "var(--Paper-overlay)", }); // 创建MUI主题 const theme = createTheme({ typography: { fontFamily: "inherit", }, }); interface ClientLayoutProps { children: React.ReactNode; } // 客户端组件负责MUI主题和UI组件 const ClientLayout: React.FC = ({ children }) => { // 将hooks移到组件内部 const [anchorEl, setAnchorEl] = React.useState(null); const [mobileDrawerOpen, setMobileDrawerOpen] = React.useState(false); const [isMobile, setIsMobile] = React.useState(false); // 监听窗口大小变化,判断是否为移动设备 React.useEffect(() => { const handleResize = () => { setIsMobile(window.innerWidth < 768); // 768px为移动端断点 }; // 初始化时判断 handleResize(); // 添加事件监听器 window.addEventListener('resize', handleResize); // 清理函数 return () => window.removeEventListener('resize', handleResize); }, []); const handleMenu = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; // 定义顶栏导航项的类型 interface NavItem { id: string; label: string; href: string; type: 'link' | 'menu'; children?: NavItem[]; } // 定义导航项目菜单的类型 interface ProjectItem { id: string; label: string; href: string; category: string; } // 动态定义顶部导航链接 const navItems: NavItem[] = [ { id: 'home', label: 'LeonCloud', href: '/', type: 'link' }, { id: 'link', label: 'Link', href: '/test', type: 'link' }, { id: 'Menu', label: 'Menu', href: '', type: 'menu' }, // { // id: 'id', // label: 'label', // href: '/href', // type: 'link' // } ]; // 动态定义项目列表 const projectItems: ProjectItem[] = [ { id: 'first', label: 'First', href: '/awa/first', category: '1' }, { id: 'second', label: 'Second', href: '/awa/second', category: '1' }, { id: 'third', label: 'Third', href: '/awa/third', category: '2' } ]; // 按分类组织项目 const projectsByCategory = projectItems.reduce((acc, item) => { if (!acc[item.category]) { acc[item.category] = []; } acc[item.category].push(item); return acc; }, {} as Record); // 侧边栏开关控制 const toggleDrawer = (open: boolean) => () => { setMobileDrawerOpen(open); }; // 侧边栏项目点击处理 const handleDrawerItemClick = (href: string) => { window.location.href = href; setMobileDrawerOpen(false); }; // 分类展开状态管理 - 现在在projectsByCategory定义之后初始化 const [expandedCategories, setExpandedCategories] = React.useState>({ // 直接初始化所有已知分类为展开状态 'Web': true, '其它': true }); // 项目部分的展开状态管理 const [projectsExpanded, setProjectsExpanded] = React.useState(false); // 切换分类展开/收缩状态 const toggleCategory = (category: string) => { setExpandedCategories(prev => ({ ...prev, [category]: !prev[category] })); }; interface Props { /** * Injected by the documentation to work in an iframe. * You won't need it on your project. */ window?: () => Window; children?: React.ReactElement<{ elevation?: number }>; } // function ElevationScroll(props: Props) { // const { children, window } = props; // // Note that you normally won't need to set the window ref as useScrollTrigger // // will default to window. // // This is only being set here because the demo is in an iframe. // const trigger = useScrollTrigger({ // disableHysteresis: true, // threshold: 0, // target: window ? window() : undefined, // }); // return children // ? React.cloneElement(children, { // elevation: trigger ? 4 : 0, // }) // : null; // } return ( {/* 响应式顶栏 - 移动端显示汉堡菜单,桌面端显示完整导航 */} {/* 移动端:汉堡菜单按钮 */} {isMobile && ( )} {/* 首页链接(在所有设备上都显示) */} (window.location.href = '/')} > LeonCloud {/* 桌面端:完整导航链接 */} {!isMobile && ( {navItems.filter(item => item.id !== 'home').map((item) => { if (item.type === 'link') { return ( (window.location.href = item.href)} > {item.label} ); } else if (item.type === 'menu') { return ( ); } return null; })} )} {/* 桌面端:项目下拉菜单 */} {!isMobile && ( {Object.entries(projectsByCategory).map(([category, items]) => ( {category} {items.map((project) => ( { window.location.href = project.href; handleClose(); }} > {project.label} ))} ))} )} {/* 移动端侧边栏 */} {/* 侧边栏头部 */} 导航菜单 {/* 侧边栏导航链接 */} {navItems.filter(item => item.id !== 'home').map((item) => { if (item.type === 'link') { return ( { e.preventDefault(); handleDrawerItemClick(item.href); }} > ); } else if (item.type === 'menu') { return ( setProjectsExpanded(prev => !prev)} sx={{ pl: 1, cursor: 'pointer', '&:hover': { backgroundColor: 'rgba(0,0,0,0.04)' }, display: 'flex', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.02)', fontWeight: 'bold' }} > {projectsExpanded && Object.entries(projectsByCategory).map(([category, projects]) => ( toggleCategory(category)} sx={{ pl: 2, cursor: 'pointer', '&:hover': { backgroundColor: 'rgba(0,0,0,0.04)' }, display: 'flex', alignItems: 'center' }} > {expandedCategories[category] && projects.map((project) => ( { e.preventDefault(); handleDrawerItemClick(project.href); }} sx={{ pl: 6 }} > ))} ))} ); } return null; })} {/* 为固定顶栏添加足够的顶部空间 */} {children} {/* 页脚区域 */} Test 这是页脚 © {new Date().getFullYear()} Test. 保留所有权利。 你可以在ClientLayout.tsx修改这个页脚 ); }; export default ClientLayout;