From 4a99b10578cd8609d3d3e1bf901a09345098f6a4 Mon Sep 17 00:00:00 2001 From: "mula.liu" Date: Fri, 30 Jan 2026 13:00:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gemini-clipboard/clipboard-1769085744299.png | Bin 7034 -> 0 bytes .gemini-clipboard/clipboard-1769087429425.png | Bin 18514 -> 0 bytes .gemini-clipboard/clipboard-1769740914907.png | Bin 0 -> 49646 bytes .gemini-clipboard/clipboard-1769741905582.png | Bin 0 -> 7799 bytes frontend/src/App.jsx | 21 +- frontend/src/assets/logo-small.png | Bin 3307 -> 0 bytes .../src/components/MainLayout/AppHeader.css | 108 +++----- .../src/components/MainLayout/AppHeader.jsx | 162 ++++------- .../src/components/MainLayout/AppSider.jsx | 252 ++++++++++-------- .../src/components/MainLayout/MainLayout.css | 17 +- .../src/components/MainLayout/MainLayout.jsx | 6 +- .../ModernSidebar/ModernSidebar.css | 221 +++++++++++++++ .../ModernSidebar/ModernSidebar.jsx | 154 +++++++++++ frontend/src/index.css | 29 ++ frontend/src/stores/themeStore.js | 17 ++ frontend/src/stores/userStore.js | 4 +- 16 files changed, 672 insertions(+), 319 deletions(-) delete mode 100644 .gemini-clipboard/clipboard-1769085744299.png delete mode 100644 .gemini-clipboard/clipboard-1769087429425.png create mode 100644 .gemini-clipboard/clipboard-1769740914907.png create mode 100644 .gemini-clipboard/clipboard-1769741905582.png delete mode 100644 frontend/src/assets/logo-small.png create mode 100644 frontend/src/components/ModernSidebar/ModernSidebar.css create mode 100644 frontend/src/components/ModernSidebar/ModernSidebar.jsx create mode 100644 frontend/src/stores/themeStore.js diff --git a/.gemini-clipboard/clipboard-1769085744299.png b/.gemini-clipboard/clipboard-1769085744299.png deleted file mode 100644 index 8c41fecd863787277176af443b4fb3b95eee8bd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7034 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 I=@&2m2W5l^YybcN diff --git a/.gemini-clipboard/clipboard-1769087429425.png b/.gemini-clipboard/clipboard-1769087429425.png deleted file mode 100644 index 0d29001f8fb68d2861ebed2a30bd2158df8c8aec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18514 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 diff --git a/.gemini-clipboard/clipboard-1769740914907.png b/.gemini-clipboard/clipboard-1769740914907.png new file mode 100644 index 0000000000000000000000000000000000000000..b38ad02b598a9aeaeb8efa25e00d19d2b12573e5 GIT binary patch literal 49646 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'r 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 literal 0 HcmV?d00001 diff --git a/.gemini-clipboard/clipboard-1769741905582.png b/.gemini-clipboard/clipboard-1769741905582.png new file mode 100644 index 0000000000000000000000000000000000000000..05e118dc59c404a70d9964d1a10f27e310634fa2 GIT binary patch literal 7799 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 Sj)*^Ut&*IYY=yLG;Qs(qftjEH literal 0 HcmV?d00001 diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 6d573fc..eabb62f 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,6 +1,8 @@ +import { useEffect } from 'react' import { BrowserRouter, Routes, Route, Navigate, useParams, Outlet } from 'react-router-dom' -import { ConfigProvider } from 'antd' +import { ConfigProvider, theme } from 'antd' import zhCN from 'antd/locale/zh_CN' +import useThemeStore from '@/stores/themeStore' import Login from '@/pages/Login/Login' import ProjectList from '@/pages/ProjectList/ProjectList' import DocumentPage from '@/pages/Document/DocumentPage' @@ -35,8 +37,23 @@ function LayoutWrapper() { } function App() { + const { isDarkMode } = useThemeStore() + + useEffect(() => { + if (isDarkMode) { + document.body.classList.add('dark') + } else { + document.body.classList.remove('dark') + } + }, [isDarkMode]) + return ( - + } /> diff --git a/frontend/src/assets/logo-small.png b/frontend/src/assets/logo-small.png deleted file mode 100644 index 099c476970053213f3f0dbe2421b26789f04c38b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3307 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 Rx%gfH`r0P&O4#F={{dEbKDPh> diff --git a/frontend/src/components/MainLayout/AppHeader.css b/frontend/src/components/MainLayout/AppHeader.css index 10b0574..6429ab2 100644 --- a/frontend/src/components/MainLayout/AppHeader.css +++ b/frontend/src/components/MainLayout/AppHeader.css @@ -1,12 +1,13 @@ .app-header { - background: #fff; + background: var(--header-bg); padding: 0 24px; display: flex; align-items: center; justify-content: space-between; box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); height: 64px; - border-bottom: 1px solid #f0f0f0; + border-bottom: 1px solid var(--border-color); + color: var(--text-color); } /* 左侧区域 */ @@ -25,26 +26,13 @@ transition: width 0.2s; } -.logo-small { - width: 40px; - height: 40px; - border-radius: 8px; - transition: all 0.2s; -} - -.logo-full { - height: 32px; - width: auto; - transition: all 0.2s; -} - .trigger { font-size: 18px; cursor: pointer; transition: color 0.3s; padding: 8px; border-radius: 4px; - color: rgba(0, 0, 0, 0.65); + color: var(--text-color-secondary); display: flex; align-items: center; } @@ -61,67 +49,29 @@ gap: 16px; } -.header-search { - border-radius: 16px; -} - .header-actions { display: flex; align-items: center; + gap: 16px; } -.header-icon { - font-size: 16px; - color: rgba(0, 0, 0, 0.65); - cursor: pointer; - transition: all 0.3s; - padding: 8px; - border-radius: 4px; +/* Icon Buttons */ +.header-icon-btn { display: flex; align-items: center; justify-content: center; -} - -.header-icon:hover { - color: #1677ff; - background: rgba(22, 119, 255, 0.08); -} - -.header-link { - font-size: 14px; - color: rgba(0, 0, 0, 0.65); + width: 40px; + height: 40px; + border-radius: 8px; cursor: pointer; - transition: all 0.3s; - padding: 6px 12px; - border-radius: 4px; - display: flex; - align-items: center; - gap: 4px; + color: var(--text-color-secondary); + transition: all 0.2s; + background: transparent; } -.header-link:hover { - color: #1677ff; - background: rgba(22, 119, 255, 0.08); -} - -.user-info { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 4px 8px; - border-radius: 4px; - transition: all 0.3s; -} - -.user-info:hover { - background: rgba(22, 119, 255, 0.08); -} - -.username { - font-size: 14px; - color: rgba(0, 0, 0, 0.88); - font-weight: 500; +.header-icon-btn:hover { + background-color: var(--item-hover-bg); + color: var(--text-color); } /* 通知面板样式 */ @@ -135,7 +85,7 @@ .popover-header { padding: 12px 16px; - border-bottom: 1px solid #f0f0f0; + border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; @@ -144,6 +94,7 @@ .popover-header .title { font-weight: 600; font-size: 16px; + color: var(--text-color); } .notification-list { @@ -155,23 +106,33 @@ padding: 12px 16px !important; cursor: pointer; transition: background 0.3s; + background: var(--bg-color); } .notification-item:hover { - background: #f5f5f5; + background: var(--item-hover-bg); } .notification-item.unread { background: #e6f7ff; } +/* Dark mode adjustment for unread */ +body.dark .notification-item.unread { + background: #111d2c; +} + .notification-item.unread:hover { background: #bae7ff; } +body.dark .notification-item.unread:hover { + background: #112a45; +} + .content-text { font-size: 13px; - color: #595959; + color: var(--text-color-secondary); margin-top: 4px; display: -webkit-box; -webkit-line-clamp: 2; @@ -181,16 +142,13 @@ .time { font-size: 12px; - color: #bfbfbf; + color: var(--text-color-secondary); + opacity: 0.8; margin-top: 4px; } .popover-footer { padding: 8px; - border-top: 1px solid #f0f0f0; + border-top: 1px solid var(--border-color); text-align: center; -} - -.ml-1 { - margin-left: 4px; } \ No newline at end of file diff --git a/frontend/src/components/MainLayout/AppHeader.jsx b/frontend/src/components/MainLayout/AppHeader.jsx index c5b88ad..ddb3bf7 100644 --- a/frontend/src/components/MainLayout/AppHeader.jsx +++ b/frontend/src/components/MainLayout/AppHeader.jsx @@ -1,68 +1,41 @@ import { useState, useEffect } from 'react' -import { Layout, Badge, Avatar, Dropdown, Space, Popover, List, Tabs, Button, Empty, Typography } from 'antd' +import { Layout, Badge, Avatar, Dropdown, Space, Popover, List, Tabs, Button, Empty, Typography, Segmented, Tooltip } from 'antd' import { useNavigate } from 'react-router-dom' import { MenuFoldOutlined, MenuUnfoldOutlined, BellOutlined, - QuestionCircleOutlined, - FileTextOutlined, - CustomerServiceOutlined, - UserOutlined, - CheckOutlined, ProjectOutlined, TeamOutlined, NotificationOutlined, + MoonOutlined, + SunOutlined, + GlobalOutlined } from '@ant-design/icons' import useUserStore from '@/stores/userStore' import useNotificationStore from '@/stores/notificationStore' +import useThemeStore from '@/stores/themeStore' import { getNotifications, getUnreadCount, markAsRead, markAllAsRead } from '@/api/notification' import Toast from '@/components/Toast/Toast' -import headerMenuData from '../../data/headerMenuData.json' import './AppHeader.css' const { Header } = Layout const { Text } = Typography -// 图标映射 -const iconMap = { - QuestionCircleOutlined: , - FileTextOutlined: , - CustomerServiceOutlined: , -} - -function AppHeader({ collapsed, onToggle }) { +function AppHeader({ collapsed, onToggle, showLogo = true }) { const navigate = useNavigate() - const { user, logout } = useUserStore() + const { user } = useUserStore() const { unreadCount, fetchUnreadCount, decrementUnreadCount, resetUnreadCount } = useNotificationStore() - - // 用户下拉菜单 - const userMenuItems = [ - { - key: 'profile', - label: '个人中心', - }, - { - key: 'settings', - label: '账户设置', - }, - { - type: 'divider', - }, - { - key: 'logout', - label: '退出登录', - }, - ] + const { isDarkMode, toggleTheme } = useThemeStore() const [notifications, setNotifications] = useState([]) const [loading, setLoading] = useState(false) const [popoverVisible, setPopoverVisible] = useState(false) + const [lang, setLang] = useState('zh') useEffect(() => { if (user) { fetchUnreadCount() - // 每 2 分钟轮询一次 const timer = setInterval(fetchUnreadCount, 120000) return () => clearInterval(timer) } @@ -83,7 +56,7 @@ function AppHeader({ collapsed, onToggle }) { const handleMarkRead = async (id) => { try { await markAsRead(id) - setNotifications(notifications.map(n => n.id === id ? { ...n, is_read: 1 } : n)) + setNotifications(notifications.map(n => n.id === id ? { ...n, is_read: true } : n)) decrementUnreadCount() } catch (error) { console.error('Mark read error:', error) @@ -93,7 +66,7 @@ function AppHeader({ collapsed, onToggle }) { const handleMarkAllRead = async () => { try { await markAllAsRead() - setNotifications(notifications.map(n => ({ ...n, is_read: 1 }))) + setNotifications(notifications.map(n => ({ ...n, is_read: true }))) resetUnreadCount() Toast.success('操作成功', '所有通知已标记为已读') } catch (error) { @@ -161,73 +134,46 @@ function AppHeader({ collapsed, onToggle }) { ) - const handleUserMenuClick = ({ key }) => { - if (key === 'logout') { - logout() - Toast.success('退出成功', '您已安全退出') - navigate('/login') - } else if (key === 'profile') { - navigate('/profile') - } else if (key === 'settings') { - Toast.info('开发中', '账户设置功能正在开发中') - } - } - - const handleHeaderMenuClick = (key) => { - console.log('Header menu clicked:', key) - if (key === 'support') { - Toast.info('开发中', '支持功能正在开发中') - } - } - - // 获取用户头像URL - const getUserAvatarUrl = () => { - if (!user?.avatar) return null - // avatar 字段存储的是相对路径,如:2/avatar/xxx.jpg - // 需要转换为 API 端点: /api/v1/auth/avatar/{user_id}/{filename} - const parts = user.avatar.split('/') - if (parts.length >= 3) { - const userId = parts[0] - const filename = parts[2] - return `/api/v1/auth/avatar/${userId}/${filename}` - } - return null - } - return ( -
+
{/* 左侧:Logo + 折叠按钮 */} -
- {/* Logo 区域 */} -
- logo -

