feat: 实现前端管理后台(React + Vite + Ant Design + Zustand)
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { Layout as AntLayout, Menu, Dropdown, Space, Button, theme } from 'antd';
|
||||
import {
|
||||
VideoCameraOutlined,
|
||||
SettingOutlined,
|
||||
FileTextOutlined,
|
||||
UserOutlined,
|
||||
LogoutOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useAuthStore } from '../store/auth';
|
||||
|
||||
const { Header, Sider, Content } = AntLayout;
|
||||
|
||||
export default function Layout() {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { user, clearAuth } = useAuthStore();
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
} = theme.useToken();
|
||||
|
||||
const menuItems = [
|
||||
{ key: '/videos', icon: <VideoCameraOutlined />, label: '视频库' },
|
||||
{ key: '/accounts', icon: <SettingOutlined />, label: '账号配置' },
|
||||
{ key: '/logs', icon: <FileTextOutlined />, label: '操作日志' },
|
||||
];
|
||||
|
||||
const handleMenuClick = ({ key }: { key: string }) => {
|
||||
navigate(key);
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
clearAuth();
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
const userMenuItems = [
|
||||
{ key: 'user', label: user?.username, disabled: true },
|
||||
{ key: 'role', label: `角色: ${user?.role === 'admin' ? '管理员' : '只读'}`, disabled: true },
|
||||
{ type: 'divider' as const },
|
||||
{ key: 'logout', icon: <LogoutOutlined />, label: '退出登录', onClick: handleLogout },
|
||||
];
|
||||
|
||||
return (
|
||||
<AntLayout style={{ minHeight: '100vh' }}>
|
||||
<Sider trigger={null} collapsible theme="light">
|
||||
<div
|
||||
style={{
|
||||
height: 64,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 16,
|
||||
}}
|
||||
>
|
||||
VOD 管理器
|
||||
</div>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[location.pathname]}
|
||||
items={menuItems}
|
||||
onClick={handleMenuClick}
|
||||
/>
|
||||
</Sider>
|
||||
<AntLayout>
|
||||
<Header style={{ padding: '0 24px', background: colorBgContainer }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', height: '100%' }}>
|
||||
<Dropdown menu={{ items: userMenuItems }} placement="bottomRight">
|
||||
<Button type="text">
|
||||
<Space>
|
||||
<UserOutlined />
|
||||
{user?.username}
|
||||
</Space>
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</Header>
|
||||
<Content
|
||||
style={{
|
||||
margin: 24,
|
||||
padding: 24,
|
||||
background: colorBgContainer,
|
||||
borderRadius: borderRadiusLG,
|
||||
minHeight: 280,
|
||||
}}
|
||||
>
|
||||
<Outlet />
|
||||
</Content>
|
||||
</AntLayout>
|
||||
</AntLayout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user