feat: add search function on provider list & optimize ui behaviors when dragging provider item (#2706)
* 添加“腾讯云TI”供应商及其支持的deepseek模型 * add search feature for model providers & adjust ui element behaviors when dragging * dev merge fix * merge fix
This commit is contained in:
parent
0e4f06e86a
commit
640d3783a0
@ -562,7 +562,7 @@ export const PROVIDER_CONFIG = {
|
|||||||
models: 'https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu'
|
models: 'https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'tencent-cloud-ti': {
|
'tentent-cloud-ti': {
|
||||||
api: {
|
api: {
|
||||||
url: 'https://api.lkeap.cloud.tencent.com'
|
url: 'https://api.lkeap.cloud.tencent.com'
|
||||||
},
|
},
|
||||||
|
|||||||
@ -782,7 +782,8 @@
|
|||||||
"remove_duplicate_keys": "Remove Duplicate Keys",
|
"remove_duplicate_keys": "Remove Duplicate Keys",
|
||||||
"remove_invalid_keys": "Remove Invalid Keys",
|
"remove_invalid_keys": "Remove Invalid Keys",
|
||||||
"search_placeholder": "Search model id or name",
|
"search_placeholder": "Search model id or name",
|
||||||
"title": "Model Provider"
|
"title": "Model Provider",
|
||||||
|
"search": "Search Providers..."
|
||||||
},
|
},
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"mode": {
|
"mode": {
|
||||||
|
|||||||
@ -782,7 +782,8 @@
|
|||||||
"remove_duplicate_keys": "重複キーを削除",
|
"remove_duplicate_keys": "重複キーを削除",
|
||||||
"remove_invalid_keys": "無効なキーを削除",
|
"remove_invalid_keys": "無効なキーを削除",
|
||||||
"search_placeholder": "モデルIDまたは名前を検索",
|
"search_placeholder": "モデルIDまたは名前を検索",
|
||||||
"title": "モデルプロバイダー"
|
"title": "モデルプロバイダー",
|
||||||
|
"search": "プロバイダーを検索..."
|
||||||
},
|
},
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"mode": {
|
"mode": {
|
||||||
|
|||||||
@ -782,7 +782,8 @@
|
|||||||
"remove_duplicate_keys": "Удалить дубликаты ключей",
|
"remove_duplicate_keys": "Удалить дубликаты ключей",
|
||||||
"remove_invalid_keys": "Удалить недействительные ключи",
|
"remove_invalid_keys": "Удалить недействительные ключи",
|
||||||
"search_placeholder": "Поиск по ID или имени модели",
|
"search_placeholder": "Поиск по ID или имени модели",
|
||||||
"title": "Провайдеры моделей"
|
"title": "Провайдеры моделей",
|
||||||
|
"search": "Поиск поставщиков..."
|
||||||
},
|
},
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"mode": {
|
"mode": {
|
||||||
|
|||||||
@ -782,7 +782,8 @@
|
|||||||
"remove_duplicate_keys": "移除重复密钥",
|
"remove_duplicate_keys": "移除重复密钥",
|
||||||
"remove_invalid_keys": "删除无效密钥",
|
"remove_invalid_keys": "删除无效密钥",
|
||||||
"search_placeholder": "搜索模型 ID 或名称",
|
"search_placeholder": "搜索模型 ID 或名称",
|
||||||
"title": "模型服务"
|
"title": "模型服务",
|
||||||
|
"search": "搜索模型平台..."
|
||||||
},
|
},
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"mode": {
|
"mode": {
|
||||||
|
|||||||
@ -781,7 +781,8 @@
|
|||||||
"remove_duplicate_keys": "移除重複密鑰",
|
"remove_duplicate_keys": "移除重複密鑰",
|
||||||
"remove_invalid_keys": "刪除無效密鑰",
|
"remove_invalid_keys": "刪除無效密鑰",
|
||||||
"search_placeholder": "搜尋模型 ID 或名稱",
|
"search_placeholder": "搜尋模型 ID 或名稱",
|
||||||
"title": "模型提供者"
|
"title": "模型提供者",
|
||||||
|
"search": "搜尋模型平台..."
|
||||||
},
|
},
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"mode": {
|
"mode": {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { getProviderLogo } from '@renderer/config/providers'
|
|||||||
import { useAllProviders, useProviders } from '@renderer/hooks/useProvider'
|
import { useAllProviders, useProviders } from '@renderer/hooks/useProvider'
|
||||||
import { Provider } from '@renderer/types'
|
import { Provider } from '@renderer/types'
|
||||||
import { droppableReorder, generateColorFromChar, getFirstCharacter, uuid } from '@renderer/utils'
|
import { droppableReorder, generateColorFromChar, getFirstCharacter, uuid } from '@renderer/utils'
|
||||||
import { Avatar, Button, Dropdown, MenuProps, Tag } from 'antd'
|
import { Avatar, Button, Dropdown, Input, MenuProps, Tag } from 'antd'
|
||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
@ -18,6 +18,7 @@ const ProvidersList: FC = () => {
|
|||||||
const { updateProviders, addProvider, removeProvider, updateProvider } = useProviders()
|
const { updateProviders, addProvider, removeProvider, updateProvider } = useProviders()
|
||||||
const [selectedProvider, setSelectedProvider] = useState<Provider>(providers[0])
|
const [selectedProvider, setSelectedProvider] = useState<Provider>(providers[0])
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const [searchText, setSearchText] = useState<string>('')
|
||||||
const [dragging, setDragging] = useState(false)
|
const [dragging, setDragging] = useState(false)
|
||||||
|
|
||||||
const onDragEnd = (result: DropResult) => {
|
const onDragEnd = (result: DropResult) => {
|
||||||
@ -95,17 +96,58 @@ const ProvidersList: FC = () => {
|
|||||||
return menus
|
return menus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//will match the providers and the models that provider provides
|
||||||
|
const filteredProviders = providers.filter((provider) => {
|
||||||
|
// 获取 provider 的名称
|
||||||
|
const providerName = provider.isSystem ? t(`provider.${provider.id}`) : provider.name
|
||||||
|
|
||||||
|
// 检查 provider 的 id 和 name 是否匹配搜索条件
|
||||||
|
const isProviderMatch =
|
||||||
|
provider.id.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||||
|
providerName.toLowerCase().includes(searchText.toLowerCase())
|
||||||
|
|
||||||
|
// 检查 provider.models 中是否有 model 的 id 或 name 匹配搜索条件
|
||||||
|
const isModelMatch = provider.models.some((model) => {
|
||||||
|
return (
|
||||||
|
model.id.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||||
|
model.name.toLowerCase().includes(searchText.toLowerCase())
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 如果 provider 或 model 匹配,则保留该 provider
|
||||||
|
return isProviderMatch || isModelMatch
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<ProviderListContainer>
|
<ProviderListContainer>
|
||||||
|
<AddButtonWrapper>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
placeholder={t('settings.provider.search')}
|
||||||
|
value={searchText}
|
||||||
|
onChange={(e) => setSearchText(e.target.value)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
setSearchText('')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
allowClear
|
||||||
|
disabled={dragging}
|
||||||
|
/>
|
||||||
|
</AddButtonWrapper>
|
||||||
<Scrollbar>
|
<Scrollbar>
|
||||||
<ProviderList>
|
<ProviderList>
|
||||||
<DragDropContext onDragStart={() => setDragging(true)} onDragEnd={onDragEnd}>
|
<DragDropContext onDragStart={() => setDragging(true)} onDragEnd={onDragEnd}>
|
||||||
<Droppable droppableId="droppable">
|
<Droppable droppableId="droppable">
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
{providers.map((provider, index) => (
|
{filteredProviders.map((provider, index) => (
|
||||||
<Draggable key={`draggable_${provider.id}_${index}`} draggableId={provider.id} index={index}>
|
<Draggable
|
||||||
|
key={`draggable_${provider.id}_${index}`}
|
||||||
|
draggableId={provider.id}
|
||||||
|
index={index}
|
||||||
|
isDragDisabled={searchText.length > 0}>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div
|
<div
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
@ -148,13 +190,11 @@ const ProvidersList: FC = () => {
|
|||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
</ProviderList>
|
</ProviderList>
|
||||||
</Scrollbar>
|
</Scrollbar>
|
||||||
{!dragging && (
|
<AddButtonWrapper>
|
||||||
<AddButtonWrapper>
|
<Button style={{ width: '100%' }} icon={<PlusOutlined />} onClick={onAddProvider} disabled={dragging}>
|
||||||
<Button style={{ width: '100%' }} icon={<PlusOutlined />} onClick={onAddProvider}>
|
{t('button.add')}
|
||||||
{t('button.add')}
|
</Button>
|
||||||
</Button>
|
</AddButtonWrapper>
|
||||||
</AddButtonWrapper>
|
|
||||||
)}
|
|
||||||
</ProviderListContainer>
|
</ProviderListContainer>
|
||||||
<ProviderSetting provider={selectedProvider} key={JSON.stringify(selectedProvider)} />
|
<ProviderSetting provider={selectedProvider} key={JSON.stringify(selectedProvider)} />
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user