148 lines
3.7 KiB
TypeScript
148 lines
3.7 KiB
TypeScript
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
|
import { Layout, Menu, Dropdown, Avatar, message, Modal } from 'antd';
|
|
import {
|
|
DashboardOutlined,
|
|
QrcodeOutlined,
|
|
TeamOutlined,
|
|
SearchOutlined,
|
|
UserOutlined,
|
|
LogoutOutlined,
|
|
LockOutlined,
|
|
ExclamationCircleOutlined,
|
|
} from '@ant-design/icons';
|
|
import { authApi } from '@/services/api';
|
|
import './styles/AdminLayout.css';
|
|
import logo from '@/assets/img/logo.png?url';
|
|
|
|
const { Header, Sider, Content } = Layout;
|
|
|
|
function AdminLayout() {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const user = authApi.getCurrentUser();
|
|
|
|
const menuItems = [
|
|
{
|
|
key: 'dashboard',
|
|
icon: <DashboardOutlined />,
|
|
label: '控制台',
|
|
onClick: () => navigate('/admin/dashboard'),
|
|
},
|
|
{
|
|
key: 'generate',
|
|
icon: <QrcodeOutlined />,
|
|
label: '生成二维码',
|
|
onClick: () => navigate('/admin/generate'),
|
|
},
|
|
{
|
|
key: 'manage',
|
|
icon: <TeamOutlined />,
|
|
label: '企业管理',
|
|
onClick: () => navigate('/admin/manage'),
|
|
},
|
|
{
|
|
key: 'query',
|
|
icon: <SearchOutlined />,
|
|
label: '序列号查询',
|
|
onClick: () => navigate('/admin/query'),
|
|
},
|
|
];
|
|
|
|
const handleLogout = () => {
|
|
Modal.confirm({
|
|
title: '确认退出',
|
|
icon: <ExclamationCircleOutlined />,
|
|
content: '您确定要退出登录吗?',
|
|
okText: '确定',
|
|
cancelText: '取消',
|
|
onOk: async () => {
|
|
try {
|
|
await authApi.logout();
|
|
message.success('已退出登录');
|
|
navigate('/login');
|
|
} catch (error) {
|
|
message.error('退出失败');
|
|
}
|
|
},
|
|
});
|
|
};
|
|
|
|
const userMenuItems = [
|
|
{
|
|
key: 'profile',
|
|
icon: <UserOutlined />,
|
|
label: '用户资料',
|
|
onClick: () => navigate('/admin/profile'),
|
|
},
|
|
{
|
|
key: 'changePassword',
|
|
icon: <LockOutlined />,
|
|
label: '修改密码',
|
|
onClick: () => {
|
|
message.info('修改密码功能即将上线');
|
|
},
|
|
},
|
|
{
|
|
type: 'divider' as const,
|
|
},
|
|
{
|
|
key: 'logout',
|
|
icon: <LogoutOutlined />,
|
|
label: '退出登录',
|
|
onClick: handleLogout,
|
|
danger: true,
|
|
},
|
|
];
|
|
|
|
const getSelectedKey = () => {
|
|
const path = location.pathname;
|
|
if (path.includes('/dashboard')) return 'dashboard';
|
|
if (path.includes('/generate')) return 'generate';
|
|
if (path.includes('/manage')) return 'manage';
|
|
if (path.includes('/query')) return 'query';
|
|
if (path.includes('/profile')) return 'profile';
|
|
return 'dashboard';
|
|
};
|
|
|
|
return (
|
|
<Layout className="admin-layout">
|
|
<Sider
|
|
className="admin-sider"
|
|
width={256}
|
|
>
|
|
<div className="logo">
|
|
<img src={logo} alt="Logo" style={{ height: '40px' }} />
|
|
</div>
|
|
<Menu
|
|
theme="light"
|
|
mode="inline"
|
|
selectedKeys={[getSelectedKey()]}
|
|
items={menuItems}
|
|
className="admin-menu"
|
|
/>
|
|
</Sider>
|
|
|
|
<Layout>
|
|
<Header className="admin-header">
|
|
<div className="header-title">
|
|
{menuItems.find((item) => item.key === getSelectedKey())?.label}
|
|
</div>
|
|
<div className="header-right">
|
|
<Dropdown menu={{ items: userMenuItems }} placement="bottomRight">
|
|
<div className="user-info">
|
|
<Avatar icon={<UserOutlined />} />
|
|
<span className="username">{user?.name || user?.username}</span>
|
|
</div>
|
|
</Dropdown>
|
|
</div>
|
|
</Header>
|
|
|
|
<Content className="admin-content">
|
|
<Outlet />
|
|
</Content>
|
|
</Layout>
|
|
</Layout>
|
|
);
|
|
}
|
|
|
|
export default AdminLayout; |