new-api/web/src/components/SiderBar.js

387 lines
9.7 KiB
JavaScript
Raw Normal View History

2024-03-15 16:05:33 +08:00
import React, { useContext, useEffect, useMemo, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { UserContext } from '../context/User';
2024-03-04 16:39:42 +08:00
import { StatusContext } from '../context/Status';
import { useTranslation } from 'react-i18next';
2023-10-31 00:03:22 +08:00
2024-03-23 21:24:39 +08:00
import {
API,
getLogo,
getSystemName,
isAdmin,
isMobile,
showError,
} from '../helpers';
2023-10-31 00:03:22 +08:00
import '../index.css';
import {
IconCalendarClock, IconChecklistStroked,
2024-09-26 00:59:09 +08:00
IconComment, IconCommentStroked,
2024-03-15 16:05:33 +08:00
IconCreditCard,
2024-09-17 19:55:18 +08:00
IconGift, IconHelpCircle,
2024-03-15 16:05:33 +08:00
IconHistogram,
IconHome,
IconImage,
IconKey,
IconLayers,
2024-05-13 23:02:35 +08:00
IconPriceTag,
2024-03-15 16:05:33 +08:00
IconSetting,
2024-09-17 19:55:18 +08:00
IconUser
2023-10-31 00:03:22 +08:00
} from '@douyinfe/semi-icons';
import { Avatar, Dropdown, Layout, Nav, Switch, Divider } from '@douyinfe/semi-ui';
2024-05-13 23:02:35 +08:00
import { setStatusData } from '../helpers/data.js';
2024-09-17 19:55:18 +08:00
import { stringToColor } from '../helpers/render.js';
import { useSetTheme, useTheme } from '../context/Theme/index.js';
2024-12-11 16:11:27 +08:00
import { StyleContext } from '../context/Style/index.js';
2023-10-31 00:03:22 +08:00
// HeaderBar Buttons
2023-11-25 17:30:46 +08:00
const SiderBar = () => {
const { t } = useTranslation();
2024-12-11 16:11:27 +08:00
const [styleState, styleDispatch] = useContext(StyleContext);
2024-03-15 16:05:33 +08:00
const [statusState, statusDispatch] = useContext(StatusContext);
2024-03-23 21:24:39 +08:00
const defaultIsCollapsed =
2024-12-11 16:11:27 +08:00
localStorage.getItem('default_collapse_sidebar') === 'true';
2024-03-02 02:12:02 +08:00
2024-03-15 16:05:33 +08:00
const [selectedKeys, setSelectedKeys] = useState(['home']);
const [isCollapsed, setIsCollapsed] = useState(defaultIsCollapsed);
2024-10-12 21:06:49 +08:00
const [chatItems, setChatItems] = useState([]);
2024-09-17 19:55:18 +08:00
const theme = useTheme();
const setTheme = useSetTheme();
2024-03-02 02:12:02 +08:00
const routerMap = {
home: '/',
channel: '/channel',
token: '/token',
redemption: '/redemption',
topup: '/topup',
user: '/user',
log: '/log',
midjourney: '/midjourney',
setting: '/setting',
about: '/about',
chat: '/chat',
2024-03-23 21:24:39 +08:00
detail: '/detail',
2024-05-13 23:02:35 +08:00
pricing: '/pricing',
task: '/task',
2024-09-26 00:59:09 +08:00
playground: '/playground',
personal: '/personal',
};
const workspaceItems = useMemo(
2024-03-23 21:24:39 +08:00
() => [
{
text: t('数据看板'),
itemKey: 'detail',
to: '/detail',
icon: <IconCalendarClock />,
className:
localStorage.getItem('enable_data_export') === 'true'
? ''
: 'tableHiddle',
},
2024-03-23 21:24:39 +08:00
{
text: t('API令牌'),
itemKey: 'token',
to: '/token',
icon: <IconKey />,
2024-03-23 21:24:39 +08:00
},
{
text: t('使用日志'),
2024-03-23 21:24:39 +08:00
itemKey: 'log',
to: '/log',
icon: <IconHistogram />,
},
{
text: t('绘图日志'),
2024-03-23 21:24:39 +08:00
itemKey: 'midjourney',
to: '/midjourney',
icon: <IconImage />,
className:
localStorage.getItem('enable_drawing') === 'true'
? ''
2024-03-23 21:24:39 +08:00
: 'tableHiddle',
},
{
text: t('任务日志'),
itemKey: 'task',
to: '/task',
icon: <IconChecklistStroked />,
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: <IconCreditCard />,
},
2024-03-23 21:24:39 +08:00
{
text: t('个人设置'),
itemKey: 'personal',
to: '/personal',
icon: <IconUser />,
},
],
[t],
);
const adminItems = useMemo(
() => [
{
text: t('渠道'),
itemKey: 'channel',
to: '/channel',
icon: <IconLayers />,
className: isAdmin() ? '' : 'tableHiddle',
},
{
text: t('兑换码'),
itemKey: 'redemption',
to: '/redemption',
icon: <IconGift />,
className: isAdmin() ? '' : 'tableHiddle',
},
{
text: t('用户管理'),
itemKey: 'user',
to: '/user',
icon: <IconUser />,
},
{
text: t('系统设置'),
2024-03-23 21:24:39 +08:00
itemKey: 'setting',
to: '/setting',
icon: <IconSetting />,
},
],
[isAdmin(), t],
);
const chatMenuItems = useMemo(
() => [
{
text: 'Playground',
itemKey: 'playground',
to: '/playground',
icon: <IconCommentStroked />,
},
{
text: t('聊天'),
itemKey: 'chat',
items: chatItems,
icon: <IconComment />,
},
2024-03-23 21:24:39 +08:00
],
[chatItems, t],
2024-03-23 21:24:39 +08:00
);
2024-03-15 16:05:33 +08:00
useEffect(() => {
2024-03-23 21:24:39 +08:00
let localKey = window.location.pathname.split('/')[1];
if (localKey === '') {
2024-03-23 21:24:39 +08:00
localKey = 'home';
}
setSelectedKeys([localKey]);
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;
2024-10-12 21:06:49 +08:00
}
// setRouterMap({ ...routerMap, chat: '/chat/' + i })
chatItems.push(chat);
}
setChatItems(chatItems);
2024-10-12 21:06:49 +08:00
}
} catch (e) {
console.error(e);
showError('聊天数据解析失败')
}
2024-10-12 21:06:49 +08:00
}
setIsCollapsed(localStorage.getItem('default_collapse_sidebar') === 'true');
2024-03-15 16:05:33 +08:00
}, []);
2023-10-31 00:03:22 +08:00
// 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: 'normal',
};
2024-03-15 16:05:33 +08:00
return (
<>
2024-09-17 19:55:18 +08:00
<Nav
style={{ maxWidth: 200, height: '100%' }}
2024-09-17 19:55:18 +08:00
defaultIsCollapsed={
localStorage.getItem('default_collapse_sidebar') === 'true'
}
isCollapsed={isCollapsed}
onCollapseChange={(collapsed) => {
setIsCollapsed(collapsed);
}}
selectedKeys={selectedKeys}
renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
let chats = localStorage.getItem('chats');
if (chats) {
chats = JSON.parse(chats);
if (Array.isArray(chats) && chats.length > 0) {
for (let i = 0; i < chats.length; i++) {
routerMap['chat' + i] = '/chat/' + i;
}
if (chats.length > 1) {
// delete /chat
if (routerMap['chat']) {
delete routerMap['chat'];
}
} else {
// rename /chat to /chat/0
routerMap['chat'] = '/chat/0';
}
2024-10-12 21:06:49 +08:00
}
}
2024-09-17 19:55:18 +08:00
return (
<Link
style={{ textDecoration: 'none' }}
to={routerMap[props.itemKey]}
>
{itemElement}
</Link>
);
}}
onSelect={(key) => {
if (key.itemKey.toString().startsWith('chat')) {
styleDispatch({ type: 'SET_INNER_PADDING', payload: false });
} else {
styleDispatch({ type: 'SET_INNER_PADDING', payload: true });
}
2024-09-17 19:55:18 +08:00
setSelectedKeys([key.itemKey]);
}}
>
{/* Chat Section - Only show if there are chat items */}
{chatMenuItems.map((item) => {
if (item.items && item.items.length > 0) {
return (
<Nav.Sub
key={item.itemKey}
itemKey={item.itemKey}
text={item.text}
icon={item.icon}
>
{item.items.map((subItem) => (
<Nav.Item
key={subItem.itemKey}
itemKey={subItem.itemKey}
text={subItem.text}
/>
))}
</Nav.Sub>
);
} else {
return (
<Nav.Item
key={item.itemKey}
itemKey={item.itemKey}
text={item.text}
icon={item.icon}
/>
);
}
})}
{/* Divider */}
<Divider style={dividerStyle} />
{/* Workspace Section */}
{!isCollapsed && <div style={groupLabelStyle}>{t('控制台')}</div>}
{workspaceItems.map((item) => (
<Nav.Item
key={item.itemKey}
itemKey={item.itemKey}
text={item.text}
icon={item.icon}
className={item.className}
/>
))}
{/* Divider */}
<Divider style={dividerStyle} />
{/* Finance Management Section */}
{!isCollapsed && <div style={groupLabelStyle}>{t('个人中心')}</div>}
{financeItems.map((item) => (
<Nav.Item
key={item.itemKey}
itemKey={item.itemKey}
text={item.text}
icon={item.icon}
className={item.className}
/>
))}
{isAdmin() && (
<>
{/* Divider */}
<Divider style={dividerStyle} />
{/* Admin Section */}
{adminItems.map((item) => (
<Nav.Item
key={item.itemKey}
itemKey={item.itemKey}
text={item.text}
icon={item.icon}
className={item.className}
/>
))}
</>
)}
<Nav.Footer
collapseButton={true}
collapseText={(collapsed)=>
{
if(collapsed){
return t('展开侧边栏')
}
return t('收起侧边栏')
}
}
/>
2024-09-17 19:55:18 +08:00
</Nav>
2024-03-15 16:05:33 +08:00
</>
);
2023-10-31 00:03:22 +08:00
};
2023-11-25 17:30:46 +08:00
export default SiderBar;