NexDocus

-
+ {showLogo && ( +
+ {/* Logo 区域 */} +
+ logo +

NexDocus

+
- {/* 折叠按钮 */} -
- {collapsed ? : } + {/* 折叠按钮 */} +
+ {collapsed ? : } +
-
+ )} + {!showLogo &&
} {/* Spacer if left is empty */} - {/* 右侧:功能按钮 + 用户信息 */} + {/* 右侧:功能按钮 */}
- {/* 功能图标 */} - {/* 动态渲染 header 菜单 */} - {headerMenuData.map((item) => ( -
handleHeaderMenuClick(item.key)} - > - {iconMap[item.icon]} - {item.label} -
- ))} + + {/* 1. 主题切换 */} +
+ {isDarkMode ? : } +
- {/* 消息中心 */} + {/* 2. 语言切换 */} + + + {/* 3. 消息通知 */} -
- - +
+ + - 消息
- {/* 用户下拉菜单 */} - -
- } src={getUserAvatarUrl()} /> - {user?.nickname || user?.username || 'User'} -
-
) } -export default AppHeader +export default AppHeader \ No newline at end of file diff --git a/frontend/src/components/MainLayout/AppSider.jsx b/frontend/src/components/MainLayout/AppSider.jsx index bfb8939..33da543 100644 --- a/frontend/src/components/MainLayout/AppSider.jsx +++ b/frontend/src/components/MainLayout/AppSider.jsx @@ -1,5 +1,4 @@ import { useState, useEffect } from 'react' -import { Layout, Menu, Badge, message } from 'antd' import { useNavigate, useLocation } from 'react-router-dom' import { DashboardOutlined, @@ -14,34 +13,40 @@ import { FileTextOutlined, SafetyOutlined, TeamOutlined, + ProjectOutlined, + RocketOutlined, + ReadOutlined, + BookOutlined, } from '@ant-design/icons' +import { message } from 'antd' import { getUserMenus } from '@/api/menu' -import './AppSider.css' - -const { Sider } = Layout +import useUserStore from '@/stores/userStore' +import ModernSidebar from '../ModernSidebar/ModernSidebar' // 图标映射 const iconMap = { - DashboardOutlined, - DesktopOutlined, - GlobalOutlined, - CloudServerOutlined, - UserOutlined, - AppstoreOutlined, - SettingOutlined, - BlockOutlined, - FolderOutlined, - FileTextOutlined, - SafetyOutlined, - TeamOutlined, + DashboardOutlined: , + DesktopOutlined: , + GlobalOutlined: , + CloudServerOutlined: , + UserOutlined: , + AppstoreOutlined: , + SettingOutlined: , + BlockOutlined: , + FolderOutlined: , + FileTextOutlined: , + SafetyOutlined: , + TeamOutlined: , + ProjectOutlined: , + ReadOutlined: , + BookOutlined: , } function AppSider({ collapsed, onToggle }) { const navigate = useNavigate() const location = useLocation() - const [openKeys, setOpenKeys] = useState([]) - const [menuData, setMenuData] = useState([]) - const [loading, setLoading] = useState(true) + const { user, logout } = useUserStore() + const [menuGroups, setMenuGroups] = useState([]) // 加载菜单数据 useEffect(() => { @@ -52,120 +57,137 @@ function AppSider({ collapsed, onToggle }) { try { const res = await getUserMenus() if (res.data) { - setMenuData(res.data) + // 过滤菜单:只显示 type=1 (目录) 和 type=2 (菜单) + const validMenus = res.data.filter(item => [1, 2].includes(item.menu_type)) + transformMenuData(validMenus) } } catch (error) { console.error('Load menus error:', error) message.error('加载菜单失败') - } finally { - setLoading(false) } } - // 根据当前路径获取应该打开的父菜单 - const getDefaultOpenKeys = () => { + const transformMenuData = (data) => { + const groups = [] + + // 默认组 (用于存放一级菜单即是叶子节点的情况) + const defaultGroup = { + title: '', // 空标题或 '通用' + items: [] + } + + data.forEach(item => { + // 检查是否有子菜单 + const validChildren = item.children ? item.children.filter(child => [1, 2].includes(child.menu_type)) : [] + + if (validChildren.length > 0) { + // 一级菜单作为组标题 + const groupItems = validChildren.map(child => { + const icon = typeof child.icon === 'string' ? (iconMap[child.icon] || ) : child.icon + return { + key: child.menu_code, + label: child.menu_name, + icon: icon, + path: child.path + } + }) + + groups.push({ + title: item.menu_name, // e.g. "系统管理" + items: groupItems + }) + } else { + // 一级菜单是叶子节点,放入默认组 + const icon = typeof item.icon === 'string' ? (iconMap[item.icon] || ) : item.icon + defaultGroup.items.push({ + key: item.menu_code, + label: item.menu_name, + icon: icon, + path: item.path + }) + } + }) + + // 如果默认组有内容,放在最前面 + if (defaultGroup.items.length > 0) { + groups.unshift(defaultGroup) + } + + setMenuGroups(groups) + } + + const handleNavigate = (key, item) => { + if (item.path) { + navigate(item.path) + } + } + + const handleLogout = () => { + logout() + navigate('/login') + } + + const handleProfileClick = () => { + navigate('/profile') + } + + // 获取当前激活的 key + // 简单匹配 path + const getActiveKey = () => { const path = location.pathname - for (const item of menuData) { - if (item.children) { - const hasChild = item.children.some((c) => c.path === path) - if (hasChild) { - return [item.menu_code] - } - } - } - return [] - } - - // 监听菜单数据加载完成,初始化打开的父菜单 - useEffect(() => { - if (menuData.length > 0 && openKeys.length === 0) { - const defaultKeys = getDefaultOpenKeys() - setOpenKeys(defaultKeys) - } - }, [menuData]) - - const handleMenuClick = ({ key }) => { - // 查找对应的路径 - for (const item of menuData) { - if (item.menu_code === key && item.path) { - navigate(item.path) - return - } - if (item.children) { - const child = item.children.find((c) => c.menu_code === key) - if (child && child.path) { - navigate(child.path) - return - } - } - } - } - - const handleOpenChange = (keys) => { - setOpenKeys(keys) - } - - // 获取当前选中的菜单项 - const getSelectedKey = () => { - const path = location.pathname - for (const item of menuData) { - if (item.path === path) return item.menu_code - if (item.children) { - const child = item.children.find((c) => c.path === path) - if (child) return child.menu_code + // 遍历所有 items 找匹配 + for (const group of menuGroups) { + for (const item of group.items) { + if (item.path === path) return item.key } } return '' } - // 生成菜单项配置 - const getMenuItems = () => { - return menuData.map((item) => { - const IconComponent = iconMap[item.icon] - const icon = IconComponent ? : null + const logoNode = ( +
+ logo + {!collapsed && ( + NexDocus + )} +
+ ) - // 如果有子菜单 - if (item.children && item.children.length > 0) { - return { - key: item.menu_code, - icon: icon, - label: item.menu_name, - popupClassName: 'sider-submenu-popup', - children: item.children.map((child) => ({ - key: child.menu_code, - label: child.menu_name, - })), - } - } - - // 普通菜单项 - return { - key: item.menu_code, - icon: icon, - label: item.menu_name, - } - }) + // 获取用户头像URL + const getUserAvatarUrl = () => { + if (!user?.avatar) return null + // avatar 字段存储的是相对路径,如:2/avatar/xxx.jpg + // 需要转换为 API 端点: /api/v1/auth/avatar/{user_id}/{filename} + // 如果已经是 http 开头(第三方),则直接返回 + if (user.avatar.startsWith('http')) return user.avatar + + const parts = user.avatar.split('/') + if (parts.length >= 3) { + const userId = parts[0] + const filename = parts[2] + return `/api/v1/auth/avatar/${userId}/${filename}` + } + return null } + const userObj = user ? { + name: user.nickname || user.username, + role: user.role_name || 'Admin', + avatar: getUserAvatarUrl() + } : null + return ( - - {/* 菜单 */} - - + onCollapse={onToggle} + /> ) } diff --git a/frontend/src/components/MainLayout/MainLayout.css b/frontend/src/components/MainLayout/MainLayout.css index c79a46a..e71ef55 100644 --- a/frontend/src/components/MainLayout/MainLayout.css +++ b/frontend/src/components/MainLayout/MainLayout.css @@ -1,24 +1,27 @@ .main-layout { min-height: 100vh; display: flex; - flex-direction: column; - background: #fafafa; + flex-direction: row; /* Changed to row for Sider-Left layout */ + background: var(--bg-color-secondary); } .main-content-wrapper { display: flex; + flex-direction: column; flex: 1; - height: calc(100vh - 64px); - background: #fafafa; + height: 100vh; + background: var(--bg-color-secondary); + overflow: hidden; } .main-content { - background: #f5f5f5; + background: var(--bg-color-secondary); overflow-y: auto; flex: 1; + padding: 16px; } .content-wrapper { - padding: 8px; + padding: 0; min-height: 100%; -} +} \ No newline at end of file diff --git a/frontend/src/components/MainLayout/MainLayout.jsx b/frontend/src/components/MainLayout/MainLayout.jsx index 2c4ea0b..726c328 100644 --- a/frontend/src/components/MainLayout/MainLayout.jsx +++ b/frontend/src/components/MainLayout/MainLayout.jsx @@ -14,10 +14,10 @@ function MainLayout({ children }) { } return ( - - + + - +
{children} diff --git a/frontend/src/components/ModernSidebar/ModernSidebar.css b/frontend/src/components/ModernSidebar/ModernSidebar.css new file mode 100644 index 0000000..b22ec6b --- /dev/null +++ b/frontend/src/components/ModernSidebar/ModernSidebar.css @@ -0,0 +1,221 @@ +.modern-sidebar { + height: 100vh; + position: relative; + background: var(--sider-bg) !important; + border-right: 1px solid var(--border-color); + display: flex; + flex-direction: column; +} + +.modern-sidebar .ant-layout-sider-children { + display: flex; + flex-direction: column; + height: 100%; +} + +/* Header */ +.modern-sidebar-header { + padding: 24px 20px; + position: relative; + display: flex; + align-items: center; + height: 80px; + flex-shrink: 0; +} + +.logo-container { + display: flex; + align-items: center; + overflow: hidden; + white-space: nowrap; +} + +/* Collapse Trigger */ +.collapse-trigger { + position: absolute; + right: -12px; + top: 32px; + width: 24px; + height: 24px; + background: var(--bg-color); + border: 1px solid var(--border-color); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + z-index: 10; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + color: var(--text-color-secondary); + transition: all 0.3s; +} + +.collapse-trigger:hover { + color: #1677ff; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +/* Menu Area */ +.modern-sidebar-menu { + flex: 1; + overflow-y: auto; + padding: 0 16px; +} + +.modern-sidebar-menu::-webkit-scrollbar { + width: 4px; +} + +.modern-sidebar-menu::-webkit-scrollbar-thumb { + background: var(--border-color); + border-radius: 2px; +} + +/* Menu Group */ +.menu-group { + margin-bottom: 24px; +} + +.group-title { + font-size: 12px; + color: var(--text-color-secondary); + font-weight: 600; + letter-spacing: 0.5px; + margin-bottom: 12px; + padding-left: 12px; + text-transform: uppercase; +} + +/* Menu Item */ +.modern-sidebar-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 16px; + margin-bottom: 8px; + cursor: pointer; + border-radius: 12px; /* Rounded corners */ + transition: all 0.2s; + color: var(--text-color); + font-weight: 500; +} + +.modern-sidebar-item:hover { + background-color: var(--item-hover-bg); + color: var(--text-color); +} + +.modern-sidebar-item.active { + background-color: #2563eb; /* Royal Blue */ + color: #fff; + box-shadow: 0 4px 12px rgba(37, 99, 235, 0.25); +} + +.item-content { + display: flex; + align-items: center; + gap: 12px; +} + +.item-icon { + font-size: 18px; + display: flex; + align-items: center; +} + +.item-label { + font-size: 14px; +} + +.item-arrow { + font-size: 12px; + opacity: 0.8; +} + +/* Collapsed State */ +.modern-sidebar-item.collapsed { + justify-content: center; + padding: 12px; + border-radius: 12px; +} + +/* Footer */ +.modern-sidebar-footer { + padding: 16px; + flex-shrink: 0; + background: var(--sider-bg); +} + +.footer-link { + display: flex; + align-items: center; + gap: 8px; + color: var(--text-color-secondary); + font-size: 14px; + margin-bottom: 16px; + padding-left: 12px; + cursor: pointer; + transition: color 0.2s; +} + +.footer-link:hover { + color: var(--text-color); +} + +.footer-link.collapsed { + justify-content: center; + padding-left: 0; +} + +/* User Card */ +.user-card { + background-color: var(--bg-color-secondary); /* Light gray background */ + border-radius: 12px; + padding: 12px; + display: flex; + align-items: center; + justify-content: space-between; + transition: all 0.2s; +} + +.user-info { + display: flex; + align-items: center; + gap: 12px; + overflow: hidden; +} + +.user-details { + display: flex; + flex-direction: column; + overflow: hidden; +} + +.user-name { + font-size: 14px; + font-weight: 600; + color: var(--text-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.user-role { + font-size: 12px; + color: var(--text-color-secondary); + text-transform: uppercase; + font-weight: 500; +} + +.logout-btn { + color: var(--text-color-secondary); + cursor: pointer; + padding: 4px; + border-radius: 4px; + transition: all 0.2s; +} + +.logout-btn:hover { + background-color: var(--border-color); + color: #ef4444; /* Red for logout */ +} \ No newline at end of file diff --git a/frontend/src/components/ModernSidebar/ModernSidebar.jsx b/frontend/src/components/ModernSidebar/ModernSidebar.jsx new file mode 100644 index 0000000..d4ce841 --- /dev/null +++ b/frontend/src/components/ModernSidebar/ModernSidebar.jsx @@ -0,0 +1,154 @@ +import React, { useState } from 'react'; +import { Layout, Avatar, Tooltip, Button } from 'antd'; +import { + MenuUnfoldOutlined, + MenuFoldOutlined, + LogoutOutlined, + QuestionCircleOutlined, + RightOutlined, + LeftOutlined +} from '@ant-design/icons'; +import './ModernSidebar.css'; + +const { Sider } = Layout; + +const ModernSidebar = ({ + logo, + menuGroups = [], + activeKey, + onNavigate, + user, + onLogout, + onProfileClick, + collapsed, + onCollapse, + width = 260, + collapsedWidth = 80, + className = '', + style = {} +}) => { + + const handleItemClick = (item) => { + if (onNavigate) { + onNavigate(item.key, item); + } + }; + + const renderMenuItem = (item) => { + const isActive = activeKey === item.key; + + // 如果是折叠状态,只显示图标,并使用Tooltip + if (collapsed) { + return ( + +
handleItemClick(item)} + > +
{item.icon}
+
+
+ ); + } + + return ( +
handleItemClick(item)} + > +
+
{item.icon}
+ {item.label} +
+ {isActive && } +
+ ); + }; + + return ( + + {/* 顶部 Logo 区域 */} +
+
+ {logo} +
+ {/* 折叠按钮 - 悬浮在边缘 */} +
onCollapse && onCollapse(!collapsed)} + > + {collapsed ? : } +
+
+ + {/* 菜单列表区域 */} +
+ {menuGroups.map((group, index) => ( +
+ {!collapsed && group.title && ( +
{group.title}
+ )} +
+ {group.items.map(item => renderMenuItem(item))} +
+
+ ))} +
+ + {/* 底部区域 */} +
+ {/* 帮助支持 */} + {!collapsed && ( +
+ + 帮助支持 +
+ )} + {collapsed && ( +
+ +
+ )} + + {/* 用户卡片 */} +
+
+ + {user?.name?.[0]?.toUpperCase() || 'U'} + + {!collapsed && ( +
+
{user?.name || 'User'}
+
{user?.role || 'Member'}
+
+ )} +
+ {!collapsed && ( +
+ +
+ )} +
+
+
+ ); +}; + +export default ModernSidebar; diff --git a/frontend/src/index.css b/frontend/src/index.css index b0435a7..bfa1d8f 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,3 +1,32 @@ +:root { + --bg-color: #fff; + --bg-color-secondary: #fafafa; + --text-color: #000000e0; + --text-color-secondary: #00000073; + --border-color: #f0f0f0; + --header-bg: #fff; + --sider-bg: #fff; + --item-hover-bg: #f5f5f5; + --card-bg: #fff; +} + +body.dark { + --bg-color: #141414; + --bg-color-secondary: #1f1f1f; + --text-color: #ffffffd9; + --text-color-secondary: #ffffff73; + --border-color: #303030; + --header-bg: #141414; + --sider-bg: #141414; + --item-hover-bg: #1f1f1f; + --card-bg: #1f1f1f; +} + +body { + background-color: var(--bg-color); + color: var(--text-color); +} + .search-highlight { background-color: #ffd54f !important; color: black !important; diff --git a/frontend/src/stores/themeStore.js b/frontend/src/stores/themeStore.js new file mode 100644 index 0000000..8c7a6cd --- /dev/null +++ b/frontend/src/stores/themeStore.js @@ -0,0 +1,17 @@ +import { create } from 'zustand' +import { persist, createJSONStorage } from 'zustand/middleware' + +const useThemeStore = create( + persist( + (set) => ({ + isDarkMode: false, + toggleTheme: () => set((state) => ({ isDarkMode: !state.isDarkMode })), + }), + { + name: 'theme-storage', + storage: createJSONStorage(() => localStorage), + } + ) +) + +export default useThemeStore diff --git a/frontend/src/stores/userStore.js b/frontend/src/stores/userStore.js index b132ed2..a98f69d 100644 --- a/frontend/src/stores/userStore.js +++ b/frontend/src/stores/userStore.js @@ -2,7 +2,7 @@ * 用户状态管理 Store */ import { create } from 'zustand' -import { persist } from 'zustand/middleware' +import { persist, createJSONStorage } from 'zustand/middleware' const useUserStore = create( persist( @@ -26,7 +26,7 @@ const useUserStore = create( }), { name: 'user-storage', - getStorage: () => localStorage, + storage: createJSONStorage(() => localStorage), } ) )