Skip to content

Commit f30b4cd

Browse files
authored
feat(ModelModal): 添加模型搜索功能并优化筛选UI (#92)
在模型选择器中添加搜索框功能,允许用户通过模型名称快速筛选 将标签筛选器和搜索框整合到固定标题区域,优化交互体验 修复图像分析模型的图片支持选项显示逻辑
1 parent e4fef73 commit f30b4cd

File tree

1 file changed

+75
-38
lines changed

1 file changed

+75
-38
lines changed

ui/ModelModal/src/ModelModal.tsx

Lines changed: 75 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
InputAdornment,
1616
IconButton,
1717
} from '@mui/material';
18-
import { Visibility, VisibilityOff } from '@mui/icons-material';
18+
import { Visibility, VisibilityOff, Search } from '@mui/icons-material';
1919
import { Icon, message, Modal, ThemeProvider } from '@ctzhian/ui';
2020
import Card from './components/card';
2121
import ModelTagsWithLabel from './components/ModelTagsWithLabel';
@@ -96,6 +96,7 @@ export const ModelModal: React.FC<ModelModalProps> = ({
9696
const [filteredModelList, setFilteredModelList] = useState<
9797
{ model: string; provider: string }[]
9898
>([]);
99+
const [modelSearchQuery, setModelSearchQuery] = useState('');
99100

100101
const [loading, setLoading] = useState(false);
101102
const [modelLoading, setModelLoading] = useState(false);
@@ -608,7 +609,7 @@ export const ModelModal: React.FC<ModelModalProps> = ({
608609
}}
609610
onClick={() =>
610611
window.open(
611-
addingModelTutorialURL ,
612+
addingModelTutorialURL,
612613
'_blank'
613614
)
614615
}
@@ -944,6 +945,10 @@ export const ModelModal: React.FC<ModelModalProps> = ({
944945
helperText={errors.model_name?.message}
945946
SelectProps={{
946947
MenuProps: {
948+
autoFocus: false,
949+
MenuListProps: {
950+
autoFocusItem: false,
951+
},
947952
PaperProps: {
948953
sx: {
949954
maxHeight: 450,
@@ -957,13 +962,20 @@ export const ModelModal: React.FC<ModelModalProps> = ({
957962
>
958963
{(() => {
959964
// 使用筛选后的模型列表,如果没有筛选则使用原始列表
960-
const modelsToShow =
965+
const modelsBase =
961966
filteredModelList.length > 0
962967
? filteredModelList
963968
: modelUserList.map((item) => ({
964-
model: item.model,
965-
provider: providerBrand,
966-
}));
969+
model: item.model,
970+
provider: providerBrand,
971+
}));
972+
973+
const query = modelSearchQuery.trim().toLowerCase();
974+
const modelsToShow = query
975+
? modelsBase.filter((m) =>
976+
m.model.toLowerCase().includes(query)
977+
)
978+
: modelsBase;
967979

968980
// 按组分类模型
969981
const groupedModels = modelsToShow.reduce(
@@ -1037,46 +1049,71 @@ export const ModelModal: React.FC<ModelModalProps> = ({
10371049
.flat();
10381050

10391051
return [
1040-
<MenuItem
1041-
key='sticky-chip'
1042-
disableRipple
1043-
disableTouchRipple
1052+
<ListSubheader
1053+
key='sticky-tools'
10441054
sx={{
10451055
position: 'sticky',
10461056
top: 0,
1047-
zIndex: 1000,
1057+
zIndex: 1001,
10481058
backgroundColor: '#ffffff !important',
10491059
borderBottom: '1px solid',
10501060
borderColor: 'divider',
1051-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
1052-
'&:hover': {
1053-
backgroundColor: '#ffffff !important',
1054-
},
1055-
'&:focus': {
1056-
backgroundColor: '#ffffff !important',
1057-
},
1061+
boxShadow: '0 2px 4px rgba(0,0,0,0.06)',
10581062
cursor: 'default',
1059-
'&.Mui-selected': {
1060-
backgroundColor: '#ffffff !important',
1061-
},
1062-
'&.Mui-selected:hover': {
1063-
backgroundColor: '#ffffff !important',
1064-
},
1063+
px: 1,
1064+
py: 1,
1065+
}}
1066+
onMouseDown={(e) => {
1067+
e.stopPropagation();
10651068
}}
10661069
onClick={(e) => {
1067-
e.preventDefault();
1070+
e.stopPropagation();
10681071
}}
10691072
>
1070-
<ModelTagFilter
1071-
models={modelUserList.map((item) => ({
1072-
model: item.model,
1073-
provider: providerBrand,
1074-
}))}
1075-
onFilteredModelsChange={(filteredModels) => {
1076-
setFilteredModelList(filteredModels);
1077-
}}
1078-
/>
1079-
</MenuItem>,
1073+
<Stack direction='column' spacing={1}>
1074+
<TextField
1075+
value={modelSearchQuery}
1076+
onChange={(e) => setModelSearchQuery(e.target.value)}
1077+
fullWidth
1078+
size='small'
1079+
placeholder='搜索模型名称'
1080+
onKeyDown={(e) => {
1081+
e.stopPropagation();
1082+
}}
1083+
onMouseDown={(e) => {
1084+
e.stopPropagation();
1085+
}}
1086+
onClick={(e) => {
1087+
e.stopPropagation();
1088+
}}
1089+
InputProps={{
1090+
startAdornment: (
1091+
<InputAdornment position='start'>
1092+
<Search fontSize='small' />
1093+
</InputAdornment>
1094+
),
1095+
}}
1096+
/>
1097+
<Box
1098+
onMouseDown={(e) => {
1099+
e.stopPropagation();
1100+
}}
1101+
onClick={(e) => {
1102+
e.stopPropagation();
1103+
}}
1104+
>
1105+
<ModelTagFilter
1106+
models={modelUserList.map((item) => ({
1107+
model: item.model,
1108+
provider: providerBrand,
1109+
}))}
1110+
onFilteredModelsChange={(filteredModels) => {
1111+
setFilteredModelList(filteredModels);
1112+
}}
1113+
/>
1114+
</Box>
1115+
</Stack>
1116+
</ListSubheader>,
10801117
...modelItems,
10811118
];
10821119
})()}
@@ -1168,13 +1205,13 @@ export const ModelModal: React.FC<ModelModalProps> = ({
11681205
<Stack spacing={0}>
11691206
{/* 复选框组 - 使用更紧凑的布局 */}
11701207
<Stack spacing={0} sx={{ ml: -1.2 }}>
1171-
<Controller
1208+
<Controller
11721209
control={control}
11731210
name='support_image'
11741211
render={({ field }) => {
11751212
const isAnalysisVl = model_type === 'analysis-vl';
11761213
const isChecked = isAnalysisVl ? true : field.value;
1177-
1214+
11781215
return (
11791216
<FormControlLabel
11801217
control={
@@ -1200,7 +1237,7 @@ export const ModelModal: React.FC<ModelModalProps> = ({
12001237
fontSize: 11,
12011238
}}
12021239
>
1203-
{isAnalysisVl
1240+
{isAnalysisVl
12041241
? '(图像分析模型默认启用图片功能)'
12051242
: '(支持图片输入的模型可以启用此选项)'
12061243
}

0 commit comments

Comments
 (0)