feat: improve SelectModelPopup (#2740)

* fix: do not match provider id for non-system models

* feat: match multiple words
This commit is contained in:
one 2025-03-04 10:11:54 +08:00 committed by GitHub
parent 886a7ec1e9
commit 0e4f06e86a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -63,41 +63,59 @@ const PopupContainer: React.FC<PopupContainerProps> = ({ model, resolve }) => {
setPinnedModels(sortBy(newPinnedModels, ['group', 'name'])) setPinnedModels(sortBy(newPinnedModels, ['group', 'name']))
} }
// 根据输入的文本筛选模型
const getFilteredModels = useCallback(
(provider) => {
const nonEmbeddingModels = provider.models.filter((m) => !isEmbeddingModel(m))
if (!searchText.trim()) {
return sortBy(nonEmbeddingModels, ['group', 'name'])
}
const keywords = searchText.toLowerCase().split(/\s+/).filter(Boolean)
return sortBy(nonEmbeddingModels, ['group', 'name']).filter((m) => {
const fullName = provider.isSystem
? `${m.name}${m.provider}${t('provider.' + provider.id)}`
: `${m.name}${m.provider}`
const lowerFullName = fullName.toLowerCase()
return keywords.every((keyword) => lowerFullName.includes(keyword))
})
},
[searchText, t]
)
const filteredItems: MenuItem[] = providers const filteredItems: MenuItem[] = providers
.filter((p) => p.models && p.models.length > 0) .filter((p) => p.models && p.models.length > 0)
.map((p) => { .map((p) => {
const filteredModels = sortBy(p.models, ['group', 'name']) const filteredModels = getFilteredModels(p).map((m) => ({
.filter((m) => !isEmbeddingModel(m)) key: getModelUniqId(m),
.filter((m) => label: (
[m.name + m.provider + t('provider.' + p.id)].join('').toLowerCase().includes(searchText.toLowerCase()) <ModelItem>
) <ModelNameRow>
.map((m) => ({ <span>{m?.name}</span> <ModelTags model={m} />
key: getModelUniqId(m), </ModelNameRow>
label: ( <PinIcon
<ModelItem> onClick={(e) => {
<ModelNameRow> e.stopPropagation()
<span>{m?.name}</span> <ModelTags model={m} /> togglePin(getModelUniqId(m))
</ModelNameRow> }}
<PinIcon isPinned={pinnedModels.includes(getModelUniqId(m))}>
onClick={(e) => { <PushpinOutlined />
e.stopPropagation() </PinIcon>
togglePin(getModelUniqId(m)) </ModelItem>
}} ),
isPinned={pinnedModels.includes(getModelUniqId(m))}> icon: (
<PushpinOutlined /> <Avatar src={getModelLogo(m?.id || '')} size={24}>
</PinIcon> {first(m?.name)}
</ModelItem> </Avatar>
), ),
icon: ( onClick: () => {
<Avatar src={getModelLogo(m?.id || '')} size={24}> resolve(m)
{first(m?.name)} setOpen(false)
</Avatar> }
), }))
onClick: () => {
resolve(m)
setOpen(false)
}
}))
// Only return the group if it has filtered models // Only return the group if it has filtered models
return filteredModels.length > 0 return filteredModels.length > 0
@ -194,27 +212,22 @@ const PopupContainer: React.FC<PopupContainerProps> = ({ model, resolve }) => {
// 添加其他过滤后的模型 // 添加其他过滤后的模型
providers.forEach((p) => { providers.forEach((p) => {
if (p.models) { if (p.models) {
sortBy(p.models, ['group', 'name']) getFilteredModels(p).forEach((m) => {
.filter((m) => !isEmbeddingModel(m)) const modelId = getModelUniqId(m)
.filter((m) => const isPinned = pinnedModels.includes(modelId)
[m.name + m.provider + t('provider.' + p.id)].join('').toLowerCase().includes(searchText.toLowerCase()) // 如果是搜索状态,或者不是固定模型,才添加到列表中
) if (searchText.length > 0 || !isPinned) {
.forEach((m) => { items.push({
const modelId = getModelUniqId(m) key: isPinned ? modelId + '_pinned' : modelId,
const isPinned = pinnedModels.includes(modelId) model: m
// 如果是搜索状态,或者不是固定模型,才添加到列表中 })
if (searchText.length > 0 || !isPinned) { }
items.push({ })
key: isPinned ? modelId + '_pinned' : modelId,
model: m
})
}
})
} }
}) })
return items return items
}, [pinnedModels, searchText, providers, t]) }, [pinnedModels, searchText, providers, getFilteredModels])
// 处理键盘导航 // 处理键盘导航
const handleKeyDown = useCallback( const handleKeyDown = useCallback(