|
3 | 3 | <div class="text-3xl leading-9 mb-6"> |
4 | 4 | {{ $t("resourceConsole.title") }} |
5 | 5 | </div> |
| 6 | + |
| 7 | + <!-- Quick Navigation Tabs --> |
| 8 | + <el-tabs |
| 9 | + v-model="activeTab" |
| 10 | + class="border-b border-gray-200 my-8 tabCont" |
| 11 | + > |
| 12 | + <el-tab-pane |
| 13 | + name="" |
| 14 | + :label="` ${$t('resourceConsole.allProducts')} `" |
| 15 | + ></el-tab-pane> |
| 16 | + <el-tab-pane |
| 17 | + name="finetune" |
| 18 | + :label="` ${$t('finetune.title')} `" |
| 19 | + ></el-tab-pane> |
| 20 | + <el-tab-pane |
| 21 | + name="endpoints" |
| 22 | + :label="` ${$t('endpoints.title')} `" |
| 23 | + ></el-tab-pane> |
| 24 | + <el-tab-pane |
| 25 | + name="evaluations" |
| 26 | + :label="` ${$t('evaluation.list.title')} `" |
| 27 | + ></el-tab-pane> |
| 28 | + </el-tabs> |
| 29 | + |
| 30 | + |
6 | 31 | <!-- finetunes --> |
7 | | - <h3 class="text-lg flex justify-between gap-2"> |
8 | | - <span>{{ $t("finetune.title") }}</span> |
9 | | - <a href="/finetune/new" class="btn btn-primary btn-md"> |
10 | | - <SvgIcon name="plus" /> |
11 | | - {{ $t('resourceConsole.new') }} |
12 | | - </a> |
| 32 | + <h3 v-if="activeTab === '' || activeTab === 'finetune'" class="text-lg flex justify-between gap-2 mt-8"> |
| 33 | + <span class="whitespace-nowrap">{{ $t("finetune.title") }}</span> |
| 34 | + <CsgButton |
| 35 | + class="btn btn-primary btn-sm" |
| 36 | + @click="handleNewClick" |
| 37 | + :name="$t('resourceConsole.new')" |
| 38 | + :svgName="'plus'" |
| 39 | + /> |
13 | 40 | </h3> |
14 | | - <div class="mt-4"> |
15 | | - <div v-if="hasFinetune" class="grid grid-cols-2 xl:grid-cols-1 gap-4 mb-8 mt-4"> |
16 | | - <FinetuneItem v-for="finetune in finetunes.data" :repo="finetune" repo-type="finetune" /> |
| 41 | + <div v-if="activeTab === '' || activeTab === 'finetune'" class="mt-4"> |
| 42 | + <div v-if="filteredFinetunes.length > 0" class="grid grid-cols-2 xl:grid-cols-1 gap-4 mb-8 mt-4"> |
| 43 | + <FinetuneItem v-for="finetune in filteredFinetunes" :repo="finetune" repo-type="finetune" /> |
17 | 44 | </div> |
18 | 45 | <div v-else class="flex flex-wrap gap-4 mb-8 mt-4"> |
19 | 46 | {{ $t("all.noData") }} |
20 | 47 | </div> |
21 | 48 | <view-more v-if="finetunes.more" target="finetunes" @view-more-targets="viewMoreTargets"></view-more> |
22 | 49 | <el-skeleton class="pr-6" v-if="finetunesLoading" :rows="2" animated /> |
23 | 50 | </div> |
| 51 | + |
24 | 52 | <!-- endpoints --> |
25 | | - <h3 class="text-lg flex justify-between gap-2"> |
26 | | - <span>{{ $t("endpoints.title") }}</span> |
27 | | - <a href="/endpoints/new" class="btn btn-primary btn-md"> |
28 | | - <SvgIcon name="plus" /> |
29 | | - {{ $t('resourceConsole.new') }} |
30 | | - </a> |
| 53 | + <h3 v-if="activeTab === '' || activeTab === 'endpoints'" class="text-lg flex justify-between gap-2 mt-8"> |
| 54 | + <span class="whitespace-nowrap">{{ $t("endpoints.title") }}</span> |
| 55 | + <CsgButton |
| 56 | + class="btn btn-primary btn-sm" |
| 57 | + @click="handleNewClick" |
| 58 | + :name="$t('resourceConsole.new')" |
| 59 | + :svgName="'plus'" |
| 60 | + /> |
31 | 61 | </h3> |
32 | | - <div class="mt-4 w-full"> |
33 | | - <div v-if="hasEndpoints" class="grid grid-cols-2 lg:grid-cols-1 gap-4 mb-8 mt-4"> |
34 | | - <EndpointItem v-for="endpoint in endpoints.data" :endpoint="endpoint" :namespace="name" /> |
| 62 | + <div v-if="activeTab === '' || activeTab === 'endpoints'" class="mt-4 w-full"> |
| 63 | + <div v-if="filteredEndpoints.length > 0" class="grid grid-cols-2 lg:grid-cols-1 gap-4 mb-8 mt-4"> |
| 64 | + <EndpointItem v-for="endpoint in filteredEndpoints" :endpoint="endpoint" :namespace="name" /> |
35 | 65 | </div> |
36 | 66 | <div v-else class="flex flex-wrap gap-4 mb-8 mt-4"> |
37 | 67 | {{ $t("all.noData") }} |
|
45 | 75 | </div> |
46 | 76 |
|
47 | 77 | <!-- evaluations --> |
48 | | - <h3 class="text-lg flex justify-between gap-2"> |
49 | | - <span>{{ $t("evaluation.list.title") }}</span> |
50 | | - <a href="/evaluations/new" class="btn btn-primary btn-md"> |
51 | | - <SvgIcon name="plus" /> |
52 | | - {{ $t('evaluation.list.new') }} |
53 | | - </a> |
| 78 | + <h3 v-if="activeTab === '' || activeTab === 'evaluations'" class="text-lg flex justify-between gap-2 mt-8"> |
| 79 | + <span class="whitespace-nowrap">{{ $t("evaluation.list.title") }}</span> |
| 80 | + <CsgButton |
| 81 | + class="btn btn-primary btn-sm" |
| 82 | + @click="handleNewClick" |
| 83 | + :name="$t('evaluation.list.new')" |
| 84 | + :svgName="'plus'" |
| 85 | + /> |
54 | 86 | </h3> |
55 | | - <div class="mt-4 w-full"> |
56 | | - <EvaluationTable :evaluations="evaluations" /> |
| 87 | + <div v-if="activeTab === '' || activeTab === 'evaluations'" class="mt-4 w-full"> |
| 88 | + <EvaluationTable :evaluations="filteredEvaluations" /> |
57 | 89 | </div> |
58 | 90 | </div> |
59 | 91 | </template> |
|
67 | 99 | import EvaluationTable from "./EvaluationTable.vue" |
68 | 100 | import useFetchApi from "../../packs/useFetchApi" |
69 | 101 | import { ElMessage } from "element-plus" |
| 102 | + import CsgButton from "../shared/CsgButton.vue" |
| 103 | + import { useI18n } from 'vue-i18n' |
70 | 104 |
|
71 | 105 | const props = defineProps({ |
72 | 106 | name: String |
73 | 107 | }) |
74 | 108 |
|
| 109 | + const { t: $t } = useI18n() |
| 110 | +
|
| 111 | + const handleNewClick = (event) => { |
| 112 | + // 获取最近的标题元素 |
| 113 | + const titleElement = event.target.closest('h3') |
| 114 | + if (!titleElement) return |
| 115 | +
|
| 116 | + // 根据标题内容判断类型 |
| 117 | + const titleText = titleElement.textContent.trim() |
| 118 | + if (titleText.includes($t("finetune.title"))) { |
| 119 | + window.location.href = '/finetune/new' |
| 120 | + } else if (titleText.includes($t("endpoints.title"))) { |
| 121 | + window.location.href = '/endpoints/new' |
| 122 | + } else if (titleText.includes($t("evaluation.list.title"))) { |
| 123 | + window.location.href = '/evaluations/new' |
| 124 | + } |
| 125 | + } |
| 126 | +
|
75 | 127 | const userStore = useUserStore() |
76 | 128 | const defaultTotal = 6 |
77 | 129 | const endpoints = ref([]) |
78 | 130 | const finetunes = ref([]) |
| 131 | + const evaluations = ref([]) |
| 132 | + const activeTab = ref('') |
79 | 133 |
|
80 | 134 | const endpointsLoading = ref(false) |
81 | 135 | const finetunesLoading = ref(false) |
82 | 136 |
|
83 | 137 | const hasEndpoints = computed(() => endpoints.value?.total > 0) |
84 | 138 | const hasFinetune = computed(() => finetunes.value?.total > 0) |
85 | 139 |
|
| 140 | + const filteredFinetunes = computed(() => finetunes.value?.data || []) |
| 141 | + const filteredEndpoints = computed(() => endpoints.value?.data || []) |
| 142 | + const filteredEvaluations = computed(() => evaluations.value?.data || []) |
| 143 | +
|
86 | 144 | const csghubServer = inject("csghubServer") |
87 | 145 |
|
88 | 146 | const getRepoData = async () =>{ |
|
165 | 223 | } |
166 | 224 | ) |
167 | 225 |
|
| 226 | +
|
168 | 227 | onMounted(() => { |
169 | 228 | if (userStore.initialized) { |
170 | 229 | getRepoData() |
171 | 230 | } |
172 | 231 | }) |
173 | 232 |
|
174 | 233 | </script> |
| 234 | +
|
| 235 | +<style scoped> |
| 236 | +:deep(.tabCont) { |
| 237 | + .el-tabs__header { |
| 238 | + margin: 0; |
| 239 | + } |
| 240 | + .el-tabs__nav-wrap::after { |
| 241 | + height: 1px; |
| 242 | + background-color: #e5e7eb; |
| 243 | + } |
| 244 | + .el-tabs__item { |
| 245 | + font-size: 14px !important; |
| 246 | + color: #667085 !important; |
| 247 | + padding-bottom: 12px; |
| 248 | + height: auto; |
| 249 | + line-height: normal; |
| 250 | + &:hover { |
| 251 | + color: #223B99 !important; |
| 252 | + } |
| 253 | + &.is-active { |
| 254 | + color: #223B99 !important; |
| 255 | + font-weight: 500; |
| 256 | + } |
| 257 | + } |
| 258 | + .el-tabs__active-bar { |
| 259 | + background-color: #223B99 !important; |
| 260 | + height: 2px !important; |
| 261 | + } |
| 262 | +} |
| 263 | +</style> |
0 commit comments