feat: MainLayout 三端布局重构,使用 antd Grid.useBreakpoint()

This commit is contained in:
2026-07-03 10:04:42 +08:00
parent 611cc271ec
commit 7465f51d4f

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState } from 'react';
import { Outlet, useNavigate, useLocation } from 'react-router-dom'; import { Outlet, useNavigate, useLocation } from 'react-router-dom';
import { Layout, Menu, Button, Avatar, Dropdown, Drawer } from 'antd'; import { Layout, Menu, Button, Avatar, Dropdown, Drawer, Grid } from 'antd';
import { import {
DashboardOutlined, DashboardOutlined,
TeamOutlined, TeamOutlined,
@@ -84,18 +84,16 @@ const allMenuItems: MenuItemType[] = [
const MainLayout: React.FC = () => { const MainLayout: React.FC = () => {
const [collapsed, setCollapsed] = useState(false); const [collapsed, setCollapsed] = useState(false);
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
const [drawerOpen, setDrawerOpen] = useState(false); const [drawerOpen, setDrawerOpen] = useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const user = JSON.parse(localStorage.getItem('user') || '{}'); const user = JSON.parse(localStorage.getItem('user') || '{}');
const { hasPermission } = usePermission(); const { hasPermission } = usePermission();
useEffect(() => { const screens = Grid.useBreakpoint();
const handleResize = () => setIsMobile(window.innerWidth < 768); const isMobile = !screens.sm; // < 576px (仅 xs)
window.addEventListener('resize', handleResize); const isTablet = (screens.sm || screens.md) && !screens.lg; // 576-991px
return () => window.removeEventListener('resize', handleResize); const isDesktop = !!screens.lg; // >= 992px
}, []);
// 按 permission 过滤菜单 // 按 permission 过滤菜单
const filterByPermission = (items: MenuItemType[]): MenuItemType[] => { const filterByPermission = (items: MenuItemType[]): MenuItemType[] => {
@@ -152,7 +150,7 @@ const MainLayout: React.FC = () => {
<Sider <Sider
trigger={null} trigger={null}
collapsible collapsible
collapsed={collapsed} collapsed={isTablet ? true : collapsed}
theme="light" theme="light"
style={{ background: '#fff', borderRight: '1px solid #e5e5e7' }} style={{ background: '#fff', borderRight: '1px solid #e5e5e7' }}
> >
@@ -163,12 +161,12 @@ const MainLayout: React.FC = () => {
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
color: '#1d1d1f', color: '#1d1d1f',
fontSize: collapsed ? 16 : 17, fontSize: (isTablet || collapsed) ? 16 : 17,
fontWeight: 600, fontWeight: 600,
borderBottom: '1px solid #e5e5e7', borderBottom: '1px solid #e5e5e7',
}} }}
> >
{collapsed ? '恭' : '恭学教育基地'} {(isTablet || collapsed) ? '恭' : '恭学教育基地'}
</div> </div>
{menuContent} {menuContent}
</Sider> </Sider>
@@ -200,7 +198,7 @@ const MainLayout: React.FC = () => {
<Button <Button
type="text" type="text"
icon={ icon={
isMobile ? ( isMobile || isTablet ? (
<MenuUnfoldOutlined /> <MenuUnfoldOutlined />
) : collapsed ? ( ) : collapsed ? (
<MenuUnfoldOutlined /> <MenuUnfoldOutlined />
@@ -208,7 +206,7 @@ const MainLayout: React.FC = () => {
<MenuFoldOutlined /> <MenuFoldOutlined />
) )
} }
onClick={() => (isMobile ? setDrawerOpen(true) : setCollapsed(!collapsed))} onClick={() => (isMobile || isTablet ? setDrawerOpen(true) : setCollapsed(!collapsed))}
/> />
<Dropdown <Dropdown
menu={{ menu={{
@@ -224,14 +222,14 @@ const MainLayout: React.FC = () => {
> >
<div style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8 }}> <div style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8 }}>
<Avatar icon={<UserOutlined />} /> <Avatar icon={<UserOutlined />} />
<span>{user.name || user.username || '用户'}</span> {isDesktop && <span>{user.name || user.username || '用户'}</span>}
</div> </div>
</Dropdown> </Dropdown>
</Header> </Header>
<Content <Content
style={{ style={{
margin: isMobile ? 12 : 24, margin: isMobile ? 12 : isTablet ? 16 : 24,
padding: isMobile ? 12 : 24, padding: isMobile ? 12 : isTablet ? 16 : 24,
background: '#fff', background: '#fff',
borderRadius: 12, borderRadius: 12,
overflow: 'auto', overflow: 'auto',