feat(web): add model search bar

This commit is contained in:
Acbox
2026-03-04 23:33:05 +08:00
parent 674e8c6ce9
commit b8551a58c7
3 changed files with 62 additions and 14 deletions
+2
View File
@@ -153,6 +153,8 @@
"addModel": "Add Model",
"editModel": "Edit Model",
"deleteModelConfirm": "Are you sure you want to delete this model?",
"searchModelPlaceholder": "Search models…",
"searchNoResults": "No matching models",
"emptyTitle": "No Models",
"emptyDescription": "Click the button above to add a model for this provider",
"clientType": "Client Type",
+2
View File
@@ -149,6 +149,8 @@
"addModel": "添加模型",
"editModel": "编辑模型",
"deleteModelConfirm": "确定要删除这个模型吗?",
"searchModelPlaceholder": "搜索模型…",
"searchNoResults": "没有匹配的模型",
"emptyTitle": "暂无模型",
"emptyDescription": "点击上方按钮为当前服务商添加模型",
"clientType": "客户端类型",
@@ -13,19 +13,46 @@
</div>
</section>
<section
v-if="models && models.length > 0"
class="flex flex-col gap-4"
>
<ModelItem
v-for="model in models"
:key="model.id || `${model.llm_provider_id}:${model.model_id}`"
:model="model"
:delete-loading="deleteModelLoading"
@edit="(model) => $emit('edit', model)"
@delete="(id) => $emit('delete', id)"
/>
</section>
<template v-if="models && models.length > 0">
<InputGroup
v-if="models.length > 5"
class="shadow-none mb-4"
>
<InputGroupAddon align="inline-start">
<FontAwesomeIcon
:icon="['fas', 'magnifying-glass']"
class="text-muted-foreground"
/>
</InputGroupAddon>
<InputGroupInput
v-model="searchQuery"
:placeholder="$t('models.searchModelPlaceholder')"
/>
</InputGroup>
<section class="flex flex-col gap-4">
<ModelItem
v-for="model in filteredModels"
:key="model.id || `${model.llm_provider_id}:${model.model_id}`"
:model="model"
:delete-loading="deleteModelLoading"
@edit="(model) => $emit('edit', model)"
@delete="(id) => $emit('delete', id)"
/>
</section>
<Empty
v-if="filteredModels.length === 0"
class="flex justify-center items-center py-8"
>
<EmptyHeader>
<EmptyMedia variant="icon">
<FontAwesomeIcon :icon="['fas', 'magnifying-glass']" />
</EmptyMedia>
</EmptyHeader>
<EmptyTitle>{{ $t('models.searchNoResults') }}</EmptyTitle>
</Empty>
</template>
<Empty
v-else
@@ -44,6 +71,7 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import {
Empty,
EmptyContent,
@@ -51,13 +79,16 @@ import {
EmptyHeader,
EmptyMedia,
EmptyTitle,
InputGroup,
InputGroupAddon,
InputGroupInput,
} from '@memoh/ui'
import CreateModel from '@/components/create-model/index.vue'
import ImportModelsDialog from '@/components/import-models-dialog/index.vue'
import ModelItem from './model-item.vue'
import type { ModelsGetResponse } from '@memoh/sdk'
defineProps<{
const props = defineProps<{
providerId: string | undefined
models: ModelsGetResponse[] | undefined
deleteModelLoading: boolean
@@ -67,4 +98,17 @@ defineEmits<{
edit: [model: ModelsGetResponse]
delete: [id: string]
}>()
const searchQuery = ref('')
const filteredModels = computed(() => {
if (!props.models) return []
if (!searchQuery.value) return props.models
const keyword = searchQuery.value.toLowerCase()
return props.models.filter((model) => {
const name = (model.name ?? '').toLowerCase()
const modelId = (model.model_id ?? '').toLowerCase()
return name.includes(keyword) || modelId.includes(keyword)
})
})
</script>