feat: Integrate i18n support and enhance UI text localization
- Added internationalization (i18n) support across various components, enabling dynamic language switching and improved user experience. - Updated multiple components to utilize translation functions for labels, buttons, and messages, ensuring consistent language display. - Enhanced the user interface by refining text elements in the ChannelsTable, LogsTable, and various settings pages, improving clarity and accessibility. - Adjusted CSS styles for better responsiveness and layout consistency across different screen sizes.
This commit is contained in:
@@ -9,8 +9,10 @@ import {
|
||||
verifyJSON,
|
||||
verifyJSONPromise
|
||||
} from '../../../helpers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function SettingsChats(props) {
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
Chats: "[]",
|
||||
@@ -24,7 +26,7 @@ export default function SettingsChats(props) {
|
||||
await refForm.current.validate().then(() => {
|
||||
console.log('Validation passed');
|
||||
const updateArray = compareObjects(inputs, inputsRow);
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -44,23 +46,23 @@ export default function SettingsChats(props) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined))
|
||||
return showError('部分保存失败,请重试');
|
||||
return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.error('Validation failed:', error);
|
||||
showError('请检查输入');
|
||||
showError(t('请检查输入'));
|
||||
});
|
||||
} catch (error) {
|
||||
showError('请检查输入');
|
||||
showError(t('请检查输入'));
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
@@ -104,19 +106,19 @@ export default function SettingsChats(props) {
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'令牌聊天设置'}>
|
||||
<Form.Section text={t('令牌聊天设置')}>
|
||||
<Banner
|
||||
type='warning'
|
||||
description={'必须将上方聊天链接全部设置为空,才能使用下方聊天设置功能'}
|
||||
description={t('必须将上方聊天链接全部设置为空,才能使用下方聊天设置功能')}
|
||||
/>
|
||||
<Banner
|
||||
type='info'
|
||||
description={'链接中的{key}将自动替换为sk-xxxx,{address}将自动替换为系统设置的服务器地址,末尾不带/和/v1'}
|
||||
description={t('链接中的{key}将自动替换为sk-xxxx,{address}将自动替换为系统设置的服务器地址,末尾不带/和/v1')}
|
||||
/>
|
||||
<Form.TextArea
|
||||
label={'聊天配置'}
|
||||
label={t('聊天配置')}
|
||||
extraText={''}
|
||||
placeholder={'为一个 JSON 文本'}
|
||||
placeholder={t('为一个 JSON 文本')}
|
||||
field={'Chats'}
|
||||
autosize={{ minRows: 6, maxRows: 12 }}
|
||||
trigger='blur'
|
||||
@@ -126,7 +128,7 @@ export default function SettingsChats(props) {
|
||||
validator: (rule, value) => {
|
||||
return verifyJSON(value);
|
||||
},
|
||||
message: '不是合法的 JSON 字符串'
|
||||
message: t('不是合法的 JSON 字符串')
|
||||
}
|
||||
]}
|
||||
onChange={(value) =>
|
||||
@@ -140,7 +142,7 @@ export default function SettingsChats(props) {
|
||||
</Form>
|
||||
<Space>
|
||||
<Button onClick={onSubmit}>
|
||||
保存聊天设置
|
||||
{t('保存聊天设置')}
|
||||
</Button>
|
||||
</Space>
|
||||
</Spin>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { Button, Col, Form, Row, Spin } from '@douyinfe/semi-ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
compareObjects,
|
||||
API,
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
} from '../../../helpers';
|
||||
|
||||
export default function SettingsCreditLimit(props) {
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
QuotaForNewUser: '',
|
||||
@@ -21,7 +23,7 @@ export default function SettingsCreditLimit(props) {
|
||||
|
||||
function onSubmit() {
|
||||
const updateArray = compareObjects(inputs, inputsRow);
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -40,13 +42,13 @@ export default function SettingsCreditLimit(props) {
|
||||
if (requestQueue.length === 1) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined)) return showError('部分保存失败,请重试');
|
||||
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
@@ -72,11 +74,11 @@ export default function SettingsCreditLimit(props) {
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'额度设置'}>
|
||||
<Form.Section text={t('额度设置')}>
|
||||
<Row gutter={16}>
|
||||
<Col span={6}>
|
||||
<Form.InputNumber
|
||||
label={'新用户初始额度'}
|
||||
label={t('新用户初始额度')}
|
||||
field={'QuotaForNewUser'}
|
||||
step={1}
|
||||
min={0}
|
||||
@@ -92,12 +94,12 @@ export default function SettingsCreditLimit(props) {
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.InputNumber
|
||||
label={'请求预扣费额度'}
|
||||
label={t('请求预扣费额度')}
|
||||
field={'PreConsumedQuota'}
|
||||
step={1}
|
||||
min={0}
|
||||
suffix={'Token'}
|
||||
extraText={'请求结束后多退少补'}
|
||||
extraText={t('请求结束后多退少补')}
|
||||
placeholder={''}
|
||||
onChange={(value) =>
|
||||
setInputs({
|
||||
@@ -109,13 +111,13 @@ export default function SettingsCreditLimit(props) {
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.InputNumber
|
||||
label={'邀请新用户奖励额度'}
|
||||
label={t('邀请新用户奖励额度')}
|
||||
field={'QuotaForInviter'}
|
||||
step={1}
|
||||
min={0}
|
||||
suffix={'Token'}
|
||||
extraText={''}
|
||||
placeholder={'例如:2000'}
|
||||
placeholder={t('例如:2000')}
|
||||
onChange={(value) =>
|
||||
setInputs({
|
||||
...inputs,
|
||||
@@ -126,13 +128,13 @@ export default function SettingsCreditLimit(props) {
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Form.InputNumber
|
||||
label={'新用户使用邀请码奖励额度'}
|
||||
label={t('新用户使用邀请码奖励额度')}
|
||||
field={'QuotaForInvitee'}
|
||||
step={1}
|
||||
min={0}
|
||||
suffix={'Token'}
|
||||
extraText={''}
|
||||
placeholder={'例如:1000'}
|
||||
placeholder={t('例如:1000')}
|
||||
onChange={(value) =>
|
||||
setInputs({
|
||||
...inputs,
|
||||
@@ -145,7 +147,7 @@ export default function SettingsCreditLimit(props) {
|
||||
|
||||
<Row>
|
||||
<Button size='default' onClick={onSubmit}>
|
||||
保存额度设置
|
||||
{t('保存额度设置')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Form.Section>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { Button, Col, Form, Row, Spin, Tag } from '@douyinfe/semi-ui';
|
||||
import { Button, Col, Form, Row, Spin } from '@douyinfe/semi-ui';
|
||||
import {
|
||||
compareObjects,
|
||||
API,
|
||||
@@ -7,12 +7,15 @@ import {
|
||||
showSuccess,
|
||||
showWarning,
|
||||
} from '../../../helpers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function DataDashboard(props) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const optionsDataExportDefaultTime = [
|
||||
{ key: 'hour', label: '小时', value: 'hour' },
|
||||
{ key: 'day', label: '天', value: 'day' },
|
||||
{ key: 'week', label: '周', value: 'week' },
|
||||
{ key: 'hour', label: t('小时'), value: 'hour' },
|
||||
{ key: 'day', label: t('天'), value: 'day' },
|
||||
{ key: 'week', label: t('周'), value: 'week' },
|
||||
];
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
@@ -25,7 +28,7 @@ export default function DataDashboard(props) {
|
||||
|
||||
function onSubmit() {
|
||||
const updateArray = compareObjects(inputs, inputsRow);
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -44,13 +47,13 @@ export default function DataDashboard(props) {
|
||||
if (requestQueue.length === 1) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined)) return showError('部分保存失败,请重试');
|
||||
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
@@ -81,12 +84,12 @@ export default function DataDashboard(props) {
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'数据看板设置'}>
|
||||
<Form.Section text={t('数据看板设置')}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'DataExportEnabled'}
|
||||
label={'启用数据看板(实验性)'}
|
||||
label={t('启用数据看板(实验性)')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -102,12 +105,12 @@ export default function DataDashboard(props) {
|
||||
<Row>
|
||||
<Col span={8}>
|
||||
<Form.InputNumber
|
||||
label={'数据看板更新间隔 '}
|
||||
label={t('数据看板更新间隔')}
|
||||
step={1}
|
||||
min={1}
|
||||
suffix={'分钟'}
|
||||
extraText={'设置过短会影响数据库性能'}
|
||||
placeholder={'数据看板更新间隔'}
|
||||
suffix={t('分钟')}
|
||||
extraText={t('设置过短会影响数据库性能')}
|
||||
placeholder={t('数据看板更新间隔')}
|
||||
field={'DataExportInterval'}
|
||||
onChange={(value) =>
|
||||
setInputs({
|
||||
@@ -119,11 +122,11 @@ export default function DataDashboard(props) {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Select
|
||||
label='数据看板默认时间粒度'
|
||||
label={t('数据看板默认时间粒度')}
|
||||
optionList={optionsDataExportDefaultTime}
|
||||
field={'DataExportDefaultTime'}
|
||||
extraText={'仅修改展示粒度,统计精确到小时'}
|
||||
placeholder={'数据看板默认时间粒度'}
|
||||
extraText={t('仅修改展示粒度,统计精确到小时')}
|
||||
placeholder={t('数据看板默认时间粒度')}
|
||||
style={{ width: 180 }}
|
||||
onChange={(value) =>
|
||||
setInputs({
|
||||
@@ -136,7 +139,7 @@ export default function DataDashboard(props) {
|
||||
</Row>
|
||||
<Row>
|
||||
<Button size='default' onClick={onSubmit}>
|
||||
保存数据看板设置
|
||||
{t('保存数据看板设置')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Form.Section>
|
||||
|
||||
@@ -7,8 +7,10 @@ import {
|
||||
showSuccess,
|
||||
showWarning,
|
||||
} from '../../../helpers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function SettingsDrawing(props) {
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
DrawingEnabled: false,
|
||||
@@ -23,7 +25,7 @@ export default function SettingsDrawing(props) {
|
||||
|
||||
function onSubmit() {
|
||||
const updateArray = compareObjects(inputs, inputsRow);
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -42,13 +44,13 @@ export default function SettingsDrawing(props) {
|
||||
if (requestQueue.length === 1) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined)) return showError('部分保存失败,请重试');
|
||||
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
@@ -67,6 +69,7 @@ export default function SettingsDrawing(props) {
|
||||
refForm.current.setValues(currentInputs);
|
||||
localStorage.setItem('mj_notify_enabled', String(inputs.MjNotifyEnabled));
|
||||
}, [props.options]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Spin spinning={loading}>
|
||||
@@ -75,12 +78,12 @@ export default function SettingsDrawing(props) {
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'绘图设置'}>
|
||||
<Form.Section text={t('绘图设置')}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'DrawingEnabled'}
|
||||
label={'启用绘图功能'}
|
||||
label={t('启用绘图功能')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -95,7 +98,7 @@ export default function SettingsDrawing(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'MjNotifyEnabled'}
|
||||
label={'允许回调(会泄露服务器 IP 地址)'}
|
||||
label={t('允许回调(会泄露服务器 IP 地址)')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -110,7 +113,7 @@ export default function SettingsDrawing(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'MjAccountFilterEnabled'}
|
||||
label={'允许 AccountFilter 参数'}
|
||||
label={t('允许 AccountFilter 参数')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -125,7 +128,7 @@ export default function SettingsDrawing(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'MjForwardUrlEnabled'}
|
||||
label={'开启之后将上游地址替换为服务器地址'}
|
||||
label={t('开启之后将上游地址替换为服务器地址')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -142,8 +145,8 @@ export default function SettingsDrawing(props) {
|
||||
field={'MjModeClearEnabled'}
|
||||
label={
|
||||
<>
|
||||
开启之后会清除用户提示词中的 <Tag>--fast</Tag> 、
|
||||
<Tag>--relax</Tag> 以及 <Tag>--turbo</Tag> 参数
|
||||
{t('开启之后会清除用户提示词中的')} <Tag>--fast</Tag> 、
|
||||
<Tag>--relax</Tag> {t('以及')} <Tag>--turbo</Tag> {t('参数')}
|
||||
</>
|
||||
}
|
||||
size='default'
|
||||
@@ -160,11 +163,7 @@ export default function SettingsDrawing(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'MjActionCheckSuccessEnabled'}
|
||||
label={
|
||||
<>
|
||||
检测必须等待绘图成功才能进行放大等操作
|
||||
</>
|
||||
}
|
||||
label={t('检测必须等待绘图成功才能进行放大等操作')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -179,7 +178,7 @@ export default function SettingsDrawing(props) {
|
||||
</Row>
|
||||
<Row>
|
||||
<Button size='default' onClick={onSubmit}>
|
||||
保存绘图设置
|
||||
{t('保存绘图设置')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Form.Section>
|
||||
|
||||
@@ -7,8 +7,10 @@ import {
|
||||
showSuccess,
|
||||
showWarning,
|
||||
} from '../../../helpers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function GeneralSettings(props) {
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
TopUpLink: '',
|
||||
@@ -22,13 +24,15 @@ export default function GeneralSettings(props) {
|
||||
});
|
||||
const refForm = useRef();
|
||||
const [inputsRow, setInputsRow] = useState(inputs);
|
||||
|
||||
function onChange(value, e) {
|
||||
const name = e.target.id;
|
||||
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
const updateArray = compareObjects(inputs, inputsRow);
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -47,13 +51,13 @@ export default function GeneralSettings(props) {
|
||||
if (requestQueue.length === 1) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined)) return showError('部分保存失败,请重试');
|
||||
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
@@ -71,26 +75,27 @@ export default function GeneralSettings(props) {
|
||||
setInputsRow(structuredClone(currentInputs));
|
||||
refForm.current.setValues(currentInputs);
|
||||
}, [props.options]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Spin spinning={loading}>
|
||||
<Banner
|
||||
type='warning'
|
||||
description={'聊天链接功能已经弃用,请使用下方聊天设置功能'}
|
||||
description={t('聊天链接功能已经弃用,请使用下方聊天设置功能')}
|
||||
/>
|
||||
<Form
|
||||
values={inputs}
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'通用设置'}>
|
||||
<Form.Section text={t('通用设置')}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Input
|
||||
field={'TopUpLink'}
|
||||
label={'充值链接'}
|
||||
label={t('充值链接')}
|
||||
initValue={''}
|
||||
placeholder={'例如发卡网站的购买链接'}
|
||||
placeholder={t('例如发卡网站的购买链接')}
|
||||
onChange={onChange}
|
||||
showClear
|
||||
/>
|
||||
@@ -98,9 +103,9 @@ export default function GeneralSettings(props) {
|
||||
<Col span={8}>
|
||||
<Form.Input
|
||||
field={'ChatLink'}
|
||||
label={'默认聊天页面链接'}
|
||||
label={t('默认聊天页面链接')}
|
||||
initValue={''}
|
||||
placeholder='例如 ChatGPT Next Web 的部署地址'
|
||||
placeholder={t('例如 ChatGPT Next Web 的部署地址')}
|
||||
onChange={onChange}
|
||||
showClear
|
||||
/>
|
||||
@@ -108,9 +113,9 @@ export default function GeneralSettings(props) {
|
||||
<Col span={8}>
|
||||
<Form.Input
|
||||
field={'ChatLink2'}
|
||||
label={'聊天页面 2 链接'}
|
||||
label={t('聊天页面 2 链接')}
|
||||
initValue={''}
|
||||
placeholder='例如 ChatGPT Next Web 的部署地址'
|
||||
placeholder={t('例如 ChatGPT Next Web 的部署地址')}
|
||||
onChange={onChange}
|
||||
showClear
|
||||
/>
|
||||
@@ -118,9 +123,9 @@ export default function GeneralSettings(props) {
|
||||
<Col span={8}>
|
||||
<Form.Input
|
||||
field={'QuotaPerUnit'}
|
||||
label={'单位美元额度'}
|
||||
label={t('单位美元额度')}
|
||||
initValue={''}
|
||||
placeholder='一单位货币能兑换的额度'
|
||||
placeholder={t('一单位货币能兑换的额度')}
|
||||
onChange={onChange}
|
||||
showClear
|
||||
/>
|
||||
@@ -128,9 +133,9 @@ export default function GeneralSettings(props) {
|
||||
<Col span={8}>
|
||||
<Form.Input
|
||||
field={'RetryTimes'}
|
||||
label={'失败重试次数'}
|
||||
label={t('失败重试次数')}
|
||||
initValue={''}
|
||||
placeholder='失败重试次数'
|
||||
placeholder={t('失败重试次数')}
|
||||
onChange={onChange}
|
||||
showClear
|
||||
/>
|
||||
@@ -140,7 +145,7 @@ export default function GeneralSettings(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'DisplayInCurrencyEnabled'}
|
||||
label={'以货币形式显示额度'}
|
||||
label={t('以货币形式显示额度')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -155,7 +160,7 @@ export default function GeneralSettings(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'DisplayTokenStatEnabled'}
|
||||
label={'Billing 相关 API 显示令牌额度而非用户额度'}
|
||||
label={t('额度查询接口返回令牌额度而非用户额度')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -170,7 +175,7 @@ export default function GeneralSettings(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'DefaultCollapseSidebar'}
|
||||
label={'默认折叠侧边栏'}
|
||||
label={t('默认折叠侧边栏')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -185,7 +190,7 @@ export default function GeneralSettings(props) {
|
||||
</Row>
|
||||
<Row>
|
||||
<Button size='default' onClick={onSubmit}>
|
||||
保存通用设置
|
||||
{t('保存通用设置')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Form.Section>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { Button, Col, Form, Row, Spin, DatePicker } from '@douyinfe/semi-ui';
|
||||
import dayjs from 'dayjs';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
compareObjects,
|
||||
API,
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
} from '../../../helpers';
|
||||
|
||||
export default function SettingsLog(props) {
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [loadingCleanHistoryLog, setLoadingCleanHistoryLog] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
@@ -24,7 +26,7 @@ export default function SettingsLog(props) {
|
||||
(item) => item.key !== 'historyTimestamp',
|
||||
);
|
||||
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -43,13 +45,13 @@ export default function SettingsLog(props) {
|
||||
if (requestQueue.length === 1) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined)) return showError('部分保存失败,请重试');
|
||||
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
@@ -58,16 +60,16 @@ export default function SettingsLog(props) {
|
||||
async function onCleanHistoryLog() {
|
||||
try {
|
||||
setLoadingCleanHistoryLog(true);
|
||||
if (!inputs.historyTimestamp) throw new Error('请选择日志记录时间');
|
||||
if (!inputs.historyTimestamp) throw new Error(t('请选择日志记录时间'));
|
||||
const res = await API.delete(
|
||||
`/api/log/?target_timestamp=${Date.parse(inputs.historyTimestamp) / 1000}`,
|
||||
);
|
||||
const { success, message, data } = res.data;
|
||||
if (success) {
|
||||
showSuccess(`${data} 条日志已清理!`);
|
||||
showSuccess(`${data} ${t('条日志已清理!')}`);
|
||||
return;
|
||||
} else {
|
||||
throw new Error('日志清理失败:' + message);
|
||||
throw new Error(t('日志清理失败:') + message);
|
||||
}
|
||||
} catch (error) {
|
||||
showError(error.message);
|
||||
@@ -96,12 +98,12 @@ export default function SettingsLog(props) {
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'日志设置'}>
|
||||
<Form.Section text={t('日志设置')}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'LogConsumeEnabled'}
|
||||
label={'启用额度消费日志记录'}
|
||||
label={t('启用额度消费日志记录')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -116,7 +118,7 @@ export default function SettingsLog(props) {
|
||||
<Col span={8}>
|
||||
<Spin spinning={loadingCleanHistoryLog}>
|
||||
<Form.DatePicker
|
||||
label='日志记录时间'
|
||||
label={t('日志记录时间')}
|
||||
field={'historyTimestamp'}
|
||||
type='dateTime'
|
||||
inputReadOnly={true}
|
||||
@@ -128,7 +130,7 @@ export default function SettingsLog(props) {
|
||||
}}
|
||||
/>
|
||||
<Button size='default' onClick={onCleanHistoryLog}>
|
||||
清除历史日志
|
||||
{t('清除历史日志')}
|
||||
</Button>
|
||||
</Spin>
|
||||
</Col>
|
||||
@@ -136,7 +138,7 @@ export default function SettingsLog(props) {
|
||||
|
||||
<Row>
|
||||
<Button size='default' onClick={onSubmit}>
|
||||
保存日志设置
|
||||
{t('保存日志设置')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Form.Section>
|
||||
|
||||
@@ -7,8 +7,10 @@ import {
|
||||
showSuccess,
|
||||
showWarning,
|
||||
} from '../../../helpers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function SettingsMonitoring(props) {
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
ChannelDisableThreshold: '',
|
||||
@@ -21,7 +23,7 @@ export default function SettingsMonitoring(props) {
|
||||
|
||||
function onSubmit() {
|
||||
const updateArray = compareObjects(inputs, inputsRow);
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -40,13 +42,13 @@ export default function SettingsMonitoring(props) {
|
||||
if (requestQueue.length === 1) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined)) return showError('部分保存失败,请重试');
|
||||
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
@@ -64,6 +66,7 @@ export default function SettingsMonitoring(props) {
|
||||
setInputsRow(structuredClone(currentInputs));
|
||||
refForm.current.setValues(currentInputs);
|
||||
}, [props.options]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Spin spinning={loading}>
|
||||
@@ -72,15 +75,15 @@ export default function SettingsMonitoring(props) {
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'监控设置'}>
|
||||
<Form.Section text={t('监控设置')}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.InputNumber
|
||||
label={'最长响应时间'}
|
||||
label={t('最长响应时间')}
|
||||
step={1}
|
||||
min={0}
|
||||
suffix={'秒'}
|
||||
extraText={'当运行通道全部测试时,超过此时间将自动禁用通道'}
|
||||
suffix={t('秒')}
|
||||
extraText={t('当运行通道全部测试时,超过此时间将自动禁用通道')}
|
||||
placeholder={''}
|
||||
field={'ChannelDisableThreshold'}
|
||||
onChange={(value) =>
|
||||
@@ -93,11 +96,11 @@ export default function SettingsMonitoring(props) {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.InputNumber
|
||||
label={'额度提醒阈值'}
|
||||
label={t('额度提醒阈值')}
|
||||
step={1}
|
||||
min={0}
|
||||
suffix={'Token'}
|
||||
extraText={'低于此额度时将发送邮件提醒用户'}
|
||||
extraText={t('低于此额度时将发送邮件提醒用户')}
|
||||
placeholder={''}
|
||||
field={'QuotaRemindThreshold'}
|
||||
onChange={(value) =>
|
||||
@@ -113,7 +116,7 @@ export default function SettingsMonitoring(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'AutomaticDisableChannelEnabled'}
|
||||
label={'失败时自动禁用通道'}
|
||||
label={t('失败时自动禁用通道')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -128,7 +131,7 @@ export default function SettingsMonitoring(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'AutomaticEnableChannelEnabled'}
|
||||
label={'成功时自动启用通道'}
|
||||
label={t('成功时自动启用通道')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -143,7 +146,7 @@ export default function SettingsMonitoring(props) {
|
||||
</Row>
|
||||
<Row>
|
||||
<Button size='default' onClick={onSubmit}>
|
||||
保存监控设置
|
||||
{t('保存监控设置')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Form.Section>
|
||||
|
||||
@@ -7,8 +7,10 @@ import {
|
||||
showSuccess,
|
||||
showWarning,
|
||||
} from '../../../helpers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function SettingsSensitiveWords(props) {
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
CheckSensitiveEnabled: false,
|
||||
@@ -20,7 +22,7 @@ export default function SettingsSensitiveWords(props) {
|
||||
|
||||
function onSubmit() {
|
||||
const updateArray = compareObjects(inputs, inputsRow);
|
||||
if (!updateArray.length) return showWarning('你似乎并没有修改什么');
|
||||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||||
const requestQueue = updateArray.map((item) => {
|
||||
let value = '';
|
||||
if (typeof inputs[item.key] === 'boolean') {
|
||||
@@ -39,13 +41,13 @@ export default function SettingsSensitiveWords(props) {
|
||||
if (requestQueue.length === 1) {
|
||||
if (res.includes(undefined)) return;
|
||||
} else if (requestQueue.length > 1) {
|
||||
if (res.includes(undefined)) return showError('部分保存失败,请重试');
|
||||
if (res.includes(undefined)) return showError(t('部分保存失败,请重试'));
|
||||
}
|
||||
showSuccess('保存成功');
|
||||
showSuccess(t('保存成功'));
|
||||
props.refresh();
|
||||
})
|
||||
.catch(() => {
|
||||
showError('保存失败,请重试');
|
||||
showError(t('保存失败,请重试'));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
@@ -71,12 +73,12 @@ export default function SettingsSensitiveWords(props) {
|
||||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||||
style={{ marginBottom: 15 }}
|
||||
>
|
||||
<Form.Section text={'屏蔽词过滤设置'}>
|
||||
<Form.Section text={t('屏蔽词过滤设置')}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'CheckSensitiveEnabled'}
|
||||
label={'启用屏蔽词过滤功能'}
|
||||
label={t('启用屏蔽词过滤功能')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -91,7 +93,7 @@ export default function SettingsSensitiveWords(props) {
|
||||
<Col span={8}>
|
||||
<Form.Switch
|
||||
field={'CheckSensitiveOnPromptEnabled'}
|
||||
label={'启用 Prompt 检查'}
|
||||
label={t('启用 Prompt 检查')}
|
||||
size='default'
|
||||
checkedText='|'
|
||||
uncheckedText='〇'
|
||||
@@ -107,9 +109,9 @@ export default function SettingsSensitiveWords(props) {
|
||||
<Row>
|
||||
<Col span={16}>
|
||||
<Form.TextArea
|
||||
label={'屏蔽词列表'}
|
||||
extraText={'一行一个屏蔽词,不需要符号分割'}
|
||||
placeholder={'一行一个屏蔽词,不需要符号分割'}
|
||||
label={t('屏蔽词列表')}
|
||||
extraText={t('一行一个屏蔽词,不需要符号分割')}
|
||||
placeholder={t('一行一个屏蔽词,不需要符号分割')}
|
||||
field={'SensitiveWords'}
|
||||
onChange={(value) =>
|
||||
setInputs({
|
||||
@@ -124,7 +126,7 @@ export default function SettingsSensitiveWords(props) {
|
||||
</Row>
|
||||
<Row>
|
||||
<Button size='default' onClick={onSubmit}>
|
||||
保存屏蔽词过滤设置
|
||||
{t('保存屏蔽词过滤设置')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Form.Section>
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Layout, TabPane, Tabs } from '@douyinfe/semi-ui';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import SystemSetting from '../../components/SystemSetting';
|
||||
import { isRoot } from '../../helpers';
|
||||
import OtherSetting from '../../components/OtherSetting';
|
||||
import PersonalSetting from '../../components/PersonalSetting';
|
||||
import OperationSetting from '../../components/OperationSetting';
|
||||
|
||||
const Setting = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [tabActiveKey, setTabActiveKey] = useState('1');
|
||||
let panes = [
|
||||
{
|
||||
tab: '个人设置',
|
||||
tab: t('个人设置'),
|
||||
content: <PersonalSetting />,
|
||||
itemKey: 'personal',
|
||||
},
|
||||
@@ -21,17 +24,17 @@ const Setting = () => {
|
||||
|
||||
if (isRoot()) {
|
||||
panes.push({
|
||||
tab: '运营设置',
|
||||
tab: t('运营设置'),
|
||||
content: <OperationSetting />,
|
||||
itemKey: 'operation',
|
||||
});
|
||||
panes.push({
|
||||
tab: '系统设置',
|
||||
tab: t('系统设置'),
|
||||
content: <SystemSetting />,
|
||||
itemKey: 'system',
|
||||
});
|
||||
panes.push({
|
||||
tab: '其他设置',
|
||||
tab: t('其他设置'),
|
||||
content: <OtherSetting />,
|
||||
itemKey: 'other',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user