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
+
+
+
+ );
+};
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 区域 */}
+
+
+ {/* 中间导航菜单 */}
+
+
+
+
+ {/* 右侧操作区 */}
+
+
+ {/* 通知 */}
+
+
+
+
+ {/* 用户菜单 */}
+
+
+
+
+
+
+ );
+};
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 (
+
+
+
+
+
+
+
+ );
+};