'use client'; import styles from './HomeSidebar.module.css'; import { useEffect, useState } from 'react'; import { SidebarChild, SidebarChildVO, } from '@/app/home/components/home-sidebar/HomeSidebarChild'; import { useRouter, usePathname } from 'next/navigation'; import { sidebarConfigList } from '@/app/home/components/home-sidebar/sidbarConfigList'; import langbotIcon from '@/app/assets/langbot-logo.webp'; import { systemInfo } from '@/app/infra/http/HttpClient'; import { getCloudServiceClientSync } from '@/app/infra/http'; import { useTranslation } from 'react-i18next'; import { Moon, Sun, Monitor } from 'lucide-react'; import { useTheme } from 'next-themes'; import { Popover, PopoverContent, PopoverTrigger, } from '@/components/ui/popover'; import { Button } from '@/components/ui/button'; import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'; import { LanguageSelector } from '@/components/ui/language-selector'; import { Badge } from '@/components/ui/badge'; import PasswordChangeDialog from '@/app/home/components/password-change-dialog/PasswordChangeDialog'; // TODO 侧边导航栏要加动画 export default function HomeSidebar({ onSelectedChangeAction, }: { onSelectedChangeAction: (sidebarChild: SidebarChildVO) => void; }) { // 路由相关 const router = useRouter(); const pathname = usePathname(); // 路由被动变化时处理 useEffect(() => { handleRouteChange(pathname); }, [pathname]); const [selectedChild, setSelectedChild] = useState(); const { theme, setTheme } = useTheme(); const { t } = useTranslation(); const [popoverOpen, setPopoverOpen] = useState(false); const [passwordChangeOpen, setPasswordChangeOpen] = useState(false); const [languageSelectorOpen, setLanguageSelectorOpen] = useState(false); const [starCount, setStarCount] = useState(null); useEffect(() => { initSelect(); if (!localStorage.getItem('token')) { localStorage.setItem('token', 'test-token'); localStorage.setItem('userEmail', 'test@example.com'); } getCloudServiceClientSync() .get('/api/v1/dist/info/repo') .then((response) => { const data = response as { repo: { stargazers_count: number } }; setStarCount(data.repo.stargazers_count); }) .catch((error) => { console.error('Failed to fetch GitHub star count:', error); }); return () => console.log('sidebar.unmounted'); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); function handleChildClick(child: SidebarChildVO) { setSelectedChild(child); handleRoute(child); onSelectedChangeAction(child); } function initSelect() { // 根据当前路径选择对应的菜单项 const currentPath = pathname; const matchedChild = sidebarConfigList.find( (childConfig) => childConfig.route === currentPath, ); if (matchedChild) { handleChildClick(matchedChild); } else { // 如果没有匹配的路径,则默认选择第一个 handleChildClick(sidebarConfigList[0]); } } function handleRoute(child: SidebarChildVO) { console.log(child); router.push(`${child.route}`); } function handleRouteChange(pathname: string) { // TODO 这段逻辑并不好,未来router封装好后改掉 // 判断在home下,并且路由更改的是自己的路由子组件则更新UI const routeList = pathname.split('/'); if ( routeList[1] === 'home' && sidebarConfigList.find((childConfig) => childConfig.route === pathname) ) { console.log('find success'); const routeSelectChild = sidebarConfigList.find( (childConfig) => childConfig.route === pathname, ); if (routeSelectChild) { setSelectedChild(routeSelectChild); } } } function handleLogout() { localStorage.removeItem('token'); localStorage.removeItem('userEmail'); window.location.href = '/login'; } return (
{/* LangBot、ICON区域 */}
{/* icon */} langbot-icon {/* 文字 */}
LangBot
{systemInfo?.version}
{/* 菜单列表,后期可升级成配置驱动 */}
{sidebarConfigList.map((config) => { return (
{ console.log('click:', config.id); handleChildClick(config); }} > {}} isSelected={ selectedChild !== undefined && selectedChild.id === config.id } icon={config.icon} name={config.name} />
); })}
{starCount !== null && (
{ window.open('https://github.com/langbot-app/LangBot', '_blank'); }} className="flex justify-center cursor-pointer p-2 rounded-lg hover:bg-accent/30 transition-colors" >
{starCount.toLocaleString()}
)} { // open docs.langbot.app const language = localStorage.getItem('langbot_language'); if (language === 'zh-Hans') { window.open( 'https://docs.langbot.app/zh/insight/guide.html', '_blank', ); } else if (language === 'zh-Hant') { window.open( 'https://docs.langbot.app/zh/insight/guide.html', '_blank', ); } else { window.open( 'https://docs.langbot.app/en/insight/guide.html', '_blank', ); } }} isSelected={false} icon={ } name={t('common.helpDocs')} /> { // 防止语言选择器打开时关闭popover if (!open && languageSelectorOpen) return; setPopoverOpen(open); }} > {}} isSelected={false} icon={ } name={t('common.accountOptions')} />
{t('common.theme')} { if (value) setTheme(value); }} className="justify-start" >
{t('common.language')}
{t('common.account')}
); }