|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import React, { useEffect, useState, useRef, useMemo } from 'react'; |
|
|
import { |
|
|
Banner, |
|
|
Button, |
|
|
Col, |
|
|
Form, |
|
|
Row, |
|
|
Spin, |
|
|
Modal, |
|
|
Select, |
|
|
InputGroup, |
|
|
Input, |
|
|
} from '@douyinfe/semi-ui'; |
|
|
import { |
|
|
compareObjects, |
|
|
API, |
|
|
showError, |
|
|
showSuccess, |
|
|
showWarning, |
|
|
} from '../../../helpers'; |
|
|
import { useTranslation } from 'react-i18next'; |
|
|
|
|
|
export default function GeneralSettings(props) { |
|
|
const { t } = useTranslation(); |
|
|
const [loading, setLoading] = useState(false); |
|
|
const [showQuotaWarning, setShowQuotaWarning] = useState(false); |
|
|
const [inputs, setInputs] = useState({ |
|
|
TopUpLink: '', |
|
|
'general_setting.docs_link': '', |
|
|
'general_setting.quota_display_type': 'USD', |
|
|
'general_setting.custom_currency_symbol': '¤', |
|
|
'general_setting.custom_currency_exchange_rate': '', |
|
|
QuotaPerUnit: '', |
|
|
RetryTimes: '', |
|
|
USDExchangeRate: '', |
|
|
DisplayTokenStatEnabled: false, |
|
|
DefaultCollapseSidebar: false, |
|
|
DemoSiteEnabled: false, |
|
|
SelfUseModeEnabled: false, |
|
|
}); |
|
|
const refForm = useRef(); |
|
|
const [inputsRow, setInputsRow] = useState(inputs); |
|
|
|
|
|
function handleFieldChange(fieldName) { |
|
|
return (value) => { |
|
|
setInputs((inputs) => ({ ...inputs, [fieldName]: value })); |
|
|
}; |
|
|
} |
|
|
|
|
|
function onSubmit() { |
|
|
const updateArray = compareObjects(inputs, inputsRow); |
|
|
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么')); |
|
|
const requestQueue = updateArray.map((item) => { |
|
|
let value = ''; |
|
|
if (typeof inputs[item.key] === 'boolean') { |
|
|
value = String(inputs[item.key]); |
|
|
} else { |
|
|
value = inputs[item.key]; |
|
|
} |
|
|
return API.put('/api/option/', { |
|
|
key: item.key, |
|
|
value, |
|
|
}); |
|
|
}); |
|
|
setLoading(true); |
|
|
Promise.all(requestQueue) |
|
|
.then((res) => { |
|
|
if (requestQueue.length === 1) { |
|
|
if (res.includes(undefined)) return; |
|
|
} else if (requestQueue.length > 1) { |
|
|
if (res.includes(undefined)) |
|
|
return showError(t('部分保存失败,请重试')); |
|
|
} |
|
|
showSuccess(t('保存成功')); |
|
|
props.refresh(); |
|
|
}) |
|
|
.catch(() => { |
|
|
showError(t('保存失败,请重试')); |
|
|
}) |
|
|
.finally(() => { |
|
|
setLoading(false); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
const combinedRate = useMemo(() => { |
|
|
const type = inputs['general_setting.quota_display_type']; |
|
|
if (type === 'USD') return '1'; |
|
|
if (type === 'CNY') return String(inputs['USDExchangeRate'] || ''); |
|
|
if (type === 'TOKENS') return String(inputs['QuotaPerUnit'] || ''); |
|
|
if (type === 'CUSTOM') |
|
|
return String( |
|
|
inputs['general_setting.custom_currency_exchange_rate'] || '', |
|
|
); |
|
|
return ''; |
|
|
}, [inputs]); |
|
|
|
|
|
const onCombinedRateChange = (val) => { |
|
|
const type = inputs['general_setting.quota_display_type']; |
|
|
if (type === 'CNY') { |
|
|
handleFieldChange('USDExchangeRate')(val); |
|
|
} else if (type === 'TOKENS') { |
|
|
handleFieldChange('QuotaPerUnit')(val); |
|
|
} else if (type === 'CUSTOM') { |
|
|
handleFieldChange('general_setting.custom_currency_exchange_rate')(val); |
|
|
} |
|
|
}; |
|
|
|
|
|
useEffect(() => { |
|
|
const currentInputs = {}; |
|
|
for (let key in props.options) { |
|
|
if (Object.keys(inputs).includes(key)) { |
|
|
currentInputs[key] = props.options[key]; |
|
|
} |
|
|
} |
|
|
|
|
|
if ( |
|
|
currentInputs['general_setting.quota_display_type'] === undefined && |
|
|
props.options?.DisplayInCurrencyEnabled !== undefined |
|
|
) { |
|
|
currentInputs['general_setting.quota_display_type'] = props.options |
|
|
.DisplayInCurrencyEnabled |
|
|
? 'USD' |
|
|
: 'TOKENS'; |
|
|
} |
|
|
|
|
|
if (props.options['general_setting.custom_currency_symbol'] !== undefined) { |
|
|
currentInputs['general_setting.custom_currency_symbol'] = |
|
|
props.options['general_setting.custom_currency_symbol']; |
|
|
} |
|
|
if ( |
|
|
props.options['general_setting.custom_currency_exchange_rate'] !== |
|
|
undefined |
|
|
) { |
|
|
currentInputs['general_setting.custom_currency_exchange_rate'] = |
|
|
props.options['general_setting.custom_currency_exchange_rate']; |
|
|
} |
|
|
setInputs(currentInputs); |
|
|
setInputsRow(structuredClone(currentInputs)); |
|
|
refForm.current.setValues(currentInputs); |
|
|
}, [props.options]); |
|
|
|
|
|
return ( |
|
|
<> |
|
|
<Spin spinning={loading}> |
|
|
<Form |
|
|
values={inputs} |
|
|
getFormApi={(formAPI) => (refForm.current = formAPI)} |
|
|
style={{ marginBottom: 15 }} |
|
|
> |
|
|
<Form.Section text={t('通用设置')}> |
|
|
<Row gutter={16}> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Input |
|
|
field={'TopUpLink'} |
|
|
label={t('充值链接')} |
|
|
initValue={''} |
|
|
placeholder={t('例如发卡网站的购买链接')} |
|
|
onChange={handleFieldChange('TopUpLink')} |
|
|
showClear |
|
|
/> |
|
|
</Col> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Input |
|
|
field={'general_setting.docs_link'} |
|
|
label={t('文档地址')} |
|
|
initValue={''} |
|
|
placeholder={t('例如 https://docs.newapi.pro')} |
|
|
onChange={handleFieldChange('general_setting.docs_link')} |
|
|
showClear |
|
|
/> |
|
|
</Col> |
|
|
{/* 单位美元额度已合入汇率组合控件(TOKENS 模式下编辑),不再单独展示 */} |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Input |
|
|
field={'RetryTimes'} |
|
|
label={t('失败重试次数')} |
|
|
initValue={''} |
|
|
placeholder={t('失败重试次数')} |
|
|
onChange={handleFieldChange('RetryTimes')} |
|
|
showClear |
|
|
/> |
|
|
</Col> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Slot label={t('站点额度展示类型及汇率')}> |
|
|
<InputGroup style={{ width: '100%' }}> |
|
|
<Input |
|
|
prefix={'1 USD = '} |
|
|
style={{ width: '50%' }} |
|
|
value={combinedRate} |
|
|
onChange={onCombinedRateChange} |
|
|
disabled={ |
|
|
inputs['general_setting.quota_display_type'] === 'USD' |
|
|
} |
|
|
/> |
|
|
<Select |
|
|
style={{ width: '50%' }} |
|
|
value={inputs['general_setting.quota_display_type']} |
|
|
onChange={handleFieldChange( |
|
|
'general_setting.quota_display_type', |
|
|
)} |
|
|
> |
|
|
<Select.Option value='USD'>USD ($)</Select.Option> |
|
|
<Select.Option value='CNY'>CNY (¥)</Select.Option> |
|
|
<Select.Option value='TOKENS'>Tokens</Select.Option> |
|
|
<Select.Option value='CUSTOM'> |
|
|
{t('自定义货币')} |
|
|
</Select.Option> |
|
|
</Select> |
|
|
</InputGroup> |
|
|
</Form.Slot> |
|
|
</Col> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Input |
|
|
field={'general_setting.custom_currency_symbol'} |
|
|
label={t('自定义货币符号')} |
|
|
placeholder={t('例如 €, £, Rp, ₩, ₹...')} |
|
|
onChange={handleFieldChange( |
|
|
'general_setting.custom_currency_symbol', |
|
|
)} |
|
|
showClear |
|
|
disabled={ |
|
|
inputs['general_setting.quota_display_type'] !== 'CUSTOM' |
|
|
} |
|
|
/> |
|
|
</Col> |
|
|
</Row> |
|
|
<Row gutter={16}> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Switch |
|
|
field={'DisplayTokenStatEnabled'} |
|
|
label={t('额度查询接口返回令牌额度而非用户额度')} |
|
|
size='default' |
|
|
checkedText='|' |
|
|
uncheckedText='〇' |
|
|
onChange={handleFieldChange('DisplayTokenStatEnabled')} |
|
|
/> |
|
|
</Col> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Switch |
|
|
field={'DefaultCollapseSidebar'} |
|
|
label={t('默认折叠侧边栏')} |
|
|
size='default' |
|
|
checkedText='|' |
|
|
uncheckedText='〇' |
|
|
onChange={handleFieldChange('DefaultCollapseSidebar')} |
|
|
/> |
|
|
</Col> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Switch |
|
|
field={'DemoSiteEnabled'} |
|
|
label={t('演示站点模式')} |
|
|
size='default' |
|
|
checkedText='|' |
|
|
uncheckedText='〇' |
|
|
onChange={handleFieldChange('DemoSiteEnabled')} |
|
|
/> |
|
|
</Col> |
|
|
<Col xs={24} sm={12} md={8} lg={8} xl={8}> |
|
|
<Form.Switch |
|
|
field={'SelfUseModeEnabled'} |
|
|
label={t('自用模式')} |
|
|
extraText={t('开启后不限制:必须设置模型倍率')} |
|
|
size='default' |
|
|
checkedText='|' |
|
|
uncheckedText='〇' |
|
|
onChange={handleFieldChange('SelfUseModeEnabled')} |
|
|
/> |
|
|
</Col> |
|
|
</Row> |
|
|
<Row> |
|
|
<Button size='default' onClick={onSubmit}> |
|
|
{t('保存通用设置')} |
|
|
</Button> |
|
|
</Row> |
|
|
</Form.Section> |
|
|
</Form> |
|
|
</Spin> |
|
|
|
|
|
<Modal |
|
|
title={t('警告')} |
|
|
visible={showQuotaWarning} |
|
|
onOk={() => setShowQuotaWarning(false)} |
|
|
onCancel={() => setShowQuotaWarning(false)} |
|
|
closeOnEsc={true} |
|
|
width={500} |
|
|
> |
|
|
<Banner |
|
|
type='warning' |
|
|
description={t( |
|
|
'此设置用于系统内部计算,默认值500000是为了精确到6位小数点设计,不推荐修改。', |
|
|
)} |
|
|
bordered |
|
|
fullMode={false} |
|
|
closeIcon={null} |
|
|
/> |
|
|
</Modal> |
|
|
</> |
|
|
); |
|
|
} |
|
|
|