github-actions[bot] commited on
Commit
de009e3
·
1 Parent(s): 580dda3

Sync from GitHub Viciy2023/Qwen2API-A@31edd3f55db98e10964caba9b9f87c749bf04d57

Browse files
Files changed (1) hide show
  1. 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
- <span class="rounded-full bg-slate-100 px-3 py-1 text-xs text-slate-600">基础 {{ modelGroups.base.length }}</span>
337
- <span class="rounded-full bg-amber-100 px-3 py-1 text-xs text-amber-700">Thinking {{ modelGroups.thinking.length }}</span>
338
- <span class="rounded-full bg-cyan-100 px-3 py-1 text-xs text-cyan-700">Search {{ modelGroups.search.length }}</span>
339
- <span class="rounded-full bg-rose-100 px-3 py-1 text-xs text-rose-700">Image {{ modelGroups.image.length }}</span>
340
- <span class="rounded-full bg-indigo-100 px-3 py-1 text-xs text-indigo-700">Video {{ modelGroups.video.length }}</span>
341
- <span class="rounded-full bg-emerald-100 px-3 py-1 text-xs text-emerald-700">Image Edit {{ modelGroups.imageEdit.length }}</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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="!filteredModels.length" class="py-12 text-center text-slate-500">
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()