import React, { useContext, useEffect, useMemo, useState } from 'react'; import { Link, useNavigate, useLocation } from 'react-router-dom'; import { UserContext } from '../context/User'; import { StatusContext } from '../context/Status'; import { useTranslation } from 'react-i18next'; import { API, getLogo, getSystemName, isAdmin, isMobile, showError, } from '../helpers'; import '../index.css'; import { IconCalendarClock, IconChecklistStroked, IconComment, IconCommentStroked, IconCreditCard, IconGift, IconHelpCircle, IconHistogram, IconHome, IconImage, IconKey, IconLayers, IconPriceTag, IconSetting, IconUser } from '@douyinfe/semi-icons'; import { Avatar, Dropdown, Layout, Nav, Switch, Divider } from '@douyinfe/semi-ui'; import { setStatusData } from '../helpers/data.js'; import { stringToColor } from '../helpers/render.js'; import { useSetTheme, useTheme } from '../context/Theme/index.js'; import { StyleContext } from '../context/Style/index.js'; // 自定义侧边栏按钮样式 const navItemStyle = { borderRadius: '6px', margin: '4px 8px', transition: 'all 0.3s ease' }; // 自定义侧边栏按钮悬停样式 const navItemHoverStyle = { backgroundColor: 'var(--semi-color-primary-light-default)', color: 'var(--semi-color-primary)' }; // 自定义侧边栏按钮选中样式 const navItemSelectedStyle = { backgroundColor: 'var(--semi-color-primary-light-default)', color: 'var(--semi-color-primary)', fontWeight: '600' }; // 自定义图标样式 const iconStyle = (itemKey, selectedKeys) => { return { fontSize: '18px', color: selectedKeys.includes(itemKey) ? 'var(--semi-color-primary)' : 'var(--semi-color-text-2)', transition: 'all 0.3s ease' }; }; const SiderBar = () => { const { t } = useTranslation(); const [styleState, styleDispatch] = useContext(StyleContext); const [statusState, statusDispatch] = useContext(StatusContext); const defaultIsCollapsed = localStorage.getItem('default_collapse_sidebar') === 'true'; const [selectedKeys, setSelectedKeys] = useState(['home']); const [isCollapsed, setIsCollapsed] = useState(defaultIsCollapsed); const [chatItems, setChatItems] = useState([]); const [openedKeys, setOpenedKeys] = useState([]); const theme = useTheme(); const setTheme = useSetTheme(); const location = useLocation(); // 预先计算所有可能的图标样式 const allItemKeys = useMemo(() => { const keys = ['home', 'channel', 'token', 'redemption', 'topup', 'user', 'log', 'midjourney', 'setting', 'about', 'chat', 'detail', 'pricing', 'task', 'playground', 'personal']; // 添加聊天项的keys for (let i = 0; i < chatItems.length; i++) { keys.push('chat' + i); } return keys; }, [chatItems]); // 使用useMemo一次性计算所有图标样式 const iconStyles = useMemo(() => { const styles = {}; allItemKeys.forEach(key => { styles[key] = iconStyle(key, selectedKeys); }); return styles; }, [allItemKeys, selectedKeys]); const routerMap = { home: '/', channel: '/channel', token: '/token', redemption: '/redemption', topup: '/topup', user: '/user', log: '/log', midjourney: '/midjourney', setting: '/setting', about: '/about', chat: '/chat', detail: '/detail', pricing: '/pricing', task: '/task', playground: '/playground', personal: '/personal', }; const workspaceItems = useMemo( () => [ { text: t('数据看板'), itemKey: 'detail', to: '/detail', icon: , className: localStorage.getItem('enable_data_export') === 'true' ? '' : 'tableHiddle', }, { text: t('API令牌'), itemKey: 'token', to: '/token', icon: , }, { text: t('使用日志'), itemKey: 'log', to: '/log', icon: , }, { text: t('绘图日志'), itemKey: 'midjourney', to: '/midjourney', icon: , className: localStorage.getItem('enable_drawing') === 'true' ? '' : 'tableHiddle', }, { text: t('任务日志'), itemKey: 'task', to: '/task', icon: , className: localStorage.getItem('enable_task') === 'true' ? '' : 'tableHiddle', } ], [ localStorage.getItem('enable_data_export'), localStorage.getItem('enable_drawing'), localStorage.getItem('enable_task'), t, ], ); const financeItems = useMemo( () => [ { text: t('钱包'), itemKey: 'topup', to: '/topup', icon: , }, { text: t('个人设置'), itemKey: 'personal', to: '/personal', icon: , }, ], [t], ); const adminItems = useMemo( () => [ { text: t('渠道'), itemKey: 'channel', to: '/channel', icon: , className: isAdmin() ? '' : 'tableHiddle', }, { text: t('兑换码'), itemKey: 'redemption', to: '/redemption', icon: , className: isAdmin() ? '' : 'tableHiddle', }, { text: t('用户管理'), itemKey: 'user', to: '/user', icon: , }, { text: t('系统设置'), itemKey: 'setting', to: '/setting', icon: , }, ], [isAdmin(), t], ); const chatMenuItems = useMemo( () => [ { text: 'Playground', itemKey: 'playground', to: '/playground', icon: , }, { text: t('聊天'), itemKey: 'chat', items: chatItems, icon: , }, ], [chatItems, t], ); useEffect(() => { const currentPath = location.pathname; const matchingKey = Object.keys(routerMap).find(key => routerMap[key] === currentPath); if (matchingKey) { setSelectedKeys([matchingKey]); } else if (currentPath.startsWith('/chat/')) { setSelectedKeys(['chat']); } let chats = localStorage.getItem('chats'); if (chats) { // console.log(chats); try { chats = JSON.parse(chats); if (Array.isArray(chats)) { let chatItems = []; for (let i = 0; i < chats.length; i++) { let chat = {}; for (let key in chats[i]) { chat.text = key; chat.itemKey = 'chat' + i; chat.to = '/chat/' + i; } // setRouterMap({ ...routerMap, chat: '/chat/' + i }) chatItems.push(chat); } setChatItems(chatItems); } } catch (e) { console.error(e); showError('聊天数据解析失败') } } setIsCollapsed(localStorage.getItem('default_collapse_sidebar') === 'true'); }, [location.pathname]); // Custom divider style const dividerStyle = { margin: '8px 0', opacity: 0.6, }; // Custom group label style const groupLabelStyle = { padding: '8px 16px', color: 'var(--semi-color-text-2)', fontSize: '12px', fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: '0.5px', }; return ( <> ); }; export default SiderBar;