Merge pull request #4470 from seefs001/feature/show-removed-upstream-models
feat: show removed upstream models in fetch models modal
This commit is contained in:
@@ -269,6 +269,24 @@ const EditChannelModal = (props) => {
|
||||
return [];
|
||||
}
|
||||
}, [inputs.model_mapping]);
|
||||
const redirectModelKeyList = useMemo(() => {
|
||||
const mapping = inputs.model_mapping;
|
||||
if (typeof mapping !== 'string') return [];
|
||||
const trimmed = mapping.trim();
|
||||
if (!trimmed) return [];
|
||||
try {
|
||||
const parsed = JSON.parse(trimmed);
|
||||
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
||||
return [];
|
||||
}
|
||||
const keys = Object.keys(parsed)
|
||||
.map((key) => key.trim())
|
||||
.filter((key) => key);
|
||||
return Array.from(new Set(keys));
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}, [inputs.model_mapping]);
|
||||
const upstreamDetectedModels = useMemo(
|
||||
() =>
|
||||
Array.from(
|
||||
@@ -3842,6 +3860,7 @@ const EditChannelModal = (props) => {
|
||||
models={fetchedModels}
|
||||
selected={inputs.models}
|
||||
redirectModels={redirectModelList}
|
||||
redirectSourceModels={redirectModelKeyList}
|
||||
onConfirm={(selectedModels) => {
|
||||
handleInputChange('models', selectedModels);
|
||||
showSuccess(t('模型列表已更新'));
|
||||
|
||||
@@ -43,6 +43,7 @@ const ModelSelectModal = ({
|
||||
models = [],
|
||||
selected = [],
|
||||
redirectModels = [],
|
||||
redirectSourceModels = [],
|
||||
onConfirm,
|
||||
onCancel,
|
||||
}) => {
|
||||
@@ -54,6 +55,14 @@ const ModelSelectModal = ({
|
||||
if (typeof model === 'object' && model.model_name) return model.model_name;
|
||||
return String(model ?? '');
|
||||
};
|
||||
const normalizeModelList = (modelList = []) =>
|
||||
Array.from(
|
||||
new Set(
|
||||
(modelList || [])
|
||||
.map((model) => getModelName(model).trim())
|
||||
.filter(Boolean),
|
||||
),
|
||||
);
|
||||
|
||||
const normalizedSelected = useMemo(
|
||||
() => (selected || []).map(getModelName),
|
||||
@@ -78,6 +87,10 @@ const ModelSelectModal = ({
|
||||
),
|
||||
[redirectModels],
|
||||
);
|
||||
const normalizedRedirectSourceSet = useMemo(
|
||||
() => new Set(normalizeModelList(redirectSourceModels)),
|
||||
[redirectSourceModels],
|
||||
);
|
||||
const normalizedSelectedSet = useMemo(() => {
|
||||
const set = new Set();
|
||||
(selected || []).forEach((model) => {
|
||||
@@ -116,6 +129,16 @@ const ModelSelectModal = ({
|
||||
const existingModels = filteredModels.filter((model) =>
|
||||
isExistingModel(model),
|
||||
);
|
||||
const fetchedModelSet = useMemo(
|
||||
() => new Set(normalizeModelList(models)),
|
||||
[models],
|
||||
);
|
||||
const removedModels = normalizeModelList(selected).filter(
|
||||
(model) =>
|
||||
!fetchedModelSet.has(model) &&
|
||||
!normalizedRedirectSourceSet.has(model) &&
|
||||
model.toLowerCase().includes(keyword.toLowerCase()),
|
||||
);
|
||||
|
||||
// 同步外部选中值
|
||||
useEffect(() => {
|
||||
@@ -127,11 +150,15 @@ const ModelSelectModal = ({
|
||||
// 当模型列表变化时,设置默认tab
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
// 默认显示新获取模型tab,如果没有新模型则显示已有模型
|
||||
const hasNewModels = newModels.length > 0;
|
||||
setActiveTab(hasNewModels ? 'new' : 'existing');
|
||||
if (newModels.length > 0) {
|
||||
setActiveTab('new');
|
||||
} else if (removedModels.length > 0) {
|
||||
setActiveTab('removed');
|
||||
} else {
|
||||
setActiveTab('existing');
|
||||
}
|
||||
}
|
||||
}, [visible, newModels.length, selected]);
|
||||
}, [visible, newModels.length, removedModels.length, selected]);
|
||||
|
||||
const handleOk = () => {
|
||||
onConfirm && onConfirm(checkedList);
|
||||
@@ -197,6 +224,14 @@ const ModelSelectModal = ({
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(removedModels.length > 0
|
||||
? [
|
||||
{
|
||||
tab: `${t('上游已删除的模型')} (${removedModels.length})`,
|
||||
itemKey: 'removed',
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
// 处理分类全选/取消全选
|
||||
@@ -343,9 +378,11 @@ const ModelSelectModal = ({
|
||||
showClear
|
||||
/>
|
||||
|
||||
<Spin spinning={!models || models.length === 0}>
|
||||
<Spin
|
||||
spinning={!models || (models.length === 0 && removedModels.length === 0)}
|
||||
>
|
||||
<div style={{ maxHeight: 400, overflowY: 'auto', paddingRight: 8 }}>
|
||||
{filteredModels.length === 0 ? (
|
||||
{filteredModels.length === 0 && removedModels.length === 0 ? (
|
||||
<Empty
|
||||
image={
|
||||
<IllustrationNoResult style={{ width: 150, height: 150 }} />
|
||||
@@ -369,6 +406,14 @@ const ModelSelectModal = ({
|
||||
{renderModelsByCategory(existingModelsByCategory, 'existing')}
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 'removed' && removedModels.length > 0 && (
|
||||
<div>
|
||||
{renderModelsByCategory(
|
||||
categorizeModels(removedModels),
|
||||
'removed',
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Checkbox.Group>
|
||||
)}
|
||||
</div>
|
||||
@@ -382,7 +427,11 @@ const ModelSelectModal = ({
|
||||
<div className='flex items-center justify-end gap-2'>
|
||||
{(() => {
|
||||
const currentModels =
|
||||
activeTab === 'new' ? newModels : existingModels;
|
||||
activeTab === 'new'
|
||||
? newModels
|
||||
: activeTab === 'removed'
|
||||
? removedModels
|
||||
: existingModels;
|
||||
const currentSelected = currentModels.filter((model) =>
|
||||
checkedList.includes(model),
|
||||
).length;
|
||||
|
||||
Reference in New Issue
Block a user