feat(auth): 实现登录注册功能并重构 App 组件
- 新增登录和注册页面组件
- 实现用户认证和权限管理逻辑
- 重构 App 组件,使用 Router 和 AuthProvider
- 添加管理员面板和论坛页面组件
Change-Id: Iaa4502616970e75e3268537f73c75dac8f60e24d
diff --git a/src/layouts/MainLayout.jsx b/src/layouts/MainLayout.jsx
new file mode 100644
index 0000000..fa4ccd4
--- /dev/null
+++ b/src/layouts/MainLayout.jsx
@@ -0,0 +1,141 @@
+import React from "react";
+import { Layout, Menu, Avatar, Dropdown } from "antd";
+import {
+ UserOutlined,
+ LogoutOutlined,
+ HomeOutlined,
+ AppstoreOutlined,
+ SettingOutlined,
+ CommentOutlined,
+ CloudDownloadOutlined,
+ UploadOutlined,
+ ToolOutlined,
+} from "@ant-design/icons";
+import { useNavigate, Link, useLocation } from "react-router-dom";
+import { useAuth } from "../features/auth/contexts/AuthContext";
+
+const { Header, Content, Footer } = Layout;
+
+// 路径与菜单key的映射
+const pathToMenuKey = {
+ "/": "1",
+ "/forum": "2",
+ "/pt": "3",
+ "/torrents": "4",
+ "/upload": "5",
+ "/tools": "6",
+ "/admin": "7",
+ "/profile": "profile",
+};
+
+const MainLayout = ({ children }) => {
+ const { user, logout } = useAuth();
+ const location = useLocation();
+
+ // 根据当前路径获取对应的菜单key
+ const getSelectedKey = () => {
+ const path = location.pathname;
+ return pathToMenuKey[path] || "1"; // 默认选中首页
+ };
+
+ const handleLogout = async () => {
+ await logout(); // logout 函数内已有消息提示和导航逻辑
+ };
+
+ // 用户菜单项
+ const userMenuItems = [
+ {
+ key: "profile",
+ icon: <UserOutlined />,
+ label: <Link to="/profile">个人资料</Link>,
+ },
+ {
+ type: "divider",
+ },
+ {
+ key: "logout",
+ icon: <LogoutOutlined />,
+ label: "退出登录",
+ onClick: handleLogout,
+ },
+ ];
+
+ // 主导航菜单项
+ const menuItems = [
+ {
+ key: "1",
+ icon: <HomeOutlined />,
+ label: <Link to="/">首页</Link>,
+ },
+ {
+ key: "2",
+ icon: <CommentOutlined />,
+ label: <Link to="/forum">论坛</Link>,
+ },
+ {
+ key: "3",
+ icon: <CloudDownloadOutlined />,
+ label: <Link to="/pt">PT</Link>,
+ },
+ {
+ key: "4",
+ icon: <AppstoreOutlined />,
+ label: <Link to="/torrents">种子列表</Link>,
+ },
+ {
+ key: "5",
+ icon: <UploadOutlined />,
+ label: <Link to="/upload">发布种子</Link>,
+ },
+ {
+ key: "6",
+ icon: <ToolOutlined />,
+ label: <Link to="/tools">工具箱</Link>,
+ }
+ ];
+
+ // 如果用户是管理员,添加管理面板菜单项
+ if (user?.role === "admin") {
+ menuItems.push({
+ key: "7",
+ icon: <SettingOutlined />,
+ label: <Link to="/admin">管理面板</Link>,
+ });
+ }
+
+ return (
+ <Layout className="min-h-screen">
+ <Header className="flex items-center justify-between px-6">
+ <div className="text-white text-xl font-bold">PT网站</div>
+ <Menu
+ theme="dark"
+ mode="horizontal"
+ selectedKeys={[getSelectedKey()]}
+ className="flex-1 justify-center"
+ style={{ maxWidth: "800px" }}
+ overflowedIndicator={null}
+ items={menuItems}
+ />
+ <div>
+ <Dropdown menu={{ items: userMenuItems }} placement="bottomRight">
+ <span className="flex items-center cursor-pointer text-white">
+ <Avatar src={user?.avatar} icon={<UserOutlined />} />
+ <span className="ml-2">{user?.username || "用户"}</span>
+ <span className="ml-1 text-xs opacity-80">
+ ({user?.role || "游客"})
+ </span>
+ </span>
+ </Dropdown>
+ </div>
+ </Header>
+ <Content className="p-6">
+ <div className="bg-white p-6 min-h-[280px] rounded">{children}</div>
+ </Content>
+ <Footer style={{ textAlign: "center" }}>
+ PT网站 ©{new Date().getFullYear()} Created by G12-Team
+ </Footer>
+ </Layout>
+ );
+};
+
+export default MainLayout;