diff --git a/web/src/App.js b/web/src/App.js index 8aa16fab..05fd597f 100644 --- a/web/src/App.js +++ b/web/src/App.js @@ -36,58 +36,6 @@ const Detail = lazy(() => import('./pages/Detail')); const About = lazy(() => import('./pages/About')); function App() { - const [userState, userDispatch] = useContext(UserContext); - const [statusState, statusDispatch] = useContext(StatusContext); - const { i18n } = useTranslation(); - - const loadUser = () => { - let user = localStorage.getItem('user'); - if (user) { - let data = JSON.parse(user); - userDispatch({ type: 'login', payload: data }); - } - }; - - const loadStatus = async () => { - try { - const res = await API.get('/api/status'); - if (!res?.data) return; - - const { success, data } = res.data; - if (success) { - statusDispatch({ type: 'set', payload: data }); - setStatusData(data); - } else { - showError('Unable to connect to server'); - } - } catch (error) { - showError('Failed to load status'); - } - }; - - useEffect(() => { - loadUser(); - let systemName = getSystemName(); - if (systemName) { - document.title = systemName; - } - let logo = getLogo(); - if (logo) { - let linkElement = document.querySelector("link[rel~='icon']"); - if (linkElement) { - linkElement.href = logo; - } - } - // 从localStorage获取上次使用的语言 - const savedLang = localStorage.getItem('i18nextLng'); - if (savedLang) { - i18n.changeLanguage(savedLang); - } - loadStatus(); - - - }, [i18n]); - return ( <> diff --git a/web/src/components/ChannelsTable.js b/web/src/components/ChannelsTable.js index 3167650f..ceb3fe44 100644 --- a/web/src/components/ChannelsTable.js +++ b/web/src/components/ChannelsTable.js @@ -249,7 +249,7 @@ const ChannelsTable = () => { } }, { - title: '优先级', + title: t('优先级'), dataIndex: 'priority', render: (text, record, index) => { if (record.children === undefined) { @@ -276,8 +276,8 @@ const ChannelsTable = () => { keepFocus={true} onBlur={(e) => { Modal.warning({ - title: '修改子渠道优先级', - content: '确定要修改所有子渠道优先级为 ' + e.target.value + ' 吗?', + title: t('修改子渠道优先级'), + content: t('确定要修改所有子渠道优先级为 ') + e.target.value + t(' 吗?'), onOk: () => { if (e.target.value === '') { return; @@ -298,7 +298,7 @@ const ChannelsTable = () => { } }, { - title: '权重', + title: t('权重'), dataIndex: 'weight', render: (text, record, index) => { if (record.children === undefined) { @@ -325,8 +325,8 @@ const ChannelsTable = () => { keepFocus={true} onBlur={(e) => { Modal.warning({ - title: '修改子渠道权重', - content: '确定要修改所有子渠道权重为 ' + e.target.value + ' 吗?', + title: t('修改子渠道权重'), + content: t('确定要修改所有子渠道权重为 ') + e.target.value + t(' 吗?'), onOk: () => { if (e.target.value === '') { return; @@ -646,25 +646,25 @@ const ChannelsTable = () => { const copySelectedChannel = async (record) => { const channelToCopy = record - channelToCopy.name += '_复制'; + channelToCopy.name += t('_复制'); channelToCopy.created_time = null; channelToCopy.balance = 0; channelToCopy.used_quota = 0; if (!channelToCopy) { - showError('渠道未找到,请刷新页面后重试。'); + showError(t('渠道未找到,请刷新页面后重试。')); return; } try { const newChannel = { ...channelToCopy, id: undefined }; const response = await API.post('/api/channel/', newChannel); if (response.data.success) { - showSuccess('渠道复制成功'); + showSuccess(t('渠道复制成功')); await refresh(); } else { showError(response.data.message); } } catch (error) { - showError('渠道复制失败: ' + error.message); + showError(t('渠道复制失败: ') + error.message); } }; @@ -723,7 +723,7 @@ const ChannelsTable = () => { } const { success, message } = res.data; if (success) { - showSuccess('操作成功完成!'); + showSuccess(t('操作成功完成!')); let channel = res.data.data; let newChannels = [...channels]; if (action === 'delete') { diff --git a/web/src/components/HeaderBar.js b/web/src/components/HeaderBar.js index 759a7278..d885d59b 100644 --- a/web/src/components/HeaderBar.js +++ b/web/src/components/HeaderBar.js @@ -25,24 +25,6 @@ import { stringToColor } from '../helpers/render'; import Text from '@douyinfe/semi-ui/lib/es/typography/text'; import { StyleContext } from '../context/Style/index.js'; -// HeaderBar Buttons -let headerButtons = [ - { - text: '关于', - itemKey: 'about', - to: '/about', - icon: , - }, -]; - -if (localStorage.getItem('chat_link')) { - headerButtons.splice(1, 0, { - name: '聊天', - to: '/chat', - icon: 'comments', - }); -} - const HeaderBar = () => { const { t, i18n } = useTranslation(); const [userState, userDispatch] = useContext(UserContext); diff --git a/web/src/components/PageLayout.js b/web/src/components/PageLayout.js index 6a951c06..da1c09f9 100644 --- a/web/src/components/PageLayout.js +++ b/web/src/components/PageLayout.js @@ -4,15 +4,65 @@ import SiderBar from './SiderBar.js'; import App from '../App.js'; import FooterBar from './Footer.js'; import { ToastContainer } from 'react-toastify'; -import React, { useContext } from 'react'; +import React, { useContext, useEffect } from 'react'; import { StyleContext } from '../context/Style/index.js'; import { useTranslation } from 'react-i18next'; +import { API, getLogo, getSystemName, showError } from '../helpers/index.js'; +import { setStatusData } from '../helpers/data.js'; +import { UserContext } from '../context/User/index.js'; +import { StatusContext } from '../context/Status/index.js'; const { Sider, Content, Header, Footer } = Layout; const PageLayout = () => { + const [userState, userDispatch] = useContext(UserContext); + const [statusState, statusDispatch] = useContext(StatusContext); const [styleState, styleDispatch] = useContext(StyleContext); - const { t } = useTranslation(); + const { i18n } = useTranslation(); + + const loadUser = () => { + let user = localStorage.getItem('user'); + if (user) { + let data = JSON.parse(user); + userDispatch({ type: 'login', payload: data }); + } + }; + + const loadStatus = async () => { + try { + const res = await API.get('/api/status'); + const { success, data } = res.data; + if (success) { + statusDispatch({ type: 'set', payload: data }); + setStatusData(data); + } else { + showError('Unable to connect to server'); + } + } catch (error) { + showError('Failed to load status'); + } + }; + + useEffect(() => { + loadUser(); + loadStatus().catch(console.error); + let systemName = getSystemName(); + if (systemName) { + document.title = systemName; + } + let logo = getLogo(); + if (logo) { + let linkElement = document.querySelector("link[rel~='icon']"); + if (linkElement) { + linkElement.href = logo; + } + } + // 从localStorage获取上次使用的语言 + const savedLang = localStorage.getItem('i18nextLng'); + if (savedLang) { + i18n.changeLanguage(savedLang); + } + }, [i18n]); return ( diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index d7947a0b..32da3670 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -709,7 +709,7 @@ "密码修改成功!": "Password changed successfully!", "划转金额最低为": "The minimum transfer amount is", "请输入邮箱!": "Please enter your email!", - "验证码发送成功,请检查���箱!": "The verification code was sent successfully, please check your email!", + "验证码发送成功,请检查邮箱!": "The verification code was sent successfully, please check your email!", "请输入邮箱验证码!": "Please enter the email verification code!", "请输入要划转的数量": "Please enter the amount to be transferred", "当前余额": "Current balance", @@ -827,8 +827,8 @@ "模型消耗分布": "Model consumption distribution", "模型调用次数占比": "Proportion of model calls", "用户消耗分布": "User consumption distribution", - "时间粒度": "time granularity", - "天": "sky", + "时间粒度": "Time granularity", + "天": "day", "模型概览": "Model overview", "用户概览": "User overview", "正在策划中": "Under planning", @@ -1212,5 +1212,10 @@ "当前未开启Midjourney回调,部分项目可能无法获得绘图结果,可在运营设置中开启。": "Current Midjourney callback is not enabled, some projects may not be able to obtain drawing results, which can be enabled in the operation settings.", "Telegram 身份验证": "Telegram authentication", "Linux DO 身份验证": "Linux DO authentication", - "协议": "License" + "协议": "License", + "修改子渠道权重": "Modify sub-channel weight", + "确定要修改所有子渠道权重为 ": "Confirm to modify all sub-channel weights to ", + " 吗?": "?", + "修改子渠道优先级": "Modify sub-channel priority", + "确定要修改所有子渠道优先级为 ": "Confirm to modify all sub-channel priorities to " } \ No newline at end of file diff --git a/web/src/pages/Home/index.js b/web/src/pages/Home/index.js index 094e4692..af42541d 100644 --- a/web/src/pages/Home/index.js +++ b/web/src/pages/Home/index.js @@ -54,7 +54,8 @@ const Home = () => { useEffect(() => { displayNotice().then(); displayHomePageContent().then(); - }, []); + }); + return ( <> {homePageContentLoaded && homePageContent === '' ? ( diff --git a/web/src/pages/Playground/Playground.js b/web/src/pages/Playground/Playground.js index ecd96f50..935e7b6e 100644 --- a/web/src/pages/Playground/Playground.js +++ b/web/src/pages/Playground/Playground.js @@ -97,32 +97,29 @@ const Playground = () => { let res = await API.get(`/api/user/self/groups`); const { success, message, data } = res.data; if (success) { - // return data is a map, key is group name, value is group description - // label is group description, value is group name let localGroupOptions = Object.keys(data).map((group) => ({ label: data[group], value: group, })); - // handleInputChange('group', localGroupOptions[0].value); - if (localGroupOptions.length > 0) { - // set user group at first - if (userState.user && userState.user.group) { - let userGroup = userState.user.group; - // Find and move user's group to the front + if (localGroupOptions.length === 0) { + localGroupOptions = [{ + label: t('用户分组'), + value: '', + }]; + } else { + const localUser = JSON.parse(localStorage.getItem('user')); + const userGroup = (userState.user && userState.user.group) || (localUser && localUser.group); + + if (userGroup) { const userGroupIndex = localGroupOptions.findIndex(g => g.value === userGroup); if (userGroupIndex > -1) { const userGroupOption = localGroupOptions.splice(userGroupIndex, 1)[0]; localGroupOptions.unshift(userGroupOption); } } - } else { - localGroupOptions = [{ - label: t('用户分组'), - value: '', - }]; - setGroups(localGroupOptions); } + setGroups(localGroupOptions); handleInputChange('group', localGroupOptions[0].value); } else {