Spaces:
Running
Running
github-actions[bot] commited on
Commit ·
de009e3
1
Parent(s): 580dda3
Sync from GitHub Viciy2023/Qwen2API-A@31edd3f55db98e10964caba9b9f87c749bf04d57
Browse files- public/src/views/dashboard.vue +73 -14
public/src/views/dashboard.vue
CHANGED
|
@@ -333,12 +333,39 @@
|
|
| 333 |
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4">
|
| 334 |
<div class="flex flex-wrap items-center gap-2 text-sm text-slate-600">
|
| 335 |
<span>共 {{ availableModels.length }} 个模型</span>
|
| 336 |
-
<
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
</div>
|
| 343 |
<div class="flex w-full sm:w-auto gap-2">
|
| 344 |
<div class="relative w-full sm:w-72">
|
|
@@ -373,7 +400,7 @@
|
|
| 373 |
</button>
|
| 374 |
</div>
|
| 375 |
|
| 376 |
-
<div v-else class="max-h-[60vh] overflow-y-auto pr-2">
|
| 377 |
<div class="space-y-5">
|
| 378 |
<div v-for="group in groupedModelSections"
|
| 379 |
:key="group.key"
|
|
@@ -429,7 +456,7 @@
|
|
| 429 |
</div>
|
| 430 |
</div>
|
| 431 |
|
| 432 |
-
<div v-if="!
|
| 433 |
没有匹配的模型
|
| 434 |
</div>
|
| 435 |
</div>
|
|
@@ -473,6 +500,8 @@ const availableModels = ref([])
|
|
| 473 |
const isLoadingModels = ref(false)
|
| 474 |
const modelsError = ref('')
|
| 475 |
const modelKeyword = ref('')
|
|
|
|
|
|
|
| 476 |
|
| 477 |
// Toast 通知
|
| 478 |
const toast = ref({
|
|
@@ -526,50 +555,59 @@ const createModelGroupMap = (models) => {
|
|
| 526 |
return groups
|
| 527 |
}
|
| 528 |
|
|
|
|
| 529 |
const modelGroups = computed(() => createModelGroupMap(filteredModels.value))
|
| 530 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 531 |
const groupedModelSections = computed(() => [
|
| 532 |
{
|
| 533 |
key: 'base',
|
| 534 |
title: '基础模型',
|
| 535 |
description: '适合普通对话、通用推理和默认场景',
|
| 536 |
badgeClass: 'bg-slate-100 text-slate-700',
|
| 537 |
-
models: modelGroups.value.base
|
| 538 |
},
|
| 539 |
{
|
| 540 |
key: 'thinking',
|
| 541 |
title: 'Thinking 模型',
|
| 542 |
description: '带推理输出能力,适合复杂思考场景',
|
| 543 |
badgeClass: 'bg-amber-100 text-amber-700',
|
| 544 |
-
models: modelGroups.value.thinking
|
| 545 |
},
|
| 546 |
{
|
| 547 |
key: 'search',
|
| 548 |
title: 'Search 模型',
|
| 549 |
description: '带搜索能力,适合联网或检索场景',
|
| 550 |
badgeClass: 'bg-cyan-100 text-cyan-700',
|
| 551 |
-
models: modelGroups.value.search
|
| 552 |
},
|
| 553 |
{
|
| 554 |
key: 'image',
|
| 555 |
title: 'Image 模型',
|
| 556 |
description: '适合图片理解或生图相关能力',
|
| 557 |
badgeClass: 'bg-rose-100 text-rose-700',
|
| 558 |
-
models: modelGroups.value.image
|
| 559 |
},
|
| 560 |
{
|
| 561 |
key: 'video',
|
| 562 |
title: 'Video 模型',
|
| 563 |
description: '适合视频相关能力或多模态视频处理',
|
| 564 |
badgeClass: 'bg-indigo-100 text-indigo-700',
|
| 565 |
-
models: modelGroups.value.video
|
| 566 |
},
|
| 567 |
{
|
| 568 |
key: 'imageEdit',
|
| 569 |
title: 'Image Edit 模型',
|
| 570 |
description: '适合图像编辑与改图类能力',
|
| 571 |
badgeClass: 'bg-emerald-100 text-emerald-700',
|
| 572 |
-
models: modelGroups.value.imageEdit
|
| 573 |
}
|
| 574 |
])
|
| 575 |
|
|
@@ -590,6 +628,26 @@ const getModelDisplayName = (model) => {
|
|
| 590 |
return model.id
|
| 591 |
}
|
| 592 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 593 |
const getModelUseCase = (model) => {
|
| 594 |
const id = model.id.toLowerCase()
|
| 595 |
|
|
@@ -1036,6 +1094,7 @@ const refreshModels = async () => {
|
|
| 1036 |
const openModelsPanel = async () => {
|
| 1037 |
showModelsPanel.value = true
|
| 1038 |
modelKeyword.value = ''
|
|
|
|
| 1039 |
|
| 1040 |
if (!availableModels.value.length) {
|
| 1041 |
await getAvailableModels()
|
|
|
|
| 333 |
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4">
|
| 334 |
<div class="flex flex-wrap items-center gap-2 text-sm text-slate-600">
|
| 335 |
<span>共 {{ availableModels.length }} 个模型</span>
|
| 336 |
+
<button @click="setActiveModelFilter('all')"
|
| 337 |
+
:class="[
|
| 338 |
+
'rounded-full px-3 py-1 text-xs font-semibold transition-all duration-300',
|
| 339 |
+
activeModelFilter === 'all'
|
| 340 |
+
? 'bg-slate-800 text-white'
|
| 341 |
+
: 'bg-slate-100 text-slate-600 hover:bg-slate-200'
|
| 342 |
+
]">
|
| 343 |
+
全部 {{ availableModels.length }}
|
| 344 |
+
</button>
|
| 345 |
+
<button @click="setActiveModelFilter('base')"
|
| 346 |
+
:class="getFilterBadgeClass('base', 'bg-slate-100', 'text-slate-600', 'hover:bg-slate-200', 'bg-slate-700')">
|
| 347 |
+
基础 {{ allModelGroups.base.length }}
|
| 348 |
+
</button>
|
| 349 |
+
<button @click="setActiveModelFilter('thinking')"
|
| 350 |
+
:class="getFilterBadgeClass('thinking', 'bg-amber-100', 'text-amber-700', 'hover:bg-amber-200', 'bg-amber-500')">
|
| 351 |
+
Thinking {{ allModelGroups.thinking.length }}
|
| 352 |
+
</button>
|
| 353 |
+
<button @click="setActiveModelFilter('search')"
|
| 354 |
+
:class="getFilterBadgeClass('search', 'bg-cyan-100', 'text-cyan-700', 'hover:bg-cyan-200', 'bg-cyan-500')">
|
| 355 |
+
Search {{ allModelGroups.search.length }}
|
| 356 |
+
</button>
|
| 357 |
+
<button @click="setActiveModelFilter('image')"
|
| 358 |
+
:class="getFilterBadgeClass('image', 'bg-rose-100', 'text-rose-700', 'hover:bg-rose-200', 'bg-rose-500')">
|
| 359 |
+
Image {{ allModelGroups.image.length }}
|
| 360 |
+
</button>
|
| 361 |
+
<button @click="setActiveModelFilter('video')"
|
| 362 |
+
:class="getFilterBadgeClass('video', 'bg-indigo-100', 'text-indigo-700', 'hover:bg-indigo-200', 'bg-indigo-500')">
|
| 363 |
+
Video {{ allModelGroups.video.length }}
|
| 364 |
+
</button>
|
| 365 |
+
<button @click="setActiveModelFilter('imageEdit')"
|
| 366 |
+
:class="getFilterBadgeClass('imageEdit', 'bg-emerald-100', 'text-emerald-700', 'hover:bg-emerald-200', 'bg-emerald-500')">
|
| 367 |
+
Image Edit {{ allModelGroups.imageEdit.length }}
|
| 368 |
+
</button>
|
| 369 |
</div>
|
| 370 |
<div class="flex w-full sm:w-auto gap-2">
|
| 371 |
<div class="relative w-full sm:w-72">
|
|
|
|
| 400 |
</button>
|
| 401 |
</div>
|
| 402 |
|
| 403 |
+
<div v-else ref="modelsScrollContainer" class="max-h-[60vh] overflow-y-auto pr-2">
|
| 404 |
<div class="space-y-5">
|
| 405 |
<div v-for="group in groupedModelSections"
|
| 406 |
:key="group.key"
|
|
|
|
| 456 |
</div>
|
| 457 |
</div>
|
| 458 |
|
| 459 |
+
<div v-if="!filteredModelsByCategory.length" class="py-12 text-center text-slate-500">
|
| 460 |
没有匹配的模型
|
| 461 |
</div>
|
| 462 |
</div>
|
|
|
|
| 500 |
const isLoadingModels = ref(false)
|
| 501 |
const modelsError = ref('')
|
| 502 |
const modelKeyword = ref('')
|
| 503 |
+
const activeModelFilter = ref('all')
|
| 504 |
+
const modelsScrollContainer = ref(null)
|
| 505 |
|
| 506 |
// Toast 通知
|
| 507 |
const toast = ref({
|
|
|
|
| 555 |
return groups
|
| 556 |
}
|
| 557 |
|
| 558 |
+
const allModelGroups = computed(() => createModelGroupMap(availableModels.value))
|
| 559 |
const modelGroups = computed(() => createModelGroupMap(filteredModels.value))
|
| 560 |
|
| 561 |
+
const filteredModelsByCategory = computed(() => {
|
| 562 |
+
if (activeModelFilter.value === 'all') {
|
| 563 |
+
return filteredModels.value
|
| 564 |
+
}
|
| 565 |
+
|
| 566 |
+
return modelGroups.value[activeModelFilter.value] || []
|
| 567 |
+
})
|
| 568 |
+
|
| 569 |
const groupedModelSections = computed(() => [
|
| 570 |
{
|
| 571 |
key: 'base',
|
| 572 |
title: '基础模型',
|
| 573 |
description: '适合普通对话、通用推理和默认场景',
|
| 574 |
badgeClass: 'bg-slate-100 text-slate-700',
|
| 575 |
+
models: activeModelFilter.value === 'all' || activeModelFilter.value === 'base' ? modelGroups.value.base : []
|
| 576 |
},
|
| 577 |
{
|
| 578 |
key: 'thinking',
|
| 579 |
title: 'Thinking 模型',
|
| 580 |
description: '带推理输出能力,适合复杂思考场景',
|
| 581 |
badgeClass: 'bg-amber-100 text-amber-700',
|
| 582 |
+
models: activeModelFilter.value === 'all' || activeModelFilter.value === 'thinking' ? modelGroups.value.thinking : []
|
| 583 |
},
|
| 584 |
{
|
| 585 |
key: 'search',
|
| 586 |
title: 'Search 模型',
|
| 587 |
description: '带搜索能力,适合联网或检索场景',
|
| 588 |
badgeClass: 'bg-cyan-100 text-cyan-700',
|
| 589 |
+
models: activeModelFilter.value === 'all' || activeModelFilter.value === 'search' ? modelGroups.value.search : []
|
| 590 |
},
|
| 591 |
{
|
| 592 |
key: 'image',
|
| 593 |
title: 'Image 模型',
|
| 594 |
description: '适合图片理解或生图相关能力',
|
| 595 |
badgeClass: 'bg-rose-100 text-rose-700',
|
| 596 |
+
models: activeModelFilter.value === 'all' || activeModelFilter.value === 'image' ? modelGroups.value.image : []
|
| 597 |
},
|
| 598 |
{
|
| 599 |
key: 'video',
|
| 600 |
title: 'Video 模型',
|
| 601 |
description: '适合视频相关能力或多模态视频处理',
|
| 602 |
badgeClass: 'bg-indigo-100 text-indigo-700',
|
| 603 |
+
models: activeModelFilter.value === 'all' || activeModelFilter.value === 'video' ? modelGroups.value.video : []
|
| 604 |
},
|
| 605 |
{
|
| 606 |
key: 'imageEdit',
|
| 607 |
title: 'Image Edit 模型',
|
| 608 |
description: '适合图像编辑与改图类能力',
|
| 609 |
badgeClass: 'bg-emerald-100 text-emerald-700',
|
| 610 |
+
models: activeModelFilter.value === 'all' || activeModelFilter.value === 'imageEdit' ? modelGroups.value.imageEdit : []
|
| 611 |
}
|
| 612 |
])
|
| 613 |
|
|
|
|
| 628 |
return model.id
|
| 629 |
}
|
| 630 |
|
| 631 |
+
const setActiveModelFilter = (filterKey) => {
|
| 632 |
+
activeModelFilter.value = filterKey
|
| 633 |
+
|
| 634 |
+
if (modelsScrollContainer.value) {
|
| 635 |
+
modelsScrollContainer.value.scrollTo({
|
| 636 |
+
top: 0,
|
| 637 |
+
behavior: 'smooth'
|
| 638 |
+
})
|
| 639 |
+
}
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
const getFilterBadgeClass = (filterKey, bgClass, textClass, hoverClass, activeBgClass) => {
|
| 643 |
+
return [
|
| 644 |
+
'rounded-full px-3 py-1 text-xs font-semibold transition-all duration-300',
|
| 645 |
+
activeModelFilter.value === filterKey
|
| 646 |
+
? `${activeBgClass} text-white`
|
| 647 |
+
: `${bgClass} ${textClass} ${hoverClass}`
|
| 648 |
+
]
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
const getModelUseCase = (model) => {
|
| 652 |
const id = model.id.toLowerCase()
|
| 653 |
|
|
|
|
| 1094 |
const openModelsPanel = async () => {
|
| 1095 |
showModelsPanel.value = true
|
| 1096 |
modelKeyword.value = ''
|
| 1097 |
+
activeModelFilter.value = 'all'
|
| 1098 |
|
| 1099 |
if (!availableModels.value.length) {
|
| 1100 |
await getAvailableModels()
|