/**
* AdminLayout - 管理后台布局
*
* 布局:侧栏 248px + 顶栏 64px + 内容区
*/
import { useEffect, useState } from 'react'
import { Avatar, Button, Drawer, Dropdown, Layout, Menu, Spin, type MenuProps } from 'antd'
import {
ApiOutlined,
DashboardOutlined,
FileTextOutlined,
LogoutOutlined,
MenuFoldOutlined,
MenuOutlined,
MenuUnfoldOutlined,
SafetyOutlined,
SettingOutlined,
UserOutlined,
} from '@ant-design/icons'
import type { ReactNode } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import { useAuth } from '@/app/providers/auth-context'
import { useBreadcrumbs } from '@/lib/hooks/useBreadcrumbs'
import styles from './AdminLayout.module.css'
const { Content, Header, Sider } = Layout
const menuLabel = (testId: string, text: string) => (
{text}
)
const adminMenuItems: MenuProps['items'] = [
{
key: '/dashboard',
icon: ,
label: menuLabel('nav-dashboard', '总览'),
},
{
key: 'access-control',
icon: ,
label: menuLabel('nav-group-access-control', '访问控制'),
children: [
{ key: '/users', label: menuLabel('nav-users', '用户管理') },
{ key: '/roles', label: menuLabel('nav-roles', '角色管理') },
{ key: '/permissions', label: menuLabel('nav-permissions', '权限管理') },
],
},
{
key: 'logs',
icon: ,
label: menuLabel('nav-group-logs', '审计日志'),
children: [
{ key: '/logs/login', label: menuLabel('nav-login-logs', '登录日志') },
{ key: '/logs/operation', label: menuLabel('nav-operation-logs', '操作日志') },
],
},
{
key: 'integration',
icon: ,
label: menuLabel('nav-group-integration', '集成能力'),
children: [
{ key: '/webhooks', label: menuLabel('nav-webhooks', 'Webhooks') },
{ key: '/import-export', label: menuLabel('nav-import-export', '导入导出') },
],
},
{
key: 'profile',
icon: ,
label: menuLabel('nav-group-profile', '我的账户'),
children: [
{ key: '/profile', label: menuLabel('nav-profile', '个人资料') },
{ key: '/profile/security', label: menuLabel('nav-profile-security', '安全设置') },
],
},
]
const userMenuItems: MenuProps['items'] = [
{
key: '/webhooks',
icon: ,
label: menuLabel('nav-webhooks', 'Webhooks'),
},
{
key: 'profile',
icon: ,
label: menuLabel('nav-group-profile', '我的账户'),
children: [
{ key: '/profile', label: menuLabel('nav-profile', '个人资料') },
{ key: '/profile/security', label: menuLabel('nav-profile-security', '安全设置') },
],
},
]
interface AdminLayoutProps {
children?: ReactNode
}
export function AdminLayout({ children }: AdminLayoutProps) {
const [collapsed, setCollapsed] = useState(false)
const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false)
const [isMobile, setIsMobile] = useState(false)
const location = useLocation()
const navigate = useNavigate()
const { user, isAdmin, logout, isLoading } = useAuth()
const breadcrumbItems = useBreadcrumbs()
useEffect(() => {
const checkMobile = () => {
const nextIsMobile = window.innerWidth < 768
setIsMobile(nextIsMobile)
if (!nextIsMobile) {
setMobileDrawerOpen(false)
}
}
checkMobile()
window.addEventListener('resize', checkMobile)
return () => window.removeEventListener('resize', checkMobile)
}, [])
const openMobileDrawer = () => {
setMobileDrawerOpen(true)
}
const closeMobileDrawer = () => {
setMobileDrawerOpen(false)
}
const handleMobileMenuClick: MenuProps['onClick'] = (info) => {
navigate(info.key)
closeMobileDrawer()
}
const menuItems = isAdmin ? adminMenuItems : userMenuItems
const selectedKeys = [location.pathname]
const openKeys = collapsed
? []
: [
...(location.pathname.startsWith('/users')
|| location.pathname.startsWith('/roles')
|| location.pathname.startsWith('/permissions')
? ['access-control']
: []),
...(location.pathname.startsWith('/logs') ? ['logs'] : []),
...(location.pathname.startsWith('/webhooks')
|| location.pathname.startsWith('/import-export')
? ['integration']
: []),
...(location.pathname.startsWith('/profile') ? ['profile'] : []),
]
const handleMenuClick: MenuProps['onClick'] = (info) => {
navigate(info.key)
}
const handleBreadcrumbClick = (path: string) => {
navigate(path)
}
const handleLogout = () => {
void logout()
}
const userDropdownItems: MenuProps['items'] = [
{
key: 'profile',
icon: ,
label: '个人资料',
onClick: () => navigate('/profile'),
},
{
key: 'security',
icon: ,
label: '安全设置',
onClick: () => navigate('/profile/security'),
},
{ type: 'divider' },
{
key: 'logout',
icon: ,
label: '退出登录',
danger: true,
onClick: handleLogout,
},
]
if (isLoading) {
return (
)
}
return (
跳转到主要内容
{collapsed ? 'UMS' : '用户管理系统'}
{children || }
{collapsed ? 'UMS' : '用户管理系统'}}
placement="left"
onClose={closeMobileDrawer}
open={mobileDrawerOpen}
size="default"
className={styles.mobileDrawer}
styles={{ body: { padding: 0 } }}
>
)
}