返回 AiToEarn
index.tsx
1 /**
2 * LayoutSidebar - 左侧侧边栏布局组件
3 * 包含 Logo、主导航、底部功能区(余额、插件)、用户下拉菜单
4 * 支持展开/收缩两种状态
5 */
6 'use client'
7
8 import type { IRouterDataItem } from '../routerData'
9 import type { NavItemData } from './types'
10 import { useShallow } from 'zustand/shallow'
11 import { useNavigationLogic, useVisibleRouterData } from '@/app/layout/shared'
12 import { useSettingsModalStore } from '@/store/settingsModal'
13 import { useUserStore } from '@/store/user'
14 import { cn } from '@/utils/className'
15 import { BottomSection, LogoSection, NavSection, UserDropdownMenu } from './components'
16 import { ConfigManagerEntry } from './components/BottomSection/ConfigManagerEntry'
17 import { MyChannelsEntry } from './components/BottomSection/MyChannelsEntry'
18
19 /**
20 * 侧边栏主组件
21 */
22 function LayoutSidebar() {
23 const { currRouter, isAuthPage } = useNavigationLogic()
24 const visibleRoutes = useVisibleRouterData()
25
26 // 获取侧边栏状态和设置方法
27 const { sidebarCollapsed: collapsed, setSidebarCollapsed: setCollapsed } = useUserStore(
28 useShallow(state => ({
29 sidebarCollapsed: state.sidebarCollapsed,
30 setSidebarCollapsed: state.setSidebarCollapsed,
31 })),
32 )
33
34 const { openSettings } = useSettingsModalStore()
35
36 const mapNavItem = (item: IRouterDataItem): NavItemData => ({
37 path: item.path,
38 translationKey: item.translationKey,
39 icon: item.icon,
40 children: item.children?.map(mapNavItem),
41 })
42
43 // 首页、auth、websit 页面不显示侧边栏
44 if (isAuthPage) {
45 return null
46 }
47
48 // 转换路由数据为 NavSection 所需格式
49 const navItems = visibleRoutes.filter(item => item.translationKey !== 'myTasks').map(mapNavItem)
50
51 return (
52 <aside
53 className={cn(
54 'group sticky left-0 top-0 hidden h-screen flex-col border-r border-sidebar-border bg-sidebar p-3 transition-all duration-300 md:flex',
55 collapsed ? 'w-[68px] min-w-[68px]' : 'w-[240px] min-w-[240px]',
56 )}
57 >
58 {/* Logo 区域 - 固定 */}
59 <LogoSection collapsed={collapsed} onToggle={() => setCollapsed(!collapsed)} />
60
61 {/* 可滚动区域:主导航 */}
62 <div className="flex-1 min-h-0 overflow-y-auto overflow-x-hidden scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent">
63 <NavSection items={navItems} currentRoute={currRouter!} collapsed={collapsed} />
64 </div>
65
66 {/* 底部固定区域 - 不随滚动 */}
67 <div className="flex-shrink-0">
68 {/* 配置管理入口 */}
69 <div className="pb-1 flex flex-1">
70 <ConfigManagerEntry collapsed={collapsed} />
71 </div>
72
73 {/* 我的频道入口 */}
74 <div className="pb-1 flex flex-1">
75 <MyChannelsEntry collapsed={collapsed} />
76 </div>
77
78 {/* 底部功能区 */}
79 <BottomSection collapsed={collapsed} onOpenSettings={openSettings} />
80
81 {/* 用户下拉菜单 */}
82 <div className="mt-2 border-t border-sidebar-border pt-2">
83 <UserDropdownMenu collapsed={collapsed} onOpenSettings={openSettings} />
84 </div>
85 </div>
86 </aside>
87 )
88 }
89
90 export default LayoutSidebar
91
91 lines Plain Text