From 0416f58b3dc1bb3d8bbf77e2204bb94c1c3fc218 Mon Sep 17 00:00:00 2001 From: Leo <98382335+gaoziman@users.noreply.github.com> Date: Sun, 19 Oct 2025 21:48:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E9=A1=B6=E9=83=A8=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=E6=A0=8F=E5=B8=83=E5=B1=80=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构布局架构:移除侧边栏,采用顶部导航设计 - 实现 MainLayout 主布局组件 - 实现 Header 顶部导航栏(Logo + 水平菜单 + 用户功能区) - 实现 Footer 页脚组件 - 导航菜单包含:仪表盘、上传图片、图片库、链接管理、图片工具、存储配置、统计分析 --- src/layouts/MainLayout/Footer.tsx | 36 +++++++ src/layouts/MainLayout/Header.tsx | 168 +++++++++++++++++++++++++++++ src/layouts/MainLayout/Sidebar.tsx | 98 +++++++++++++++++ src/layouts/MainLayout/index.tsx | 26 +++++ 4 files changed, 328 insertions(+) create mode 100644 src/layouts/MainLayout/Footer.tsx create mode 100644 src/layouts/MainLayout/Header.tsx create mode 100644 src/layouts/MainLayout/Sidebar.tsx create mode 100644 src/layouts/MainLayout/index.tsx diff --git a/src/layouts/MainLayout/Footer.tsx b/src/layouts/MainLayout/Footer.tsx new file mode 100644 index 0000000..ce038f9 --- /dev/null +++ b/src/layouts/MainLayout/Footer.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Layout } from 'antd'; +import { GithubOutlined, HeartFilled } from '@ant-design/icons'; + +const { Footer: AntFooter } = Layout; + +export const Footer: React.FC = () => { + return ( + +
+ Made with by PicStack Team +
+
+ e.currentTarget.style.color = '#7C3AED'} + onMouseLeave={(e) => e.currentTarget.style.color = '#9CA3AF'} + > + + GitHub + + © 2025 PicStack. All rights reserved. +
+
+ ); +}; diff --git a/src/layouts/MainLayout/Header.tsx b/src/layouts/MainLayout/Header.tsx new file mode 100644 index 0000000..eeefc13 --- /dev/null +++ b/src/layouts/MainLayout/Header.tsx @@ -0,0 +1,168 @@ +import React from 'react'; +import { Layout, Space, Badge, Avatar, Dropdown, Menu } from 'antd'; +import { + BellOutlined, + SettingOutlined, + UserOutlined, + LogoutOutlined, + CloudUploadOutlined, + DashboardOutlined, + PictureOutlined, + LinkOutlined, + ToolOutlined, + DatabaseOutlined, + BarChartOutlined, +} from '@ant-design/icons'; +import { useNavigate, useLocation } from 'react-router-dom'; +import type { MenuProps } from 'antd'; + +const { Header: AntHeader } = Layout; + +export const Header: React.FC = () => { + const navigate = useNavigate(); + const location = useLocation(); + + // 主导航菜单项 + const navMenuItems: MenuProps['items'] = [ + { + key: '/dashboard', + icon: , + label: '仪表盘', + onClick: () => navigate('/dashboard'), + }, + { + key: '/upload', + icon: , + label: '上传图片', + onClick: () => navigate('/upload'), + }, + { + key: '/gallery', + icon: , + label: '图片库', + onClick: () => navigate('/gallery'), + }, + { + key: '/links', + icon: , + label: '链接管理', + onClick: () => navigate('/links'), + }, + { + key: '/tools', + icon: , + label: '图片工具', + onClick: () => navigate('/tools'), + }, + { + key: '/storage', + icon: , + label: '存储配置', + onClick: () => navigate('/storage'), + }, + { + key: '/analytics', + icon: , + label: '统计分析', + onClick: () => navigate('/analytics'), + }, + ]; + + // 用户菜单项 + const userMenuItems: MenuProps['items'] = [ + { + key: 'settings', + icon: , + label: '设置', + onClick: () => navigate('/settings'), + }, + { + type: 'divider', + }, + { + key: 'logout', + icon: , + label: '退出登录', + danger: true, + }, + ]; + + // 获取当前选中的菜单项 + const selectedKey = location.pathname === '/' ? '/dashboard' : location.pathname; + + return ( + + {/* Logo 区域 */} +
+
+ +
+ + PicStack + +
+ + {/* 中间导航菜单 */} +
+ +
+ + {/* 右侧操作区 */} +
+ + {/* 通知 */} + + + + + {/* 用户菜单 */} + +
+ } /> + 用户 +
+
+
+
+
+ ); +}; diff --git a/src/layouts/MainLayout/Sidebar.tsx b/src/layouts/MainLayout/Sidebar.tsx new file mode 100644 index 0000000..1092599 --- /dev/null +++ b/src/layouts/MainLayout/Sidebar.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { Layout, Menu } from 'antd'; +import { + DashboardOutlined, + CloudUploadOutlined, + PictureOutlined, + LinkOutlined, + ToolOutlined, + DatabaseOutlined, + BarChartOutlined, + SettingOutlined, +} from '@ant-design/icons'; +import { useNavigate, useLocation } from 'react-router-dom'; +import type { MenuProps } from 'antd'; + +const { Sider } = Layout; + +type MenuItem = Required['items'][number]; + +export const Sidebar: React.FC<{ collapsed: boolean }> = ({ collapsed }) => { + const navigate = useNavigate(); + const location = useLocation(); + + const menuItems: MenuItem[] = [ + { + key: '/dashboard', + icon: , + label: '仪表盘', + onClick: () => navigate('/dashboard'), + }, + { + key: '/upload', + icon: , + label: '上传图片', + onClick: () => navigate('/upload'), + }, + { + key: '/gallery', + icon: , + label: '图片库', + onClick: () => navigate('/gallery'), + }, + { + key: '/links', + icon: , + label: '链接管理', + onClick: () => navigate('/links'), + }, + { + key: '/tools', + icon: , + label: '图片工具', + onClick: () => navigate('/tools'), + }, + { + key: '/storage', + icon: , + label: '存储配置', + onClick: () => navigate('/storage'), + }, + { + key: '/analytics', + icon: , + label: '统计分析', + onClick: () => navigate('/analytics'), + }, + { + type: 'divider', + }, + { + key: '/settings', + icon: , + label: '设置', + onClick: () => navigate('/settings'), + }, + ]; + + // 获取当前激活的菜单项 + const selectedKey = location.pathname === '/' ? '/dashboard' : location.pathname; + + return ( + + + + ); +}; diff --git a/src/layouts/MainLayout/index.tsx b/src/layouts/MainLayout/index.tsx new file mode 100644 index 0000000..1101841 --- /dev/null +++ b/src/layouts/MainLayout/index.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Layout } from 'antd'; +import { Outlet } from 'react-router-dom'; +import { Header } from './Header'; +import { Footer } from './Footer'; + +const { Content } = Layout; + +export const MainLayout: React.FC = () => { + return ( + +
+ + + +