forked from wangziqi/gongxue-base
feat: MainLayout 三端布局重构,使用 antd Grid.useBreakpoint()
This commit is contained in:
@@ -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',
|
||||||
|
|||||||
Reference in New Issue
Block a user