Compare commits

..

11 Commits

12 changed files with 85 additions and 50 deletions

View File

@@ -126,10 +126,10 @@ var ValidThemes = map[string]bool{
// All duration's unit is seconds // All duration's unit is seconds
// Shouldn't larger then RateLimitKeyExpirationDuration // Shouldn't larger then RateLimitKeyExpirationDuration
var ( var (
GlobalApiRateLimitNum = env.Int("GLOBAL_API_RATE_LIMIT", 240) GlobalApiRateLimitNum = env.Int("GLOBAL_API_RATE_LIMIT", 480)
GlobalApiRateLimitDuration int64 = 3 * 60 GlobalApiRateLimitDuration int64 = 3 * 60
GlobalWebRateLimitNum = env.Int("GLOBAL_WEB_RATE_LIMIT", 120) GlobalWebRateLimitNum = env.Int("GLOBAL_WEB_RATE_LIMIT", 240)
GlobalWebRateLimitDuration int64 = 3 * 60 GlobalWebRateLimitDuration int64 = 3 * 60
UploadRateLimitNum = 10 UploadRateLimitNum = 10

View File

@@ -7,7 +7,6 @@
"history": "^5.3.0", "history": "^5.3.0",
"i18next": "^24.2.2", "i18next": "^24.2.2",
"i18next-browser-languagedetector": "^8.0.2", "i18next-browser-languagedetector": "^8.0.2",
"i18next-http-backend": "^3.0.2",
"marked": "^4.1.1", "marked": "^4.1.1",
"moment": "^2.30.1", "moment": "^2.30.1",
"react": "^18.2.0", "react": "^18.2.0",

View File

@@ -328,6 +328,7 @@ const LogsTable = () => {
<Form.Input <Form.Input
fluid fluid
label={t('log.table.token_name')} label={t('log.table.token_name')}
size={'small'}
width={3} width={3}
value={token_name} value={token_name}
placeholder={t('log.table.token_name_placeholder')} placeholder={t('log.table.token_name_placeholder')}
@@ -337,6 +338,7 @@ const LogsTable = () => {
<Form.Input <Form.Input
fluid fluid
label={t('log.table.model_name')} label={t('log.table.model_name')}
size={'small'}
width={3} width={3}
value={model_name} value={model_name}
placeholder={t('log.table.model_name_placeholder')} placeholder={t('log.table.model_name_placeholder')}
@@ -346,6 +348,7 @@ const LogsTable = () => {
<Form.Input <Form.Input
fluid fluid
label={t('log.table.start_time')} label={t('log.table.start_time')}
size={'small'}
width={4} width={4}
value={start_timestamp} value={start_timestamp}
type='datetime-local' type='datetime-local'
@@ -355,6 +358,7 @@ const LogsTable = () => {
<Form.Input <Form.Input
fluid fluid
label={t('log.table.end_time')} label={t('log.table.end_time')}
size={'small'}
width={4} width={4}
value={end_timestamp} value={end_timestamp}
type='datetime-local' type='datetime-local'
@@ -364,6 +368,7 @@ const LogsTable = () => {
<Form.Button <Form.Button
fluid fluid
label={t('log.buttons.query')} label={t('log.buttons.query')}
size={'small'}
width={2} width={2}
onClick={refresh} onClick={refresh}
> >
@@ -376,6 +381,7 @@ const LogsTable = () => {
<Form.Input <Form.Input
fluid fluid
label={t('log.table.channel_id')} label={t('log.table.channel_id')}
size={'small'}
width={3} width={3}
value={channel} value={channel}
placeholder={t('log.table.channel_id_placeholder')} placeholder={t('log.table.channel_id_placeholder')}
@@ -385,6 +391,7 @@ const LogsTable = () => {
<Form.Input <Form.Input
fluid fluid
label={t('log.table.username')} label={t('log.table.username')}
size={'small'}
width={3} width={3}
value={username} value={username}
placeholder={t('log.table.username_placeholder')} placeholder={t('log.table.username_placeholder')}

View File

@@ -415,9 +415,9 @@ const TokensTable = () => {
</Table.Cell> </Table.Cell>
<Table.Cell> <Table.Cell>
<div> <div>
<Button.Group color='green' size={'mini'}> <Button.Group color='green' size={'tiny'}>
<Button <Button
size={'mini'} size={'tiny'}
positive positive
onClick={async () => await onCopy('', token.key)} onClick={async () => await onCopy('', token.key)}
> >
@@ -430,9 +430,9 @@ const TokensTable = () => {
trigger={<></>} trigger={<></>}
/> />
</Button.Group>{' '} </Button.Group>{' '}
<Button.Group color='blue' size={'mini'}> <Button.Group color='olive' size={'tiny'}>
<Button <Button
size={'mini'} size={'tiny'}
positive positive
onClick={() => onOpenLink('', token.key)} onClick={() => onOpenLink('', token.key)}
> >
@@ -456,7 +456,7 @@ const TokensTable = () => {
hoverable hoverable
> >
<Button <Button
size={'mini'} size={'tiny'}
negative negative
onClick={() => { onClick={() => {
manageToken(token.id, 'delete', idx); manageToken(token.id, 'delete', idx);
@@ -466,7 +466,7 @@ const TokensTable = () => {
</Button> </Button>
</Popup> </Popup>
<Button <Button
size={'mini'} size={'tiny'}
onClick={() => { onClick={() => {
manageToken( manageToken(
token.id, token.id,
@@ -480,7 +480,7 @@ const TokensTable = () => {
: t('token.buttons.enable')} : t('token.buttons.enable')}
</Button> </Button>
<Button <Button
size={'mini'} size={'tiny'}
as={Link} as={Link}
to={'/token/edit/' + token.id} to={'/token/edit/' + token.id}
> >

View File

@@ -1,7 +1,7 @@
export const toastConstants = { export const toastConstants = {
SUCCESS_TIMEOUT: 1500, SUCCESS_TIMEOUT: 5000,
INFO_TIMEOUT: 3000, INFO_TIMEOUT: 8000,
ERROR_TIMEOUT: 5000, ERROR_TIMEOUT: 10000,
WARNING_TIMEOUT: 10000, WARNING_TIMEOUT: 10000,
NOTICE_TIMEOUT: 20000 NOTICE_TIMEOUT: 20000,
}; };

View File

@@ -1,10 +1,10 @@
import i18n from 'i18next'; import i18n from 'i18next';
import { initReactI18next } from 'react-i18next'; import {initReactI18next} from 'react-i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector'; import LanguageDetector from 'i18next-browser-languagedetector';
import zhTranslation from './locales/zh/translation.json';
import enTranslation from './locales/en/translation.json';
i18n i18n
.use(Backend)
.use(LanguageDetector) .use(LanguageDetector)
.use(initReactI18next) .use(initReactI18next)
.init({ .init({
@@ -15,9 +15,14 @@ i18n
escapeValue: false, escapeValue: false,
}, },
backend: { resources: {
loadPath: '/locales/{{lng}}/{{ns}}.json', zh: {
}, translation: zhTranslation
},
en: {
translation: enTranslation
}
}
}); });
export default i18n; export default i18n;

View File

@@ -85,7 +85,8 @@
"test_all_started": "Channel testing started successfully, please refresh page to see results.", "test_all_started": "Channel testing started successfully, please refresh page to see results.",
"delete_disabled_success": "Deleted all disabled channels, total: {{count}}", "delete_disabled_success": "Deleted all disabled channels, total: {{count}}",
"balance_update_success": "Channel {{name}} balance updated successfully!", "balance_update_success": "Channel {{name}} balance updated successfully!",
"all_balance_updated": "All enabled channel balances have been updated!" "all_balance_updated": "All enabled channel balances have been updated!",
"operation_success": "Operation completed successfully!"
}, },
"edit": { "edit": {
"title_edit": "Update Channel Information", "title_edit": "Update Channel Information",
@@ -165,7 +166,7 @@
"expired_time": "Expiry Time", "expired_time": "Expiry Time",
"actions": "Actions", "actions": "Actions",
"no_name": "None", "no_name": "None",
"never_expire": "Never Expires", "never_expire": "never",
"unlimited": "Unlimited", "unlimited": "Unlimited",
"status_enabled": "Enabled", "status_enabled": "Enabled",
"status_disabled": "Disabled", "status_disabled": "Disabled",

View File

@@ -85,7 +85,8 @@
"test_all_started": "已成功开始测试渠道,请刷新页面查看结果。", "test_all_started": "已成功开始测试渠道,请刷新页面查看结果。",
"delete_disabled_success": "已删除所有禁用渠道,共计 {{count}} 个", "delete_disabled_success": "已删除所有禁用渠道,共计 {{count}} 个",
"balance_update_success": "渠道 {{name}} 余额更新成功!", "balance_update_success": "渠道 {{name}} 余额更新成功!",
"all_balance_updated": "已更新完毕所有已启用渠道余额!" "all_balance_updated": "已更新完毕所有已启用渠道余额!",
"operation_success": "操作成功完成!"
}, },
"edit": { "edit": {
"title_edit": "更新渠道信息", "title_edit": "更新渠道信息",

View File

@@ -54,10 +54,16 @@ const About = () => {
style={{ width: '100%', height: '100vh', border: 'none' }} style={{ width: '100%', height: '100vh', border: 'none' }}
/> />
) : ( ) : (
<div <div className='dashboard-container'>
style={{ fontSize: 'larger' }} <Card fluid className='chart-card'>
dangerouslySetInnerHTML={{ __html: about }} <Card.Content>
></div> <div
style={{ fontSize: 'larger' }}
dangerouslySetInnerHTML={{ __html: about }}
></div>
</Card.Content>
</Card>
</div>
)} )}
</> </>
)} )}

View File

@@ -207,6 +207,9 @@ const EditChannel = () => {
return; return;
} }
let localInputs = { ...inputs }; let localInputs = { ...inputs };
if (localInputs.key === 'undefined|undefined|undefined') {
localInputs.key = ''; // prevent potential bug
}
if (localInputs.base_url && localInputs.base_url.endsWith('/')) { if (localInputs.base_url && localInputs.base_url.endsWith('/')) {
localInputs.base_url = localInputs.base_url.slice( localInputs.base_url = localInputs.base_url.slice(
0, 0,
@@ -622,6 +625,21 @@ const EditChannel = () => {
/> />
</Form.Field> </Form.Field>
))} ))}
{inputs.type === 37 && (
<Form.Field>
<Form.Input
label='Account ID'
name='user_id'
required
placeholder={
'请输入 Account ID例如d8d7c61dbc334c32d3ced580e4bf42b4'
}
onChange={handleConfigChange}
value={config.user_id}
autoComplete=''
/>
</Form.Field>
)}
{inputs.type !== 33 && !isEdit && ( {inputs.type !== 33 && !isEdit && (
<Form.Checkbox <Form.Checkbox
checked={batch} checked={batch}

View File

@@ -36,7 +36,7 @@
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04) !important; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04) !important;
border: none !important; border: none !important;
border-radius: 16px !important; border-radius: 16px !important;
padding-top: 8px!important; padding: 8px!important;
} }
.chart-container { .chart-container {
@@ -97,9 +97,9 @@
} }
.settings-tab .active.item { .settings-tab .active.item {
color: #4318FF !important; color: #000 !important;
font-weight: 600 !important; font-weight: 600 !important;
border-color: #4318FF !important; border-color: #000 !important;
} }
.ui.tab.segment { .ui.tab.segment {

View File

@@ -1,19 +1,17 @@
import React, { useEffect, useState } from 'react'; import React, {useEffect, useState} from 'react';
import { useTranslation } from 'react-i18next'; import {useTranslation} from 'react-i18next';
import { Card, Grid, Header, Segment, Statistic } from 'semantic-ui-react'; import {Card, Grid} from 'semantic-ui-react';
import { API, showError } from '../../helpers';
import moment from 'moment';
import { import {
LineChart, Bar,
BarChart,
CartesianGrid,
Legend,
Line, Line,
LineChart,
ResponsiveContainer,
Tooltip,
XAxis, XAxis,
YAxis, YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
BarChart,
Bar,
Legend,
} from 'recharts'; } from 'recharts';
import axios from 'axios'; import axios from 'axios';
import './Dashboard.css'; import './Dashboard.css';
@@ -244,7 +242,7 @@ const Dashboard = () => {
<Card.Content> <Card.Content>
<Card.Header> <Card.Header>
{t('dashboard.charts.requests.title')} {t('dashboard.charts.requests.title')}
<span className='stat-value'>{summaryData.todayRequests}</span> {/* <span className='stat-value'>{summaryData.todayRequests}</span> */}
</Card.Header> </Card.Header>
<div className='chart-container'> <div className='chart-container'>
<ResponsiveContainer <ResponsiveContainer
@@ -273,7 +271,7 @@ const Dashboard = () => {
t('dashboard.charts.requests.tooltip'), t('dashboard.charts.requests.tooltip'),
]} ]}
labelFormatter={(label) => labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}` `${t('dashboard.statistics.tooltip.date')}: ${formatDate(label)}`
} }
/> />
<Line <Line
@@ -296,9 +294,9 @@ const Dashboard = () => {
<Card.Content> <Card.Content>
<Card.Header> <Card.Header>
{t('dashboard.charts.quota.title')} {t('dashboard.charts.quota.title')}
<span className='stat-value'> {/* <span className='stat-value'>
${summaryData.todayQuota.toFixed(3)} ${summaryData.todayQuota.toFixed(3)}
</span> </span> */}
</Card.Header> </Card.Header>
<div className='chart-container'> <div className='chart-container'>
<ResponsiveContainer <ResponsiveContainer
@@ -327,7 +325,7 @@ const Dashboard = () => {
t('dashboard.charts.quota.tooltip'), t('dashboard.charts.quota.tooltip'),
]} ]}
labelFormatter={(label) => labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}` `${t('dashboard.statistics.tooltip.date')}: ${formatDate(label)}`
} }
/> />
<Line <Line
@@ -350,7 +348,7 @@ const Dashboard = () => {
<Card.Content> <Card.Content>
<Card.Header> <Card.Header>
{t('dashboard.charts.tokens.title')} {t('dashboard.charts.tokens.title')}
<span className='stat-value'>{summaryData.todayTokens}</span> {/* <span className='stat-value'>{summaryData.todayTokens}</span> */}
</Card.Header> </Card.Header>
<div className='chart-container'> <div className='chart-container'>
<ResponsiveContainer <ResponsiveContainer
@@ -379,7 +377,7 @@ const Dashboard = () => {
t('dashboard.charts.tokens.tooltip'), t('dashboard.charts.tokens.tooltip'),
]} ]}
labelFormatter={(label) => labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}` `${t('dashboard.statistics.tooltip.date')}: ${formatDate(label)}`
} }
/> />
<Line <Line
@@ -424,7 +422,7 @@ const Dashboard = () => {
boxShadow: '0 2px 8px rgba(0,0,0,0.1)', boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
}} }}
labelFormatter={(label) => labelFormatter={(label) =>
`${t('dashboard.tooltip.date')}: ${formatDate(label)}` `${t('dashboard.statistics.tooltip.date')}: ${formatDate(label)}`
} }
/> />
<Legend <Legend