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 activeApiGroup = ref('');
const isScrolling = ref(false);
const filterPremiumOnly = ref(false); // 是否只显示尊享模型
// 检查模型是否可用
function isModelAvailable(item: GetSessionListVO) {
@@ -95,18 +96,18 @@ const currentModelName = computed(
() => modelStore.currentModelInfo && modelStore.currentModelInfo.modelName,
);
// API 类型映射
const apiTypeNameMap: Record<string, string> = {
Completions: 'OpenAI Chat Completion',
Responses: 'OpenAI Responses API',
Messages: 'Anthropic Claude API',
GenerateContent: 'Google Gemini API',
};
// 过滤后的模型列表
const filteredModelList = computed(() => {
if (filterPremiumOnly.value) {
return modelStore.modelList.filter(model => model.isPremiumPackage);
}
return modelStore.modelList;
});
// 按 API 类型分组
const groupedByApiType = computed(() => {
const groups: Record<string, GetSessionListVO[]> = {};
modelStore.modelList.forEach((model) => {
filteredModelList.value.forEach((model) => {
const apiType = model.modelApiType || 'Completions';
if (!groups[apiType]) {
groups[apiType] = [];
@@ -119,7 +120,7 @@ const groupedByApiType = computed(() => {
// 按 厂商 (Provider) 分组
const groupedByProvider = computed(() => {
const groups: Record<string, GetSessionListVO[]> = {};
modelStore.modelList.forEach((model) => {
filteredModelList.value.forEach((model) => {
const provider = model.providerName || 'Other';
if (!groups[provider]) {
groups[provider] = [];
@@ -311,8 +312,17 @@ function getWrapperClass(item: GetSessionListVO) {
align-center
>
<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-icon class="ml-1">
@@ -330,7 +340,7 @@ function getWrapperClass(item: GetSessionListVO) {
<div
v-for="(_, provider) in groupedByProvider"
: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 }"
@click="scrollToGroup('provider', provider as string)"
>
@@ -402,11 +412,11 @@ function getWrapperClass(item: GetSessionListVO) {
<div
v-for="(_, apiType) in groupedByApiType"
: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 }"
@click="scrollToGroup('api', apiType as string)"
>
<div v-html="(apiTypeNameMap[apiType] || apiType).replace(/ /g, '<br/>')" />
<div v-html="(apiType).replace(/ /g, '<br/>')" />
</div>
</div>
<!-- 内容列表 -->
@@ -415,7 +425,7 @@ function getWrapperClass(item: GetSessionListVO) {
<div class="px-2 pb-4">
<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">
{{ apiTypeNameMap[apiType] || apiType }}
{{ apiType }}
</div>
<div
v-for="item in models"
@@ -516,4 +526,45 @@ function getWrapperClass(item: GetSessionListVO) {
.border-primary {
border-color: var(--el-color-primary, #409eff);
}
</style>
/* 尊享过滤标签 */
.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>