refactor: Reorganize sidebar navigation and add personal settings route

This commit is contained in:
1808837298@qq.com
2025-03-07 17:22:37 +08:00
parent 7f74a9664e
commit fd22948ead
6 changed files with 254 additions and 118 deletions

View File

@@ -30,6 +30,7 @@ import { useTranslation } from 'react-i18next';
import { StatusContext } from './context/Status';
import { setStatusData } from './helpers/data.js';
import { API, showError } from './helpers';
import PersonalSetting from './components/PersonalSetting.js';
const Home = lazy(() => import('./pages/Home'));
const Detail = lazy(() => import('./pages/Detail'));
@@ -177,6 +178,16 @@ function App() {
</PrivateRoute>
}
/>
<Route
path='/personal'
element={
<PrivateRoute>
<Suspense fallback={<Loading></Loading>}>
<PersonalSetting />
</Suspense>
</PrivateRoute>
}
/>
<Route
path='/topup'
element={

View File

@@ -393,7 +393,7 @@ const PersonalSetting = () => {
</div>
</div>
</Modal>
<div style={{marginTop: 20}}>
<div>
<Card
title={
<Card.Meta

View File

@@ -28,7 +28,7 @@ import {
IconSetting,
IconUser
} from '@douyinfe/semi-icons';
import { Avatar, Dropdown, Layout, Nav, Switch } from '@douyinfe/semi-ui';
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';
@@ -65,35 +65,11 @@ const SiderBar = () => {
pricing: '/pricing',
task: '/task',
playground: '/playground',
personal: '/personal',
};
const headerButtons = useMemo(
const workspaceItems = useMemo(
() => [
{
text: 'Playground',
itemKey: 'playground',
to: '/playground',
icon: <IconCommentStroked />,
},
{
text: t('渠道'),
itemKey: 'channel',
to: '/channel',
icon: <IconLayers />,
className: isAdmin() ? '' : 'tableHiddle',
},
{
text: t('聊天'),
itemKey: 'chat',
items: chatItems,
icon: <IconComment />,
},
{
text: t('令牌'),
itemKey: 'token',
to: '/token',
icon: <IconKey />,
},
{
text: t('数据看板'),
itemKey: 'detail',
@@ -105,33 +81,19 @@ const SiderBar = () => {
: 'tableHiddle',
},
{
text: t('兑换码'),
itemKey: 'redemption',
to: '/redemption',
icon: <IconGift />,
className: isAdmin() ? '' : 'tableHiddle',
text: t('API令牌'),
itemKey: 'token',
to: '/token',
icon: <IconKey />,
},
{
text: t('钱包'),
itemKey: 'topup',
to: '/topup',
icon: <IconCreditCard />,
},
{
text: t('用户管理'),
itemKey: 'user',
to: '/user',
icon: <IconUser />,
className: isAdmin() ? '' : 'tableHiddle',
},
{
text: t('日志'),
text: t('使用日志'),
itemKey: 'log',
to: '/log',
icon: <IconHistogram />,
},
{
text: t('绘图'),
text: t('绘图日志'),
itemKey: 'midjourney',
to: '/midjourney',
icon: <IconImage />,
@@ -141,75 +103,148 @@ const SiderBar = () => {
: 'tableHiddle',
},
{
text: t('异步任务'),
text: t('任务日志'),
itemKey: 'task',
to: '/task',
icon: <IconChecklistStroked />,
className:
localStorage.getItem('enable_task') === 'true'
? ''
: 'tableHiddle',
},
{
text: t('设置'),
itemKey: 'setting',
to: '/setting',
icon: <IconSetting />,
},
localStorage.getItem('enable_task') === 'true'
? ''
: 'tableHiddle',
}
],
[
localStorage.getItem('enable_data_export'),
localStorage.getItem('enable_drawing'),
localStorage.getItem('enable_task'),
localStorage.getItem('chat_link'),
chatItems,
isAdmin(),
t,
],
);
const financeItems = useMemo(
() => [
{
text: t('钱包'),
itemKey: 'topup',
to: '/topup',
icon: <IconCreditCard />,
},
{
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('系统设置'),
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 />,
},
],
[chatItems, t],
);
useEffect(() => {
let localKey = window.location.pathname.split('/')[1];
if (localKey === '') {
localKey = 'home';
}
setSelectedKeys([localKey]);
let chatLink = localStorage.getItem('chat_link');
if (!chatLink) {
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('聊天数据解析失败')
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');
}, []);
// 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',
};
return (
<>
<Nav
style={{ maxWidth: 220, height: '100%' }}
style={{ maxWidth: 200, height: '100%' }}
defaultIsCollapsed={
localStorage.getItem('default_collapse_sidebar') === 'true'
}
@@ -219,27 +254,27 @@ const SiderBar = () => {
}}
selectedKeys={selectedKeys}
renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
let chatLink = localStorage.getItem('chat_link');
if (!chatLink) {
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';
}
}
let chatLink = localStorage.getItem('chat_link');
if (!chatLink) {
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';
}
}
}
}
return (
<Link
style={{ textDecoration: 'none' }}
@@ -249,7 +284,6 @@ const SiderBar = () => {
</Link>
);
}}
items={headerButtons}
onSelect={(key) => {
if (key.itemKey.toString().startsWith('chat')) {
styleDispatch({ type: 'SET_INNER_PADDING', payload: false });
@@ -258,12 +292,101 @@ const SiderBar = () => {
}
setSelectedKeys([key.itemKey]);
}}
footer={
<>
</>
}
>
<Nav.Footer collapseButton={true}></Nav.Footer>
{/* Chat Section - Only show if there are chat items */}
{chatItems.length > 0 && (
<>
{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('收起侧边栏')
}
}
/>
</Nav>
</>
);

View File

@@ -621,6 +621,7 @@
"窗口等待": "window wait",
"失败": "Failed",
"绘图": "Drawing",
"绘图日志": "Drawing log",
"放大": "Upscalers",
"微妙放大": "Upscale (Subtle)",
"创造放大": "Upscale (Creative)",
@@ -1120,7 +1121,7 @@
"知识库 ID": "Knowledge Base ID",
"请输入知识库 ID例如123456": "Please enter knowledge base ID, e.g.: 123456",
"可选值": "Optional value",
"异步任务": "Async task",
"任务日志": "Task log",
"你好": "Hello",
"你好,请问有什么可以帮助您的吗?": "Hello, how may I help you?",
"用户分组": "Your default group",
@@ -1335,5 +1336,7 @@
"Claude思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比": "Claude thinking adaptation BudgetTokens = MaxTokens * BudgetTokens percentage",
"思考适配 BudgetTokens 百分比": "Thinking adaptation BudgetTokens percentage",
"0.1-1之间的小数": "Decimal between 0.1 and 1",
"模型相关设置": "Model related settings"
"模型相关设置": "Model related settings",
"收起侧边栏": "Collapse sidebar",
"展开侧边栏": "Expand sidebar"
}

View File

@@ -18,6 +18,8 @@ const CLAUDE_HEADER = {
const CLAUDE_DEFAULT_MAX_TOKENS = {
'default': 8192,
"claude-3-haiku-20240307": 4096,
"claude-3-opus-20240229": 4096,
'claude-3-7-sonnet-20250219-thinking': 8192,
}

View File

@@ -18,9 +18,6 @@ const Setting = () => {
const [tabActiveKey, setTabActiveKey] = useState('1');
let panes = [
{
tab: t('个人设置'),
content: <PersonalSetting />,
itemKey: 'personal',
},
];
@@ -61,7 +58,7 @@ const Setting = () => {
if (tab) {
setTabActiveKey(tab);
} else {
onChangeTab('personal');
onChangeTab('operation');
}
}, [location.search]);
return (