|
|
@@ -8,7 +8,9 @@ import {
|
|
|
Form,
|
|
|
Space,
|
|
|
RadioGroup,
|
|
|
- Radio
|
|
|
+ Radio,
|
|
|
+ Checkbox,
|
|
|
+ Tag
|
|
|
} from '@douyinfe/semi-ui';
|
|
|
import {
|
|
|
IconDelete,
|
|
|
@@ -30,6 +32,7 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
const [pricingMode, setPricingMode] = useState('per-token'); // 'per-token' or 'per-request'
|
|
|
const [pricingSubMode, setPricingSubMode] = useState('ratio'); // 'ratio' or 'token-price'
|
|
|
+ const [conflictOnly, setConflictOnly] = useState(false);
|
|
|
const formRef = useRef(null);
|
|
|
const pageSize = 10;
|
|
|
const quotaPerUnit = getQuotaPerUnit();
|
|
|
@@ -47,13 +50,19 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
...Object.keys(completionRatio),
|
|
|
]);
|
|
|
|
|
|
- const modelData = Array.from(modelNames).map((name) => ({
|
|
|
- name,
|
|
|
- price: modelPrice[name] === undefined ? '' : modelPrice[name],
|
|
|
- ratio: modelRatio[name] === undefined ? '' : modelRatio[name],
|
|
|
- completionRatio:
|
|
|
- completionRatio[name] === undefined ? '' : completionRatio[name],
|
|
|
- }));
|
|
|
+ const modelData = Array.from(modelNames).map((name) => {
|
|
|
+ const price = modelPrice[name] === undefined ? '' : modelPrice[name];
|
|
|
+ const ratio = modelRatio[name] === undefined ? '' : modelRatio[name];
|
|
|
+ const comp = completionRatio[name] === undefined ? '' : completionRatio[name];
|
|
|
+
|
|
|
+ return {
|
|
|
+ name,
|
|
|
+ price,
|
|
|
+ ratio,
|
|
|
+ completionRatio: comp,
|
|
|
+ hasConflict: price !== '' && (ratio !== '' || comp !== ''),
|
|
|
+ };
|
|
|
+ });
|
|
|
|
|
|
setModels(modelData);
|
|
|
} catch (error) {
|
|
|
@@ -69,11 +78,13 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
};
|
|
|
|
|
|
// 在 return 语句之前,先处理过滤和分页逻辑
|
|
|
- const filteredModels = models.filter((model) =>
|
|
|
- searchText
|
|
|
+ const filteredModels = models.filter((model) => {
|
|
|
+ const keywordMatch = searchText
|
|
|
? model.name.toLowerCase().includes(searchText.toLowerCase())
|
|
|
- : true,
|
|
|
- );
|
|
|
+ : true;
|
|
|
+ const conflictMatch = conflictOnly ? model.hasConflict : true;
|
|
|
+ return keywordMatch && conflictMatch;
|
|
|
+ });
|
|
|
|
|
|
// 然后基于过滤后的数据计算分页数据
|
|
|
const pagedData = getPagedData(filteredModels, currentPage, pageSize);
|
|
|
@@ -152,6 +163,16 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
title: t('模型名称'),
|
|
|
dataIndex: 'name',
|
|
|
key: 'name',
|
|
|
+ render: (text, record) => (
|
|
|
+ <span>
|
|
|
+ {text}
|
|
|
+ {record.hasConflict && (
|
|
|
+ <Tag color='red' shape='circle' className='ml-2'>
|
|
|
+ {t('矛盾')}
|
|
|
+ </Tag>
|
|
|
+ )}
|
|
|
+ </span>
|
|
|
+ ),
|
|
|
},
|
|
|
{
|
|
|
title: t('模型固定价格'),
|
|
|
@@ -219,9 +240,13 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
return;
|
|
|
}
|
|
|
setModels((prev) =>
|
|
|
- prev.map((model) =>
|
|
|
- model.name === name ? { ...model, [field]: value } : model,
|
|
|
- ),
|
|
|
+ prev.map((model) => {
|
|
|
+ if (model.name !== name) return model;
|
|
|
+ const updated = { ...model, [field]: value };
|
|
|
+ updated.hasConflict =
|
|
|
+ updated.price !== '' && (updated.ratio !== '' || updated.completionRatio !== '');
|
|
|
+ return updated;
|
|
|
+ }),
|
|
|
);
|
|
|
};
|
|
|
|
|
|
@@ -296,16 +321,18 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
if (existingModelIndex >= 0) {
|
|
|
// Update existing model
|
|
|
setModels((prev) =>
|
|
|
- prev.map((model, index) =>
|
|
|
- index === existingModelIndex
|
|
|
- ? {
|
|
|
- name: values.name,
|
|
|
- price: values.price || '',
|
|
|
- ratio: values.ratio || '',
|
|
|
- completionRatio: values.completionRatio || '',
|
|
|
- }
|
|
|
- : model,
|
|
|
- ),
|
|
|
+ prev.map((model, index) => {
|
|
|
+ if (index !== existingModelIndex) return model;
|
|
|
+ const updated = {
|
|
|
+ name: values.name,
|
|
|
+ price: values.price || '',
|
|
|
+ ratio: values.ratio || '',
|
|
|
+ completionRatio: values.completionRatio || '',
|
|
|
+ };
|
|
|
+ updated.hasConflict =
|
|
|
+ updated.price !== '' && (updated.ratio !== '' || updated.completionRatio !== '');
|
|
|
+ return updated;
|
|
|
+ }),
|
|
|
);
|
|
|
setVisible(false);
|
|
|
showSuccess(t('更新成功'));
|
|
|
@@ -317,15 +344,17 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- setModels((prev) => [
|
|
|
- {
|
|
|
+ setModels((prev) => {
|
|
|
+ const newModel = {
|
|
|
name: values.name,
|
|
|
price: values.price || '',
|
|
|
ratio: values.ratio || '',
|
|
|
completionRatio: values.completionRatio || '',
|
|
|
- },
|
|
|
- ...prev,
|
|
|
- ]);
|
|
|
+ };
|
|
|
+ newModel.hasConflict =
|
|
|
+ newModel.price !== '' && (newModel.ratio !== '' || newModel.completionRatio !== '');
|
|
|
+ return [newModel, ...prev];
|
|
|
+ });
|
|
|
setVisible(false);
|
|
|
showSuccess(t('添加成功'));
|
|
|
}
|
|
|
@@ -427,6 +456,15 @@ export default function ModelSettingsVisualEditor(props) {
|
|
|
}}
|
|
|
style={{ width: 200 }}
|
|
|
/>
|
|
|
+ <Checkbox
|
|
|
+ checked={conflictOnly}
|
|
|
+ onChange={(e) => {
|
|
|
+ setConflictOnly(e.target.checked);
|
|
|
+ setCurrentPage(1);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {t('仅显示矛盾倍率')}
|
|
|
+ </Checkbox>
|
|
|
</Space>
|
|
|
<Table
|
|
|
columns={columns}
|