feat: 二次确认添加重定向前模型

This commit is contained in:
Seefs 2025-11-22 19:23:27 +08:00
parent 4dbbf06adc
commit d6939d2f64

View File

@ -220,6 +220,8 @@ const EditChannelModal = (props) => {
]; ];
const formContainerRef = useRef(null); const formContainerRef = useRef(null);
const doubaoApiClickCountRef = useRef(0); const doubaoApiClickCountRef = useRef(0);
const initialModelsRef = useRef([]);
const initialModelMappingRef = useRef('');
// 2FA // 2FA
const updateTwoFAState = (updates) => { const updateTwoFAState = (updates) => {
@ -595,6 +597,10 @@ const EditChannelModal = (props) => {
system_prompt: data.system_prompt, system_prompt: data.system_prompt,
system_prompt_override: data.system_prompt_override || false, system_prompt_override: data.system_prompt_override || false,
}); });
initialModelsRef.current = (data.models || [])
.map((model) => (model || '').trim())
.filter(Boolean);
initialModelMappingRef.current = data.model_mapping || '';
// console.log(data); // console.log(data);
} else { } else {
showError(message); showError(message);
@ -830,6 +836,13 @@ const EditChannelModal = (props) => {
} }
}, [props.visible, channelId]); }, [props.visible, channelId]);
useEffect(() => {
if (!isEdit) {
initialModelsRef.current = [];
initialModelMappingRef.current = '';
}
}, [isEdit, props.visible]);
// //
const resetModalState = () => { const resetModalState = () => {
formApiRef.current?.reset(); formApiRef.current?.reset();
@ -903,6 +916,80 @@ const EditChannelModal = (props) => {
})(); })();
}; };
const confirmMissingModelMappings = (missingModels) =>
new Promise((resolve) => {
const modal = Modal.confirm({
title: t('模型未加入列表,可能无法调用'),
content: (
<div className='text-sm leading-6'>
<div>
{t(
'模型重定向里的下列模型尚未添加到“模型”列表,调用时会因为缺少可用模型而失败:',
)}
</div>
<div className='font-mono text-xs break-all text-red-600 mt-1'>
{missingModels.join(', ')}
</div>
<div className='mt-2'>
{t(
'你可以在“自定义模型名称”处手动添加它们,然后点击填入后再提交,或者直接使用下方操作自动处理。',
)}
</div>
</div>
),
centered: true,
footer: (
<Space align='center' className='w-full justify-end'>
<Button
type='tertiary'
onClick={() => {
modal.destroy();
resolve('cancel');
}}
>
{t('返回修改')}
</Button>
<Button
type='primary'
theme='light'
onClick={() => {
modal.destroy();
resolve('submit');
}}
>
{t('直接提交')}
</Button>
<Button
type='primary'
theme='solid'
onClick={() => {
modal.destroy();
resolve('add');
}}
>
{t('添加后提交')}
</Button>
</Space>
),
});
});
const hasModelConfigChanged = (normalizedModels, modelMappingStr) => {
if (!isEdit) return true;
const initialModels = initialModelsRef.current;
if (normalizedModels.length !== initialModels.length) {
return true;
}
for (let i = 0; i < normalizedModels.length; i++) {
if (normalizedModels[i] !== initialModels[i]) {
return true;
}
}
const normalizedMapping = (modelMappingStr || '').trim();
const initialMapping = (initialModelMappingRef.current || '').trim();
return normalizedMapping !== initialMapping;
};
const submit = async () => { const submit = async () => {
const formValues = formApiRef.current ? formApiRef.current.getValues() : {}; const formValues = formApiRef.current ? formApiRef.current.getValues() : {};
let localInputs = { ...formValues }; let localInputs = { ...formValues };
@ -986,14 +1073,55 @@ const EditChannelModal = (props) => {
showInfo(t('请输入API地址')); showInfo(t('请输入API地址'));
return; return;
} }
if ( const hasModelMapping =
localInputs.model_mapping && typeof localInputs.model_mapping === 'string' &&
localInputs.model_mapping !== '' && localInputs.model_mapping.trim() !== '';
!verifyJSON(localInputs.model_mapping) let parsedModelMapping = null;
) { if (hasModelMapping) {
showInfo(t('模型映射必须是合法的 JSON 格式!')); if (!verifyJSON(localInputs.model_mapping)) {
return; showInfo(t('模型映射必须是合法的 JSON 格式!'));
return;
}
try {
parsedModelMapping = JSON.parse(localInputs.model_mapping);
} catch (error) {
showInfo(t('模型映射必须是合法的 JSON 格式!'));
return;
}
} }
const normalizedModels = (localInputs.models || [])
.map((model) => (model || '').trim())
.filter(Boolean);
localInputs.models = normalizedModels;
if (
parsedModelMapping &&
typeof parsedModelMapping === 'object' &&
!Array.isArray(parsedModelMapping)
) {
const modelSet = new Set(normalizedModels);
const missingModels = Object.keys(parsedModelMapping)
.map((key) => (key || '').trim())
.filter((key) => key && !modelSet.has(key));
const shouldPromptMissing =
missingModels.length > 0 &&
hasModelConfigChanged(normalizedModels, localInputs.model_mapping);
if (shouldPromptMissing) {
const confirmAction = await confirmMissingModelMappings(missingModels);
if (confirmAction === 'cancel') {
return;
}
if (confirmAction === 'add') {
const updatedModels = Array.from(
new Set([...normalizedModels, ...missingModels]),
);
localInputs.models = updatedModels;
handleInputChange('models', updatedModels);
}
}
}
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,