blob: 99765e62e4e539eee7acce33e6f10ccf789e5703 [file] [log] [blame]
22301014bc4616f2025-06-03 16:59:44 +08001import { Outlet, useLocation, useNavigate } from 'react-router';
22301014b1477f72025-06-07 22:54:40 +08002import { Layout, Menu, Dropdown, Button, Flex } from 'antd';
3import { HomeOutlined, AppstoreOutlined, DownOutlined } from '@ant-design/icons';
4import { useEffect, useMemo } from 'react';
5import logo from "./assets/logo.png";
6import { useAppDispatch, useAppSelector } from './store/hooks';
7import { getUserInfo } from './feature/user/userSlice';
8import { logout } from './feature/auth/authSlice';
22301014bc4616f2025-06-03 16:59:44 +08009const { Header } = Layout;
10
11const AppLayout = () => {
12 const location = useLocation();
13 const navigate = useNavigate();
22301014b1477f72025-06-07 22:54:40 +080014 const userState = useAppSelector(state => state.user);
15 const dispatch = useAppDispatch();
16
17 useEffect(() => {
18 dispatch(getUserInfo())
19 }, [dispatch])
20
21 // 判断是否在登录、注册或找回密码页面
22 const isAuthPage = useMemo(() => {
23 return ['/login', '/register', '/forget'].includes(location.pathname);
24 }, [location.pathname]);
25
22301014bc4616f2025-06-03 16:59:44 +080026 // 导航项配置
27 const menuItems = [
28 {
29 key: 'home',
30 label: '主页',
31 icon: <HomeOutlined />,
32 path: '/',
33 },
34 {
35 key: 'tasks',
36 label: '任务清单',
37 icon: <AppstoreOutlined />,
38 path: '/tasks',
39 },
40 ];
41
22301014b1477f72025-06-07 22:54:40 +080042 // 处理登出逻辑
43 const handleLogout = () => {
44 dispatch(logout())
45 navigate('/login'); // 重定向到登录页
46 };
47
48 // 下拉菜单内容
49 const dropdownMenuItems = [
50 {
51 key: 'profile',
52 label: '个人中心',
53 onClick: () => navigate('/profile'),
54 },
55 {
56 key: 'logout',
57 label: '登出',
58 onClick: handleLogout,
59 },
60 ];
61
22301014bc4616f2025-06-03 16:59:44 +080062 return (
63 <Layout style={{ minHeight: '100vh', width: '100%' }}>
22301014b1477f72025-06-07 22:54:40 +080064 <Header className="header" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
65 {/* logo */}
66 <Flex justify='center' align='center'>
67 <img src={logo} alt="Logo" height='48px' />
68 <div style={{ color: 'white', marginLeft: '10px' }}>
69 创驿
70 </div>
71 </Flex>
72
73 <div style={{
74 height: '30px',
75 width: '1px',
76 backgroundColor: 'white',
77 margin: '0 20px',
78 }}></div>
79
80 {/* 中间导航菜单 */}
22301014bc4616f2025-06-03 16:59:44 +080081 <Menu
82 mode="horizontal"
22301014b1477f72025-06-07 22:54:40 +080083 theme="dark"
22301014bc4616f2025-06-03 16:59:44 +080084 selectedKeys={[location.pathname === '/' ? 'home' : location.pathname.slice(1)]}
85 items={menuItems.map(item => ({
86 ...item,
87 onClick: () => navigate(item.path),
88 }))}
22301014b1477f72025-06-07 22:54:40 +080089 style={{ flex: 1 }}
22301014bc4616f2025-06-03 16:59:44 +080090 />
22301014b1477f72025-06-07 22:54:40 +080091
92 {/* 右侧用户名和下拉菜单 */}
93 {!isAuthPage && (
94 <div style={{ display: 'flex', alignItems: 'center', color: 'white' }}>
95 <span>{userState.username}</span>
96 <Dropdown
97 trigger={['click']}
98 menu={{ items: dropdownMenuItems }}
99 >
100 <Button type="text" icon={<DownOutlined />} style={{ marginLeft: '10px', color: 'white' }} />
101 </Dropdown>
102 </div>
103 )}
22301014bc4616f2025-06-03 16:59:44 +0800104 </Header>
105 <Layout.Content style={{ padding: '24px' }}>
106 <Outlet />
107 </Layout.Content>
22301014b1477f72025-06-07 22:54:40 +0800108 <Layout.Footer style={{ textAlign: 'center' }}>
109 © 2025 创驿 - 愿做你创作路上的同行者
22301014bc4616f2025-06-03 16:59:44 +0800110 </Layout.Footer>
111 </Layout>
112 );
113};
114
22301014b1477f72025-06-07 22:54:40 +0800115export default AppLayout;