@@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
1717For commercial licensing, please contact support@quantumnous.com
1818*/
1919
20- import React , { useState , useEffect } from 'react' ;
20+ import React , { useState , useEffect , useMemo } from 'react' ;
2121import { useIsMobile } from '../../../../hooks/common/useIsMobile' ;
2222import {
2323 Modal ,
@@ -28,19 +28,21 @@ import {
2828 Empty ,
2929 Tabs ,
3030 Collapse ,
31+ Tooltip ,
3132} from '@douyinfe/semi-ui' ;
3233import {
3334 IllustrationNoResult ,
3435 IllustrationNoResultDark ,
3536} from '@douyinfe/semi-illustrations' ;
36- import { IconSearch } from '@douyinfe/semi-icons' ;
37+ import { IconSearch , IconInfoCircle } from '@douyinfe/semi-icons' ;
3738import { useTranslation } from 'react-i18next' ;
3839import { getModelCategories } from '../../../../helpers/render' ;
3940
4041const ModelSelectModal = ( {
4142 visible,
4243 models = [ ] ,
4344 selected = [ ] ,
45+ redirectModels = [ ] ,
4446 onConfirm,
4547 onCancel,
4648} ) => {
@@ -50,15 +52,54 @@ const ModelSelectModal = ({
5052 const [ activeTab , setActiveTab ] = useState ( 'new' ) ;
5153
5254 const isMobile = useIsMobile ( ) ;
55+ const normalizeModelName = ( model ) =>
56+ typeof model === 'string' ? model . trim ( ) : '' ;
57+ const normalizedRedirectModels = useMemo (
58+ ( ) =>
59+ Array . from (
60+ new Set (
61+ ( redirectModels || [ ] )
62+ . map ( ( model ) => normalizeModelName ( model ) )
63+ . filter ( Boolean ) ,
64+ ) ,
65+ ) ,
66+ [ redirectModels ] ,
67+ ) ;
68+ const normalizedSelectedSet = useMemo ( ( ) => {
69+ const set = new Set ( ) ;
70+ ( selected || [ ] ) . forEach ( ( model ) => {
71+ const normalized = normalizeModelName ( model ) ;
72+ if ( normalized ) {
73+ set . add ( normalized ) ;
74+ }
75+ } ) ;
76+ return set ;
77+ } , [ selected ] ) ;
78+ const classificationSet = useMemo ( ( ) => {
79+ const set = new Set ( normalizedSelectedSet ) ;
80+ normalizedRedirectModels . forEach ( ( model ) => set . add ( model ) ) ;
81+ return set ;
82+ } , [ normalizedSelectedSet , normalizedRedirectModels ] ) ;
83+ const redirectOnlySet = useMemo ( ( ) => {
84+ const set = new Set ( ) ;
85+ normalizedRedirectModels . forEach ( ( model ) => {
86+ if ( ! normalizedSelectedSet . has ( model ) ) {
87+ set . add ( model ) ;
88+ }
89+ } ) ;
90+ return set ;
91+ } , [ normalizedRedirectModels , normalizedSelectedSet ] ) ;
5392
5493 const filteredModels = models . filter ( ( m ) =>
55- m . toLowerCase ( ) . includes ( keyword . toLowerCase ( ) ) ,
94+ String ( m || '' ) . toLowerCase ( ) . includes ( keyword . toLowerCase ( ) ) ,
5695 ) ;
5796
5897 // 分类模型:新获取的模型和已有模型
59- const newModels = filteredModels . filter ( ( model ) => ! selected . includes ( model ) ) ;
98+ const isExistingModel = ( model ) =>
99+ classificationSet . has ( normalizeModelName ( model ) ) ;
100+ const newModels = filteredModels . filter ( ( model ) => ! isExistingModel ( model ) ) ;
60101 const existingModels = filteredModels . filter ( ( model ) =>
61- selected . includes ( model ) ,
102+ isExistingModel ( model ) ,
62103 ) ;
63104
64105 // 同步外部选中值
@@ -228,7 +269,20 @@ const ModelSelectModal = ({
228269 < div className = 'grid grid-cols-2 gap-x-4' >
229270 { categoryData . models . map ( ( model ) => (
230271 < Checkbox key = { model } value = { model } className = 'my-1' >
231- { model }
272+ < span className = 'flex items-center gap-2' >
273+ < span > { model } </ span >
274+ { redirectOnlySet . has ( normalizeModelName ( model ) ) && (
275+ < Tooltip
276+ position = 'top'
277+ content = { t ( '来自模型重定向,尚未加入模型列表' ) }
278+ >
279+ < IconInfoCircle
280+ size = 'small'
281+ className = 'text-amber-500 cursor-help'
282+ />
283+ </ Tooltip >
284+ ) }
285+ </ span >
232286 </ Checkbox >
233287 ) ) }
234288 </ div >
0 commit comments