style: 修改模型选择列表

This commit is contained in:
ccnetcore
2026-01-11 21:00:02 +08:00
parent 7ed7201d10
commit d9f5f1f050

View File

@@ -17,6 +17,7 @@ const scrollbarRef = ref();
const activeProviderGroup = ref(''); const activeProviderGroup = ref('');
const activeApiGroup = ref(''); const activeApiGroup = ref('');
const isScrolling = ref(false); const isScrolling = ref(false);
const filterPremiumOnly = ref(false); // 是否只显示尊享模型
// 检查模型是否可用 // 检查模型是否可用
function isModelAvailable(item: GetSessionListVO) { function isModelAvailable(item: GetSessionListVO) {
@@ -95,18 +96,18 @@ const currentModelName = computed(
() => modelStore.currentModelInfo && modelStore.currentModelInfo.modelName, () => modelStore.currentModelInfo && modelStore.currentModelInfo.modelName,
); );
// API 类型映射 // 过滤后的模型列表
const apiTypeNameMap: Record<string, string> = { const filteredModelList = computed(() => {
Completions: 'OpenAI Chat Completion', if (filterPremiumOnly.value) {
Responses: 'OpenAI Responses API', return modelStore.modelList.filter(model => model.isPremiumPackage);
Messages: 'Anthropic Claude API', }
GenerateContent: 'Google Gemini API', return modelStore.modelList;
}; });
// 按 API 类型分组 // 按 API 类型分组
const groupedByApiType = computed(() => { const groupedByApiType = computed(() => {
const groups: Record<string, GetSessionListVO[]> = {}; const groups: Record<string, GetSessionListVO[]> = {};
modelStore.modelList.forEach((model) => { filteredModelList.value.forEach((model) => {
const apiType = model.modelApiType || 'Completions'; const apiType = model.modelApiType || 'Completions';
if (!groups[apiType]) { if (!groups[apiType]) {
groups[apiType] = []; groups[apiType] = [];
@@ -119,7 +120,7 @@ const groupedByApiType = computed(() => {
// 按 厂商 (Provider) 分组 // 按 厂商 (Provider) 分组
const groupedByProvider = computed(() => { const groupedByProvider = computed(() => {
const groups: Record<string, GetSessionListVO[]> = {}; const groups: Record<string, GetSessionListVO[]> = {};
modelStore.modelList.forEach((model) => { filteredModelList.value.forEach((model) => {
const provider = model.providerName || 'Other'; const provider = model.providerName || 'Other';
if (!groups[provider]) { if (!groups[provider]) {
groups[provider] = []; groups[provider] = [];
@@ -311,8 +312,17 @@ function getWrapperClass(item: GetSessionListVO) {
align-center align-center
> >
<div class="model-list-container relative"> <div class="model-list-container relative">
<!-- 右上角前往模型库按钮 --> <!-- 右上角操作区域 -->
<div class="absolute right-0 top-1 z-10"> <div class="absolute right-0 top-1 z-10 flex items-center gap-3">
<!-- 尊享过滤标签 -->
<div
class="premium-filter-tag"
:class="{ 'premium-filter-tag--active': filterPremiumOnly }"
@click="filterPremiumOnly = !filterPremiumOnly"
>
<span class="premium-filter-tag__text">仅看尊享模型</span>
</div>
<el-button type="primary" link size="small" @click="goToModelLibrary"> <el-button type="primary" link size="small" @click="goToModelLibrary">
前往模型库 前往模型库
<el-icon class="ml-1"> <el-icon class="ml-1">
@@ -330,7 +340,7 @@ function getWrapperClass(item: GetSessionListVO) {
<div <div
v-for="(_, provider) in groupedByProvider" v-for="(_, provider) in groupedByProvider"
:key="provider" :key="provider"
class="cursor-pointer px-3 py-2.5 text-xs hover:bg-gray-50 truncate transition-colors duration-200 border-l-2 border-transparent" class="cursor-pointer px-2 py-2.5 text-xs hover:bg-gray-50 truncate transition-colors duration-200 border-l-2 border-transparent"
:class="{ 'text-primary font-bold bg-blue-50 border-primary': activeProviderGroup === provider, 'text-gray-600': activeProviderGroup !== provider }" :class="{ 'text-primary font-bold bg-blue-50 border-primary': activeProviderGroup === provider, 'text-gray-600': activeProviderGroup !== provider }"
@click="scrollToGroup('provider', provider as string)" @click="scrollToGroup('provider', provider as string)"
> >
@@ -402,11 +412,11 @@ function getWrapperClass(item: GetSessionListVO) {
<div <div
v-for="(_, apiType) in groupedByApiType" v-for="(_, apiType) in groupedByApiType"
:key="apiType" :key="apiType"
class="cursor-pointer px-3 py-2.5 text-xs hover:bg-gray-50 transition-colors duration-200 border-l-2 border-transparent leading-tight" class="cursor-pointer px-1 py-2.5 text-xs hover:bg-gray-50 transition-colors duration-200 border-l-2 border-transparent leading-tight"
:class="{ 'text-primary font-bold bg-blue-50 border-primary': activeApiGroup === apiType, 'text-gray-600': activeApiGroup !== apiType }" :class="{ 'text-primary font-bold bg-blue-50 border-primary': activeApiGroup === apiType, 'text-gray-600': activeApiGroup !== apiType }"
@click="scrollToGroup('api', apiType as string)" @click="scrollToGroup('api', apiType as string)"
> >
<div v-html="(apiTypeNameMap[apiType] || apiType).replace(/ /g, '<br/>')" /> <div v-html="(apiType).replace(/ /g, '<br/>')" />
</div> </div>
</div> </div>
<!-- 内容列表 --> <!-- 内容列表 -->
@@ -415,7 +425,7 @@ function getWrapperClass(item: GetSessionListVO) {
<div class="px-2 pb-4"> <div class="px-2 pb-4">
<template v-for="(models, apiType) in groupedByApiType" :key="apiType"> <template v-for="(models, apiType) in groupedByApiType" :key="apiType">
<div :id="`group-api-${apiType}`" class="group-title text-gray-500 text-xs font-bold mb-2 mt-4 px-1 pt-2"> <div :id="`group-api-${apiType}`" class="group-title text-gray-500 text-xs font-bold mb-2 mt-4 px-1 pt-2">
{{ apiTypeNameMap[apiType] || apiType }} {{ apiType }}
</div> </div>
<div <div
v-for="item in models" v-for="item in models"
@@ -516,4 +526,45 @@ function getWrapperClass(item: GetSessionListVO) {
.border-primary { .border-primary {
border-color: var(--el-color-primary, #409eff); border-color: var(--el-color-primary, #409eff);
} }
/* 尊享过滤标签 */
.premium-filter-tag {
padding: 4px 12px;
border-radius: 20px;
cursor: pointer;
font-size: 12px;
font-weight: 500;
border: 1.5px solid transparent;
background: linear-gradient(white, white) padding-box,
linear-gradient(90deg, #ff6b6b, #feca57, #48dbfb, #ff9ff3, #54a0ff, #5f27cd) border-box;
transition: all 0.3s ease;
user-select: none;
&__text {
background: linear-gradient(90deg, #ff6b6b, #feca57, #48dbfb, #ff9ff3, #54a0ff, #5f27cd);
background-size: 200% 200%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: gradientFlow 3s ease infinite;
}
&:hover {
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(255, 107, 107, 0.3);
}
&--active {
background: linear-gradient(90deg, #ff6b6b, #feca57, #48dbfb, #ff9ff3, #54a0ff, #5f27cd);
background-size: 200% 200%;
animation: gradientFlow 3s ease infinite;
.premium-filter-tag__text {
background: white;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
}
}
</style> </style>