From 5ca19d11a452fea61f4e6c52eb8afc5a1d52c0c9 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Tue, 23 Dec 2025 11:55:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(components):=20=E6=96=B0=E5=A2=9E=20Global?= =?UTF-8?q?Sidebar=20=E5=85=A8=E5=B1=80=E5=8F=B3=E4=BE=A7=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E6=A0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 可收起/展开的侧边栏设计 - 收起状态显示图标菜单(股票数量、事件数量 Badge) - 展开状态复用 WatchSidebar 组件 - 支持未登录状态提示 - 毛玻璃背景 + 金色主题装饰 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/components/GlobalSidebar/index.js | 197 ++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 src/components/GlobalSidebar/index.js diff --git a/src/components/GlobalSidebar/index.js b/src/components/GlobalSidebar/index.js new file mode 100644 index 00000000..6ea5e5bc --- /dev/null +++ b/src/components/GlobalSidebar/index.js @@ -0,0 +1,197 @@ +/** + * GlobalSidebar - 全局右侧工具栏 + * + * 可收起/展开的侧边栏,包含关注股票和事件动态 + */ + +import React from 'react'; +import { + Box, + VStack, + Icon, + IconButton, + Tooltip, + Badge, + Spinner, + Center, +} from '@chakra-ui/react'; +import { ChevronLeft, ChevronRight, BarChart2, Star } from 'lucide-react'; +import { useNavigate } from 'react-router-dom'; +import { useGlobalSidebar } from '@/contexts/GlobalSidebarContext'; +import { useAuth } from '@/contexts/AuthContext'; +import { getEventDetailUrl } from '@/utils/idEncoder'; +import WatchSidebar from '@views/Profile/components/WatchSidebar'; + +/** + * 收起状态下的图标菜单 + */ +const CollapsedMenu = ({ watchlist, followingEvents, onToggle }) => { + return ( + + {/* 展开按钮 */} + + } + size="sm" + variant="ghost" + color="rgba(255, 255, 255, 0.6)" + _hover={{ color: 'rgba(212, 175, 55, 0.9)', bg: 'rgba(255, 255, 255, 0.05)' }} + onClick={onToggle} + aria-label="展开工具栏" + /> + + + {/* 关注股票图标 */} + + + + {watchlist.length > 0 && ( + + {watchlist.length > 99 ? '99+' : watchlist.length} + + )} + + + + {/* 事件动态图标 */} + + + + {followingEvents.length > 0 && ( + + {followingEvents.length > 99 ? '99+' : followingEvents.length} + + )} + + + + ); +}; + +/** + * GlobalSidebar 主组件 + */ +const GlobalSidebar = () => { + const { user } = useAuth(); + const navigate = useNavigate(); + + const { + isOpen, + toggle, + watchlist, + realtimeQuotes, + followingEvents, + eventComments, + loading, + unwatchStock, + unfollowEvent, + } = useGlobalSidebar(); + + // 未登录时不显示 + if (!user) { + return null; + } + + return ( + + {/* 加载状态 */} + {loading && ( +
+ +
+ )} + + {isOpen ? ( + /* 展开状态 */ + + {/* 收起按钮 */} + + + } + size="xs" + variant="ghost" + color="rgba(255, 255, 255, 0.4)" + _hover={{ color: 'rgba(212, 175, 55, 0.9)', bg: 'rgba(255, 255, 255, 0.05)' }} + onClick={toggle} + aria-label="收起工具栏" + /> + + + + {/* WatchSidebar 内容 */} + + navigate(`/company/${stock.stock_code}`)} + onEventClick={(event) => navigate(getEventDetailUrl(event.id))} + onCommentClick={(comment) => navigate(getEventDetailUrl(comment.event_id))} + onAddStock={() => navigate('/stocks')} + onAddEvent={() => navigate('/community')} + onUnwatch={unwatchStock} + onUnfollow={unfollowEvent} + /> + + + ) : ( + /* 收起状态 */ + + )} +
+ ); +}; + +export default GlobalSidebar;