133 lines
3.6 KiB
TypeScript
133 lines
3.6 KiB
TypeScript
import {
|
||
AppstoreOutlined,
|
||
LogoutOutlined,
|
||
MenuFoldOutlined,
|
||
MenuUnfoldOutlined,
|
||
UserOutlined,
|
||
} from '@ant-design/icons';
|
||
import { Avatar, Button, Dropdown, Layout, Menu, message } from 'antd';
|
||
import React, { useEffect, useState } from 'react';
|
||
import { history, Outlet, useLocation } from 'umi';
|
||
import { ConfigProvider } from 'antd';
|
||
import zhCN from 'antd/lib/locale/zh_CN';
|
||
import './index.less';
|
||
|
||
const { Header, Sider, Content } = Layout;
|
||
|
||
const MainLayout: React.FC = () => {
|
||
const [collapsed, setCollapsed] = useState(false);
|
||
const [username, setUsername] = useState('');
|
||
const location = useLocation();
|
||
|
||
useEffect(() => {
|
||
// 检查登录状态
|
||
const isLoggedIn = localStorage.getItem('isLoggedIn');
|
||
const currentUsername = localStorage.getItem('username');
|
||
|
||
if (!isLoggedIn) {
|
||
message.error('请先登录!');
|
||
history.push('/login');
|
||
return;
|
||
}
|
||
|
||
setUsername(currentUsername || '');
|
||
}, []);
|
||
|
||
const handleMenuClick = (key: string) => {
|
||
// 使用路由导航
|
||
history.push(`/${key}`);
|
||
};
|
||
|
||
const handleLogout = () => {
|
||
localStorage.removeItem('isLoggedIn');
|
||
localStorage.removeItem('username');
|
||
message.success('已退出登录');
|
||
history.push('/login');
|
||
};
|
||
|
||
const userMenu = (
|
||
<Menu>
|
||
<Menu.Item
|
||
key="profile"
|
||
icon={<UserOutlined />}
|
||
onClick={() => history.push('/profile')}
|
||
>
|
||
个人资料
|
||
</Menu.Item>
|
||
<Menu.Divider />
|
||
<Menu.Item key="logout" icon={<LogoutOutlined />} onClick={handleLogout}>
|
||
退出登录
|
||
</Menu.Item>
|
||
</Menu>
|
||
);
|
||
|
||
// 根据当前路径确定选中的菜单项
|
||
const getSelectedKey = () => {
|
||
const path = location.pathname;
|
||
if (path === '/images') return 'images';
|
||
if (path === '/profile') return 'profile';
|
||
return 'images'; // 默认选中镜像列表
|
||
};
|
||
|
||
return (
|
||
<ConfigProvider locale={zhCN}>
|
||
<Layout className="main-layout">
|
||
<Sider
|
||
trigger={null}
|
||
collapsible
|
||
collapsed={collapsed}
|
||
className="main-sider"
|
||
>
|
||
<div className="logo">{!collapsed && <span>VDI管理平台</span>}</div>
|
||
<Menu
|
||
theme="dark"
|
||
mode="inline"
|
||
selectedKeys={[getSelectedKey()]}
|
||
onClick={({ key }) => handleMenuClick(key)}
|
||
>
|
||
<Menu.Item key="userList" icon={<AppstoreOutlined />}>
|
||
用户
|
||
</Menu.Item>
|
||
<Menu.Item key="terminal" icon={<AppstoreOutlined />}>
|
||
终端
|
||
</Menu.Item>
|
||
<Menu.Item key="images" icon={<AppstoreOutlined />}>
|
||
镜像列表
|
||
</Menu.Item>
|
||
<Menu.Item key="profile" icon={<UserOutlined />}>
|
||
我的
|
||
</Menu.Item>
|
||
</Menu>
|
||
</Sider>
|
||
|
||
<Layout>
|
||
<Header className="main-header">
|
||
<Button
|
||
type="text"
|
||
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||
onClick={() => setCollapsed(!collapsed)}
|
||
className="trigger"
|
||
/>
|
||
|
||
<div className="header-right">
|
||
<span className="welcome-text">欢迎,{username}</span>
|
||
<Dropdown overlay={userMenu} placement="bottomRight">
|
||
<Avatar icon={<UserOutlined />} className="user-avatar" />
|
||
</Dropdown>
|
||
</div>
|
||
</Header>
|
||
|
||
<Content
|
||
className="main-content"
|
||
style={{ height: 'calc(100vh - 64px)', overflow: 'auto' }}
|
||
>
|
||
<Outlet />
|
||
</Content>
|
||
</Layout>
|
||
</Layout>
|
||
</ConfigProvider>
|
||
);
|
||
};
|
||
|
||
export default MainLayout;
|