|
|
@@ -26,6 +26,7 @@ import { |
|
|
Form, |
|
|
Form, |
|
|
Space, |
|
|
Space, |
|
|
Typography, |
|
|
Typography, |
|
|
|
|
|
RadioGroup, |
|
|
Radio, |
|
|
Radio, |
|
|
Notification, |
|
|
Notification, |
|
|
} from '@douyinfe/semi-ui'; |
|
|
} from '@douyinfe/semi-ui'; |
|
|
@@ -34,6 +35,7 @@ import { |
|
|
IconPlus, |
|
|
IconPlus, |
|
|
IconSearch, |
|
|
IconSearch, |
|
|
IconSave, |
|
|
IconSave, |
|
|
|
|
|
IconEdit, |
|
|
IconBolt, |
|
|
IconBolt, |
|
|
} from '@douyinfe/semi-icons'; |
|
|
} from '@douyinfe/semi-icons'; |
|
|
import { API, showError, showSuccess } from '../../../helpers'; |
|
|
import { API, showError, showSuccess } from '../../../helpers'; |
|
|
@@ -60,6 +62,8 @@ export default function ModelRatioNotSetEditor(props) { |
|
|
const editFormRef = useRef(null); |
|
|
const editFormRef = useRef(null); |
|
|
const [editVisible, setEditVisible] = useState(false); |
|
|
const [editVisible, setEditVisible] = useState(false); |
|
|
const [editRecord, setEditRecord] = useState(null); |
|
|
const [editRecord, setEditRecord] = useState(null); |
|
|
|
|
|
const [pricingMode, setPricingMode] = useState('per-token'); |
|
|
|
|
|
const [pricingSubMode, setPricingSubMode] = useState('ratio'); |
|
|
const { Text } = Typography; |
|
|
const { Text } = Typography; |
|
|
// 定义可选的每页显示条数 |
|
|
// 定义可选的每页显示条数 |
|
|
const pageSizeOptions = [10, 20, 50, 100]; |
|
|
const pageSizeOptions = [10, 20, 50, 100]; |
|
|
@@ -197,6 +201,11 @@ export default function ModelRatioNotSetEditor(props) { |
|
|
ModelPrice: JSON.stringify(output.ModelPrice, null, 2), |
|
|
ModelPrice: JSON.stringify(output.ModelPrice, null, 2), |
|
|
ModelRatio: JSON.stringify(output.ModelRatio, null, 2), |
|
|
ModelRatio: JSON.stringify(output.ModelRatio, null, 2), |
|
|
CompletionRatio: JSON.stringify(output.CompletionRatio, null, 2), |
|
|
CompletionRatio: JSON.stringify(output.CompletionRatio, null, 2), |
|
|
|
|
|
CacheRatio: JSON.stringify(output.CacheRatio, null, 2), |
|
|
|
|
|
CreateCacheRatio: JSON.stringify(output.CreateCacheRatio, null, 2), |
|
|
|
|
|
ImageRatio: JSON.stringify(output.ImageRatio, null, 2), |
|
|
|
|
|
AudioRatio: JSON.stringify(output.AudioRatio, null, 2), |
|
|
|
|
|
AudioCompletionRatio: JSON.stringify(output.AudioCompletionRatio, null, 2), |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const requestQueue = Object.entries(finalOutput).map(([key, value]) => { |
|
|
const requestQueue = Object.entries(finalOutput).map(([key, value]) => { |
|
|
@@ -288,15 +297,10 @@ export default function ModelRatioNotSetEditor(props) { |
|
|
key: 'action', |
|
|
key: 'action', |
|
|
render: (_, record) => ( |
|
|
render: (_, record) => ( |
|
|
<Button |
|
|
<Button |
|
|
size='small' |
|
|
|
|
|
icon={<IconBolt />} |
|
|
|
|
|
onClick={() => { |
|
|
|
|
|
setEditRecord(record); |
|
|
|
|
|
setEditVisible(true); |
|
|
|
|
|
}} |
|
|
|
|
|
> |
|
|
|
|
|
{t('高级比例')} |
|
|
|
|
|
</Button> |
|
|
|
|
|
|
|
|
type='primary' |
|
|
|
|
|
icon={<IconEdit />} |
|
|
|
|
|
onClick={() => openEditModal(record)} |
|
|
|
|
|
/> |
|
|
), |
|
|
), |
|
|
}, |
|
|
}, |
|
|
]; |
|
|
]; |
|
|
@@ -431,7 +435,6 @@ export default function ModelRatioNotSetEditor(props) { |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleBatchTypeChange = (value) => { |
|
|
const handleBatchTypeChange = (value) => { |
|
|
console.log(t('Changing batch type to:'), value); |
|
|
|
|
|
setBatchFillType(value); |
|
|
setBatchFillType(value); |
|
|
|
|
|
|
|
|
// 切换类型时清空对应的值 |
|
|
// 切换类型时清空对应的值 |
|
|
@@ -443,6 +446,60 @@ export default function ModelRatioNotSetEditor(props) { |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const calculateTokenPriceFromRatio = (ratio) => { |
|
|
|
|
|
return ratio * 2; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const openEditModal = (record) => { |
|
|
|
|
|
const initialPricingMode = record.price !== '' ? 'per-request' : 'per-token'; |
|
|
|
|
|
const initialPricingSubMode = 'ratio'; |
|
|
|
|
|
|
|
|
|
|
|
setPricingMode(initialPricingMode); |
|
|
|
|
|
setPricingSubMode(initialPricingSubMode); |
|
|
|
|
|
|
|
|
|
|
|
const modelCopy = { ...record }; |
|
|
|
|
|
|
|
|
|
|
|
// 计算tokenPrice(从ratio反推) |
|
|
|
|
|
if (record.ratio) { |
|
|
|
|
|
modelCopy.tokenPrice = calculateTokenPriceFromRatio( |
|
|
|
|
|
parseFloat(record.ratio), |
|
|
|
|
|
).toString(); |
|
|
|
|
|
|
|
|
|
|
|
if (record.completionRatio) { |
|
|
|
|
|
modelCopy.completionTokenPrice = ( |
|
|
|
|
|
parseFloat(modelCopy.tokenPrice) * |
|
|
|
|
|
parseFloat(record.completionRatio) |
|
|
|
|
|
).toString(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
setEditRecord(modelCopy); |
|
|
|
|
|
setEditVisible(true); |
|
|
|
|
|
|
|
|
|
|
|
// 使用 setTimeout 确保表单渲染后再设置值 |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
if (editFormRef.current) { |
|
|
|
|
|
const formValues = {}; |
|
|
|
|
|
|
|
|
|
|
|
if (initialPricingMode === 'per-request') { |
|
|
|
|
|
formValues.priceInput = modelCopy.price; |
|
|
|
|
|
} else if (initialPricingMode === 'per-token') { |
|
|
|
|
|
formValues.ratioInput = modelCopy.ratio; |
|
|
|
|
|
formValues.completionRatioInput = modelCopy.completionRatio; |
|
|
|
|
|
formValues.modelTokenPrice = modelCopy.tokenPrice; |
|
|
|
|
|
formValues.completionTokenPrice = modelCopy.completionTokenPrice; |
|
|
|
|
|
} |
|
|
|
|
|
formValues.cacheRatio = modelCopy.cacheRatio; |
|
|
|
|
|
formValues.cacheCreationRatio = modelCopy.cacheCreationRatio; |
|
|
|
|
|
formValues.imageRatio = modelCopy.imageRatio; |
|
|
|
|
|
formValues.audioRatio = modelCopy.audioRatio; |
|
|
|
|
|
formValues.audioCompletionRatio = modelCopy.audioCompletionRatio; |
|
|
|
|
|
|
|
|
|
|
|
editFormRef.current.setValues(formValues); |
|
|
|
|
|
} |
|
|
|
|
|
}, 0); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
const rowSelection = { |
|
|
const rowSelection = { |
|
|
selectedRowKeys, |
|
|
selectedRowKeys, |
|
|
onChange: (selectedKeys) => { |
|
|
onChange: (selectedKeys) => { |
|
|
@@ -715,27 +772,87 @@ export default function ModelRatioNotSetEditor(props) { |
|
|
</Form> |
|
|
</Form> |
|
|
</Modal> |
|
|
</Modal> |
|
|
|
|
|
|
|
|
{/* 高级比例编辑弹窗 */} |
|
|
|
|
|
|
|
|
{/* 编辑模型弹窗 */} |
|
|
<Modal |
|
|
<Modal |
|
|
title={t('高级比例设置') + ' - ' + (editRecord?.name || '')} |
|
|
|
|
|
|
|
|
title={t('编辑模型') + ' - ' + (editRecord?.name || '')} |
|
|
visible={editVisible} |
|
|
visible={editVisible} |
|
|
onCancel={() => { |
|
|
onCancel={() => { |
|
|
setEditVisible(false); |
|
|
setEditVisible(false); |
|
|
setEditRecord(null); |
|
|
setEditRecord(null); |
|
|
|
|
|
setPricingMode('per-token'); |
|
|
|
|
|
setPricingSubMode('ratio'); |
|
|
}} |
|
|
}} |
|
|
onOk={() => { |
|
|
onOk={() => { |
|
|
if (editRecord && editFormRef.current) { |
|
|
if (editRecord && editFormRef.current) { |
|
|
|
|
|
const valuesToSave = { ...editRecord }; |
|
|
|
|
|
|
|
|
|
|
|
// 处理按价格设置模式 |
|
|
|
|
|
if ( |
|
|
|
|
|
pricingMode === 'per-token' && |
|
|
|
|
|
pricingSubMode === 'token-price' && |
|
|
|
|
|
editRecord.tokenPrice |
|
|
|
|
|
) { |
|
|
|
|
|
const tokenPrice = parseFloat(editRecord.tokenPrice); |
|
|
|
|
|
valuesToSave.ratio = (tokenPrice / 2).toString(); |
|
|
|
|
|
|
|
|
|
|
|
if (editRecord.completionTokenPrice) { |
|
|
|
|
|
const completionPrice = parseFloat( |
|
|
|
|
|
editRecord.completionTokenPrice, |
|
|
|
|
|
); |
|
|
|
|
|
const modelPrice = parseFloat(editRecord.tokenPrice); |
|
|
|
|
|
if (modelPrice > 0) { |
|
|
|
|
|
valuesToSave.completionRatio = ( |
|
|
|
|
|
completionPrice / modelPrice |
|
|
|
|
|
).toString(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 根据定价模式清理字段 |
|
|
|
|
|
if (pricingMode === 'per-token') { |
|
|
|
|
|
valuesToSave.price = ''; |
|
|
|
|
|
} else { |
|
|
|
|
|
valuesToSave.ratio = ''; |
|
|
|
|
|
valuesToSave.completionRatio = ''; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 从表单读取高级倍率字段 |
|
|
const formValues = editFormRef.current.getValues(); |
|
|
const formValues = editFormRef.current.getValues(); |
|
|
|
|
|
valuesToSave.cacheRatio = |
|
|
|
|
|
formValues.cacheRatio != null |
|
|
|
|
|
? formValues.cacheRatio |
|
|
|
|
|
: ''; |
|
|
|
|
|
valuesToSave.cacheCreationRatio = |
|
|
|
|
|
formValues.cacheCreationRatio != null |
|
|
|
|
|
? formValues.cacheCreationRatio |
|
|
|
|
|
: ''; |
|
|
|
|
|
valuesToSave.imageRatio = |
|
|
|
|
|
formValues.imageRatio != null |
|
|
|
|
|
? formValues.imageRatio |
|
|
|
|
|
: ''; |
|
|
|
|
|
valuesToSave.audioRatio = |
|
|
|
|
|
formValues.audioRatio != null |
|
|
|
|
|
? formValues.audioRatio |
|
|
|
|
|
: ''; |
|
|
|
|
|
valuesToSave.audioCompletionRatio = |
|
|
|
|
|
formValues.audioCompletionRatio != null |
|
|
|
|
|
? formValues.audioCompletionRatio |
|
|
|
|
|
: ''; |
|
|
|
|
|
|
|
|
setModels((prev) => |
|
|
setModels((prev) => |
|
|
prev.map((model) => { |
|
|
prev.map((model) => { |
|
|
if (model.name !== editRecord.name) return model; |
|
|
if (model.name !== editRecord.name) return model; |
|
|
return { |
|
|
return { |
|
|
...model, |
|
|
...model, |
|
|
cacheRatio: formValues.cacheRatio != null ? formValues.cacheRatio : model.cacheRatio, |
|
|
|
|
|
cacheCreationRatio: formValues.cacheCreationRatio != null ? formValues.cacheCreationRatio : model.cacheCreationRatio, |
|
|
|
|
|
imageRatio: formValues.imageRatio != null ? formValues.imageRatio : model.imageRatio, |
|
|
|
|
|
audioRatio: formValues.audioRatio != null ? formValues.audioRatio : model.audioRatio, |
|
|
|
|
|
audioCompletionRatio: formValues.audioCompletionRatio != null ? formValues.audioCompletionRatio : model.audioCompletionRatio, |
|
|
|
|
|
|
|
|
price: valuesToSave.price, |
|
|
|
|
|
ratio: valuesToSave.ratio, |
|
|
|
|
|
completionRatio: valuesToSave.completionRatio, |
|
|
|
|
|
cacheRatio: valuesToSave.cacheRatio, |
|
|
|
|
|
cacheCreationRatio: valuesToSave.cacheCreationRatio, |
|
|
|
|
|
imageRatio: valuesToSave.imageRatio, |
|
|
|
|
|
audioRatio: valuesToSave.audioRatio, |
|
|
|
|
|
audioCompletionRatio: |
|
|
|
|
|
valuesToSave.audioCompletionRatio, |
|
|
}; |
|
|
}; |
|
|
}), |
|
|
}), |
|
|
); |
|
|
); |
|
|
@@ -748,51 +865,181 @@ export default function ModelRatioNotSetEditor(props) { |
|
|
<Form |
|
|
<Form |
|
|
key={editRecord?.name || 'empty'} |
|
|
key={editRecord?.name || 'empty'} |
|
|
getFormApi={(api) => (editFormRef.current = api)} |
|
|
getFormApi={(api) => (editFormRef.current = api)} |
|
|
initValues={{ |
|
|
|
|
|
cacheRatio: editRecord?.cacheRatio ?? '', |
|
|
|
|
|
cacheCreationRatio: editRecord?.cacheCreationRatio ?? '', |
|
|
|
|
|
imageRatio: editRecord?.imageRatio ?? '', |
|
|
|
|
|
audioRatio: editRecord?.audioRatio ?? '', |
|
|
|
|
|
audioCompletionRatio: editRecord?.audioCompletionRatio ?? '', |
|
|
|
|
|
}} |
|
|
|
|
|
> |
|
|
> |
|
|
<Form.InputNumber |
|
|
|
|
|
field='cacheRatio' |
|
|
|
|
|
label={t('缓存读取倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值(1.0)')} |
|
|
|
|
|
extraText={t('缓存命中时输入价格的倍率。0.5 = 缓存命中的 token 按输入价格的一半计费,留空使用全局默认值 1.0')} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='cacheCreationRatio' |
|
|
|
|
|
label={t('缓存创建倍率(5分钟)')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值(1.25)')} |
|
|
|
|
|
extraText={t('写入缓存的 token 按此倍率 × 输入价格计费。默认 1.25(5分钟 TTL);超过 1 小时自动按 1.6x 计费,留空使用全局默认值')} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='imageRatio' |
|
|
|
|
|
label={t('图片倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值')} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='audioRatio' |
|
|
|
|
|
label={t('音频输入倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值')} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='audioCompletionRatio' |
|
|
|
|
|
label={t('音频输出倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值')} |
|
|
|
|
|
/> |
|
|
|
|
|
|
|
|
<Form.Section text={t('定价模式')}> |
|
|
|
|
|
<div style={{ marginBottom: '16px' }}> |
|
|
|
|
|
<RadioGroup |
|
|
|
|
|
type='button' |
|
|
|
|
|
value={pricingMode} |
|
|
|
|
|
onChange={(e) => { |
|
|
|
|
|
setPricingMode(e.target.value); |
|
|
|
|
|
}} |
|
|
|
|
|
> |
|
|
|
|
|
<Radio value='per-token'>{t('按量计费')}</Radio> |
|
|
|
|
|
<Radio value='per-request'>{t('按次计费')}</Radio> |
|
|
|
|
|
</RadioGroup> |
|
|
|
|
|
</div> |
|
|
|
|
|
</Form.Section> |
|
|
|
|
|
|
|
|
|
|
|
{pricingMode === 'per-token' && ( |
|
|
|
|
|
<> |
|
|
|
|
|
<Form.Section text={t('价格设置方式')}> |
|
|
|
|
|
<div style={{ marginBottom: '16px' }}> |
|
|
|
|
|
<RadioGroup |
|
|
|
|
|
type='button' |
|
|
|
|
|
value={pricingSubMode} |
|
|
|
|
|
onChange={(e) => { |
|
|
|
|
|
setPricingSubMode(e.target.value); |
|
|
|
|
|
}} |
|
|
|
|
|
> |
|
|
|
|
|
<Radio value='ratio'>{t('按倍率设置')}</Radio> |
|
|
|
|
|
<Radio value='token-price'> |
|
|
|
|
|
{t('按价格设置')} |
|
|
|
|
|
</Radio> |
|
|
|
|
|
</RadioGroup> |
|
|
|
|
|
</div> |
|
|
|
|
|
</Form.Section> |
|
|
|
|
|
|
|
|
|
|
|
{pricingSubMode === 'ratio' && ( |
|
|
|
|
|
<> |
|
|
|
|
|
<Form.Input |
|
|
|
|
|
field='ratioInput' |
|
|
|
|
|
label={t('模型倍率')} |
|
|
|
|
|
placeholder={t('输入模型倍率')} |
|
|
|
|
|
onChange={(value) => |
|
|
|
|
|
setEditRecord((prev) => |
|
|
|
|
|
prev ? { ...prev, ratio: value } : prev, |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
initValue={editRecord?.ratio || ''} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.Input |
|
|
|
|
|
field='completionRatioInput' |
|
|
|
|
|
label={t('补全倍率')} |
|
|
|
|
|
placeholder={t('输入补全倍率')} |
|
|
|
|
|
onChange={(value) => |
|
|
|
|
|
setEditRecord((prev) => |
|
|
|
|
|
prev |
|
|
|
|
|
? { ...prev, completionRatio: value } |
|
|
|
|
|
: prev, |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
initValue={editRecord?.completionRatio || ''} |
|
|
|
|
|
/> |
|
|
|
|
|
</> |
|
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
|
|
{pricingSubMode === 'token-price' && ( |
|
|
|
|
|
<> |
|
|
|
|
|
<Form.Input |
|
|
|
|
|
field='modelTokenPrice' |
|
|
|
|
|
label={t('输入价格')} |
|
|
|
|
|
suffix={t('$/1M tokens')} |
|
|
|
|
|
onChange={(value) => { |
|
|
|
|
|
let updated = { |
|
|
|
|
|
...(editRecord || {}), |
|
|
|
|
|
tokenPrice: value, |
|
|
|
|
|
ratio: 0, |
|
|
|
|
|
}; |
|
|
|
|
|
if (!isNaN(value) && value !== '') { |
|
|
|
|
|
const tokenPrice = parseFloat(value); |
|
|
|
|
|
updated.ratio = (tokenPrice / 2).toString(); |
|
|
|
|
|
} |
|
|
|
|
|
setEditRecord(updated); |
|
|
|
|
|
}} |
|
|
|
|
|
initValue={editRecord?.tokenPrice || ''} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.Input |
|
|
|
|
|
field='completionTokenPrice' |
|
|
|
|
|
label={t('输出价格')} |
|
|
|
|
|
suffix={t('$/1M tokens')} |
|
|
|
|
|
onChange={(value) => { |
|
|
|
|
|
let updated = { |
|
|
|
|
|
...(editRecord || {}), |
|
|
|
|
|
completionTokenPrice: value, |
|
|
|
|
|
completionRatio: 0, |
|
|
|
|
|
}; |
|
|
|
|
|
if ( |
|
|
|
|
|
!isNaN(value) && |
|
|
|
|
|
value !== '' && |
|
|
|
|
|
editRecord?.tokenPrice |
|
|
|
|
|
) { |
|
|
|
|
|
const completionPrice = parseFloat(value); |
|
|
|
|
|
const modelPrice = parseFloat( |
|
|
|
|
|
editRecord.tokenPrice, |
|
|
|
|
|
); |
|
|
|
|
|
if (modelPrice > 0) { |
|
|
|
|
|
updated.completionRatio = ( |
|
|
|
|
|
completionPrice / modelPrice |
|
|
|
|
|
).toString(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
setEditRecord(updated); |
|
|
|
|
|
}} |
|
|
|
|
|
initValue={editRecord?.completionTokenPrice || ''} |
|
|
|
|
|
/> |
|
|
|
|
|
</> |
|
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
|
|
<Form.Section text={t('高级比例(留空使用默认值)')}> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='cacheRatio' |
|
|
|
|
|
label={t('缓存读取倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值(1.0)')} |
|
|
|
|
|
extraText={t( |
|
|
|
|
|
'缓存命中时输入价格的倍率。0.5 = 缓存命中的 token 按输入价格的一半计费,留空使用全局默认值 1.0', |
|
|
|
|
|
)} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='cacheCreationRatio' |
|
|
|
|
|
label={t('缓存创建倍率(5分钟)')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值(1.25)')} |
|
|
|
|
|
extraText={t( |
|
|
|
|
|
'写入缓存的 token 按此倍率 × 输入价格计费。默认 1.25(5分钟 TTL);超过 1 小时自动按 1.6x 计费,留空使用全局默认值', |
|
|
|
|
|
)} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='imageRatio' |
|
|
|
|
|
label={t('图片倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值')} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='audioRatio' |
|
|
|
|
|
label={t('音频输入倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值')} |
|
|
|
|
|
/> |
|
|
|
|
|
<Form.InputNumber |
|
|
|
|
|
field='audioCompletionRatio' |
|
|
|
|
|
label={t('音频输出倍率')} |
|
|
|
|
|
min={0} |
|
|
|
|
|
step={0.01} |
|
|
|
|
|
placeholder={t('全局默认值')} |
|
|
|
|
|
/> |
|
|
|
|
|
</Form.Section> |
|
|
|
|
|
</> |
|
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
|
|
{pricingMode === 'per-request' && ( |
|
|
|
|
|
<Form.Input |
|
|
|
|
|
field='priceInput' |
|
|
|
|
|
label={t('固定价格(每次)')} |
|
|
|
|
|
placeholder={t('输入每次价格')} |
|
|
|
|
|
onChange={(value) => |
|
|
|
|
|
setEditRecord((prev) => |
|
|
|
|
|
prev ? { ...prev, price: value } : prev, |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
initValue={editRecord?.price || ''} |
|
|
|
|
|
/> |
|
|
|
|
|
)} |
|
|
</Form> |
|
|
</Form> |
|
|
</Modal> |
|
|
</Modal> |
|
|
</> |
|
|
</> |
|
|
|