mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
Merge branch 'NyaDoo/master'
This commit is contained in:
@@ -57,7 +57,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-if="toast.message"
|
v-if="toast.message"
|
||||||
class="text-sm"
|
class="text-sm break-words"
|
||||||
:class="messageClasses"
|
:class="messageClasses"
|
||||||
>
|
>
|
||||||
{{ toast.message }}
|
{{ toast.message }}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
|
|
||||||
const contentClass = computed(() =>
|
const contentClass = computed(() =>
|
||||||
cn(
|
cn(
|
||||||
'z-[200] min-w-[8rem] overflow-hidden rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-lg',
|
'z-[200] min-w-[8rem] overflow-hidden rounded-2xl border border-border bg-card p-1 text-foreground shadow-2xl backdrop-blur-xl',
|
||||||
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
||||||
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
props.class
|
props.class
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ defineEmits<{
|
|||||||
const itemClass = computed(() =>
|
const itemClass = computed(() =>
|
||||||
cn(
|
cn(
|
||||||
'relative flex cursor-pointer select-none items-center rounded-lg px-3 py-1.5 text-sm outline-none',
|
'relative flex cursor-pointer select-none items-center rounded-lg px-3 py-1.5 text-sm outline-none',
|
||||||
'hover:bg-accent focus:bg-accent focus:text-accent-foreground',
|
'data-[highlighted]:bg-accent focus:bg-accent text-foreground',
|
||||||
'transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
'transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
props.class
|
props.class
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,57 +9,66 @@
|
|||||||
>
|
>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<!-- 常驻选择面板 -->
|
<!-- 搜索栏 -->
|
||||||
<div class="border rounded-lg overflow-hidden">
|
<div class="flex items-center gap-2">
|
||||||
<!-- 搜索 + 操作栏 -->
|
<div class="flex-1 relative">
|
||||||
<div class="flex items-center gap-2 p-2 border-b bg-muted/30">
|
<Search class="absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
||||||
<div class="relative flex-1">
|
<Input
|
||||||
<Search class="absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
v-model="searchQuery"
|
||||||
<Input
|
placeholder="搜索模型或添加自定义模型..."
|
||||||
v-model="searchQuery"
|
class="pl-8 h-9"
|
||||||
placeholder="搜索模型或添加自定义模型..."
|
/>
|
||||||
class="pl-8 h-8 text-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<!-- 已选数量徽章 -->
|
|
||||||
<span
|
|
||||||
v-if="selectedModels.length === 0 && !isAutoFetchMode"
|
|
||||||
class="h-6 px-2 text-xs rounded flex items-center bg-muted text-muted-foreground shrink-0"
|
|
||||||
>
|
|
||||||
全部模型
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
v-else-if="selectedModels.length === 0 && isAutoFetchMode"
|
|
||||||
class="h-6 px-2 text-xs rounded flex items-center bg-amber-500/10 text-amber-600 dark:text-amber-400 shrink-0"
|
|
||||||
>
|
|
||||||
未选择模型
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
v-else
|
|
||||||
class="h-6 px-2 text-xs rounded flex items-center bg-primary/10 text-primary shrink-0"
|
|
||||||
>
|
|
||||||
已选 {{ selectedModels.length }} 个
|
|
||||||
</span>
|
|
||||||
<!-- 刷新上游模型按钮 -->
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="h-6 w-6 flex items-center justify-center rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors shrink-0"
|
|
||||||
:disabled="fetchingUpstreamModels"
|
|
||||||
title="刷新上游模型"
|
|
||||||
@click="refreshUpstreamModels"
|
|
||||||
>
|
|
||||||
<RefreshCw
|
|
||||||
v-if="!fetchingUpstreamModels"
|
|
||||||
class="w-3.5 h-3.5"
|
|
||||||
/>
|
|
||||||
<Loader2
|
|
||||||
v-else
|
|
||||||
class="w-3.5 h-3.5 animate-spin"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 已选数量徽章 -->
|
||||||
|
<span
|
||||||
|
v-if="selectedModels.length === 0 && !isAutoFetchMode"
|
||||||
|
class="h-7 px-2.5 text-xs rounded-md flex items-center bg-muted text-muted-foreground shrink-0"
|
||||||
|
>
|
||||||
|
全部模型
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-else-if="selectedModels.length === 0 && isAutoFetchMode"
|
||||||
|
class="h-7 px-2.5 text-xs rounded-md flex items-center bg-amber-500/10 text-amber-600 dark:text-amber-400 shrink-0"
|
||||||
|
>
|
||||||
|
未选择模型
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="h-7 px-2.5 text-xs rounded-md flex items-center bg-primary/10 text-primary shrink-0"
|
||||||
|
>
|
||||||
|
已选 {{ selectedModels.length }} 个
|
||||||
|
</span>
|
||||||
|
<!-- 刷新上游模型按钮 -->
|
||||||
|
<button
|
||||||
|
v-if="upstreamModelsLoaded"
|
||||||
|
type="button"
|
||||||
|
class="p-2 hover:bg-muted rounded-md transition-colors shrink-0"
|
||||||
|
:disabled="fetchingUpstreamModels"
|
||||||
|
title="刷新上游模型"
|
||||||
|
@click="refreshUpstreamModels"
|
||||||
|
>
|
||||||
|
<RefreshCw
|
||||||
|
class="w-4 h-4"
|
||||||
|
:class="{ 'animate-spin': fetchingUpstreamModels }"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-else-if="!fetchingUpstreamModels"
|
||||||
|
type="button"
|
||||||
|
class="p-2 hover:bg-muted rounded-md transition-colors shrink-0"
|
||||||
|
title="从提供商获取模型"
|
||||||
|
@click="refreshUpstreamModels"
|
||||||
|
>
|
||||||
|
<Zap class="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
<Loader2
|
||||||
|
v-else
|
||||||
|
class="w-4 h-4 animate-spin text-muted-foreground shrink-0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 分组列表 -->
|
<!-- 模型列表 -->
|
||||||
|
<div class="border rounded-lg overflow-hidden">
|
||||||
<div class="max-h-96 overflow-y-auto">
|
<div class="max-h-96 overflow-y-auto">
|
||||||
<!-- 加载中 -->
|
<!-- 加载中 -->
|
||||||
<div
|
<div
|
||||||
@@ -90,7 +99,7 @@
|
|||||||
<!-- 自定义模型 -->
|
<!-- 自定义模型 -->
|
||||||
<div v-if="customModels.length > 0">
|
<div v-if="customModels.length > 0">
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-between px-3 h-9 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors border-b border-border/30"
|
class="flex items-center justify-between px-3 py-2 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors"
|
||||||
@click="toggleGroupCollapse('custom')"
|
@click="toggleGroupCollapse('custom')"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -146,7 +155,7 @@
|
|||||||
<template v-if="filteredGlobalModels.length > 0">
|
<template v-if="filteredGlobalModels.length > 0">
|
||||||
<!-- 标题 sticky top -->
|
<!-- 标题 sticky top -->
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-between px-3 h-9 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors border-b border-border/30"
|
class="flex items-center justify-between px-3 py-2 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors"
|
||||||
@click="toggleGroupCollapse('global')"
|
@click="toggleGroupCollapse('global')"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -215,13 +224,9 @@
|
|||||||
|
|
||||||
<!-- 上游模型 -->
|
<!-- 上游模型 -->
|
||||||
<template v-if="filteredUpstreamModels.length > 0">
|
<template v-if="filteredUpstreamModels.length > 0">
|
||||||
<!-- 标题 sticky(双向粘性:top 和 bottom) -->
|
<!-- 标题 sticky -->
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-between px-3 h-9 bg-muted sticky z-20 cursor-pointer hover:bg-muted/80 transition-colors border-b border-border/30"
|
class="flex items-center justify-between px-3 py-2 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors"
|
||||||
:style="{
|
|
||||||
top: filteredGlobalModels.length > 0 ? '36px' : '0px',
|
|
||||||
bottom: '0px'
|
|
||||||
}"
|
|
||||||
@click="toggleGroupCollapse('upstream')"
|
@click="toggleGroupCollapse('upstream')"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -353,7 +358,8 @@ import {
|
|||||||
ChevronDown,
|
ChevronDown,
|
||||||
Lock,
|
Lock,
|
||||||
LockOpen,
|
LockOpen,
|
||||||
RefreshCw
|
RefreshCw,
|
||||||
|
Zap
|
||||||
} from 'lucide-vue-next'
|
} from 'lucide-vue-next'
|
||||||
import { Dialog, Button, Input } from '@/components/ui'
|
import { Dialog, Button, Input } from '@/components/ui'
|
||||||
import { useToast } from '@/composables/useToast'
|
import { useToast } from '@/composables/useToast'
|
||||||
@@ -706,6 +712,8 @@ async function refreshUpstreamModels() {
|
|||||||
await fetchUpstreamModels(true)
|
await fetchUpstreamModels(true)
|
||||||
if (upstreamModels.value.length > 0) {
|
if (upstreamModels.value.length > 0) {
|
||||||
success('上游模型已刷新')
|
success('上游模型已刷新')
|
||||||
|
// 获取成功后收缩所有分组
|
||||||
|
collapsedGroups.value = new Set(['global', 'upstream', 'custom'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,21 +744,19 @@ watch(() => props.open, async (open) => {
|
|||||||
upstreamModelsLoaded.value = false
|
upstreamModelsLoaded.value = false
|
||||||
allCustomModels.value = []
|
allCustomModels.value = []
|
||||||
|
|
||||||
// 默认全部收缩,自动获取模式下展开上游模型
|
// 自动获取模式下展开上游模型,其他收缩;非自动获取模式下全部展开
|
||||||
if (props.apiKey.auto_fetch_models) {
|
if (props.apiKey.auto_fetch_models) {
|
||||||
collapsedGroups.value = new Set(['global', 'custom'])
|
collapsedGroups.value = new Set(['global', 'custom'])
|
||||||
} else {
|
} else {
|
||||||
collapsedGroups.value = new Set(['global', 'upstream', 'custom'])
|
collapsedGroups.value = new Set()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载全局模型
|
// 加载全局模型
|
||||||
await loadGlobalModels()
|
await loadGlobalModels()
|
||||||
|
|
||||||
// 自动获取上游模型
|
// 自动获取模式下,获取上游模型并刷新(保留锁定的模型)
|
||||||
await fetchUpstreamModels()
|
|
||||||
|
|
||||||
// 自动获取模式下,用最新上游模型刷新(保留锁定的模型)
|
|
||||||
if (props.apiKey.auto_fetch_models) {
|
if (props.apiKey.auto_fetch_models) {
|
||||||
|
await fetchUpstreamModels()
|
||||||
// 锁定的模型 + 最新上游模型(去重)
|
// 锁定的模型 + 最新上游模型(去重)
|
||||||
const newSelected = new Set(lockedModels.value)
|
const newSelected = new Set(lockedModels.value)
|
||||||
upstreamModelNames.value.forEach(m => newSelected.add(m))
|
upstreamModelNames.value.forEach(m => newSelected.add(m))
|
||||||
|
|||||||
@@ -41,37 +41,60 @@
|
|||||||
<!-- 映射名称选择面板 -->
|
<!-- 映射名称选择面板 -->
|
||||||
<div class="space-y-1.5">
|
<div class="space-y-1.5">
|
||||||
<Label class="text-xs">映射名称</Label>
|
<Label class="text-xs">映射名称</Label>
|
||||||
<div class="border rounded-lg overflow-hidden">
|
<!-- 搜索栏 -->
|
||||||
<!-- 搜索 + 操作栏 -->
|
<div class="flex items-center gap-2">
|
||||||
<div class="flex items-center gap-2 p-2 border-b bg-muted/30">
|
<div class="flex-1 relative">
|
||||||
<div class="relative flex-1">
|
<Search class="absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
||||||
<Search class="absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
<Input
|
||||||
<Input
|
v-model="searchQuery"
|
||||||
v-model="searchQuery"
|
placeholder="搜索或添加自定义映射名称..."
|
||||||
placeholder="搜索或添加自定义映射名称..."
|
class="pl-8 h-9"
|
||||||
class="pl-8 h-8 text-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<!-- 已选数量徽章 -->
|
|
||||||
<span
|
|
||||||
v-if="selectedNames.length === 0"
|
|
||||||
class="h-6 px-2 text-xs rounded flex items-center bg-muted text-muted-foreground shrink-0"
|
|
||||||
>
|
|
||||||
未选择
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
v-else
|
|
||||||
class="h-6 px-2 text-xs rounded flex items-center bg-primary/10 text-primary shrink-0"
|
|
||||||
>
|
|
||||||
已选 {{ selectedNames.length }} 个
|
|
||||||
</span>
|
|
||||||
<Loader2
|
|
||||||
v-if="fetchingUpstreamModels"
|
|
||||||
class="w-4 h-4 animate-spin text-muted-foreground shrink-0"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 已选数量徽章 -->
|
||||||
|
<span
|
||||||
|
v-if="selectedNames.length === 0"
|
||||||
|
class="h-7 px-2.5 text-xs rounded-md flex items-center bg-muted text-muted-foreground shrink-0"
|
||||||
|
>
|
||||||
|
未选择
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="h-7 px-2.5 text-xs rounded-md flex items-center bg-primary/10 text-primary shrink-0"
|
||||||
|
>
|
||||||
|
已选 {{ selectedNames.length }} 个
|
||||||
|
</span>
|
||||||
|
<!-- 刷新上游模型按钮 -->
|
||||||
|
<button
|
||||||
|
v-if="upstreamModelsLoaded"
|
||||||
|
type="button"
|
||||||
|
class="p-2 hover:bg-muted rounded-md transition-colors shrink-0"
|
||||||
|
:disabled="fetchingUpstreamModels"
|
||||||
|
title="刷新上游模型"
|
||||||
|
@click="fetchUpstreamModels()"
|
||||||
|
>
|
||||||
|
<RefreshCw
|
||||||
|
class="w-4 h-4"
|
||||||
|
:class="{ 'animate-spin': fetchingUpstreamModels }"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-else-if="!fetchingUpstreamModels"
|
||||||
|
type="button"
|
||||||
|
class="p-2 hover:bg-muted rounded-md transition-colors shrink-0"
|
||||||
|
title="从提供商获取模型"
|
||||||
|
@click="fetchUpstreamModels()"
|
||||||
|
>
|
||||||
|
<Zap class="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
<Loader2
|
||||||
|
v-else
|
||||||
|
class="w-4 h-4 animate-spin text-muted-foreground shrink-0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 分组列表 -->
|
<!-- 模型列表 -->
|
||||||
|
<div class="border rounded-lg overflow-hidden">
|
||||||
<div class="max-h-80 overflow-y-auto">
|
<div class="max-h-80 overflow-y-auto">
|
||||||
<!-- 加载中 -->
|
<!-- 加载中 -->
|
||||||
<div
|
<div
|
||||||
@@ -102,7 +125,7 @@
|
|||||||
<!-- 自定义映射名称 -->
|
<!-- 自定义映射名称 -->
|
||||||
<div v-if="customNames.length > 0">
|
<div v-if="customNames.length > 0">
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-between px-3 h-9 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors border-b border-border/30"
|
class="flex items-center justify-between px-3 py-2 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors"
|
||||||
@click="toggleGroupCollapse('custom')"
|
@click="toggleGroupCollapse('custom')"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -141,7 +164,7 @@
|
|||||||
<!-- 上游模型 -->
|
<!-- 上游模型 -->
|
||||||
<template v-if="filteredUpstreamModels.length > 0">
|
<template v-if="filteredUpstreamModels.length > 0">
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-between px-3 h-9 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors border-b border-border/30"
|
class="flex items-center justify-between px-3 py-2 bg-muted sticky top-0 z-20 cursor-pointer hover:bg-muted/80 transition-colors"
|
||||||
@click="toggleGroupCollapse('upstream')"
|
@click="toggleGroupCollapse('upstream')"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -226,7 +249,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { Tag, Loader2, Plus, Search, Check, ChevronDown } from 'lucide-vue-next'
|
import { Tag, Loader2, Plus, Search, Check, ChevronDown, RefreshCw, Zap } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Input,
|
Input,
|
||||||
@@ -263,6 +286,7 @@ const props = defineProps<{
|
|||||||
models: Model[]
|
models: Model[]
|
||||||
editingGroup?: AliasGroup | null
|
editingGroup?: AliasGroup | null
|
||||||
preselectedModelId?: string | null
|
preselectedModelId?: string | null
|
||||||
|
hasAutoFetchKey?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -278,6 +302,7 @@ const submitting = ref(false)
|
|||||||
const modelSelectOpen = ref(false)
|
const modelSelectOpen = ref(false)
|
||||||
const loadingModels = ref(false)
|
const loadingModels = ref(false)
|
||||||
const fetchingUpstreamModels = ref(false)
|
const fetchingUpstreamModels = ref(false)
|
||||||
|
const upstreamModelsLoaded = ref(false)
|
||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
@@ -426,6 +451,7 @@ async function fetchUpstreamModels() {
|
|||||||
const result = await fetchCachedModels(props.providerId)
|
const result = await fetchCachedModels(props.providerId)
|
||||||
if (result.models.length > 0) {
|
if (result.models.length > 0) {
|
||||||
upstreamModels.value = result.models
|
upstreamModels.value = result.models
|
||||||
|
upstreamModelsLoaded.value = true
|
||||||
// 获取上游模型后,将不在上游列表中的已选名称添加到自定义列表
|
// 获取上游模型后,将不在上游列表中的已选名称添加到自定义列表
|
||||||
const upstreamIds = new Set(result.models.map(m => m.id))
|
const upstreamIds = new Set(result.models.map(m => m.id))
|
||||||
const customFromSelected = selectedNames.value.filter(name => !upstreamIds.has(name))
|
const customFromSelected = selectedNames.value.filter(name => !upstreamIds.has(name))
|
||||||
@@ -448,8 +474,10 @@ async function fetchUpstreamModels() {
|
|||||||
watch(() => props.open, async (isOpen) => {
|
watch(() => props.open, async (isOpen) => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
initForm()
|
initForm()
|
||||||
// 加载上游模型
|
// 只有在有 key 配置了自动获取时才自动加载上游模型
|
||||||
await fetchUpstreamModels()
|
if (props.hasAutoFetchKey) {
|
||||||
|
await fetchUpstreamModels()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -469,6 +497,8 @@ function initForm() {
|
|||||||
allCustomNames.value = []
|
allCustomNames.value = []
|
||||||
}
|
}
|
||||||
searchQuery.value = ''
|
searchQuery.value = ''
|
||||||
|
upstreamModels.value = []
|
||||||
|
upstreamModelsLoaded.value = false
|
||||||
// 默认展开所有分组
|
// 默认展开所有分组
|
||||||
collapsedGroups.value = new Set()
|
collapsedGroups.value = new Set()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -413,6 +413,7 @@
|
|||||||
ref="modelMappingTabRef"
|
ref="modelMappingTabRef"
|
||||||
:key="`mapping-${provider.id}`"
|
:key="`mapping-${provider.id}`"
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
|
:provider-keys="providerKeys"
|
||||||
@refresh="handleModelMappingChanged"
|
@refresh="handleModelMappingChanged"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -296,6 +296,7 @@
|
|||||||
:models="models"
|
:models="models"
|
||||||
:editing-group="editingGroup"
|
:editing-group="editingGroup"
|
||||||
:preselected-model-id="preselectedModelId"
|
:preselected-model-id="preselectedModelId"
|
||||||
|
:has-auto-fetch-key="hasAutoFetchKey"
|
||||||
@saved="onDialogSaved"
|
@saved="onDialogSaved"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -362,6 +363,7 @@ interface CombinedMapping {
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
provider: any
|
provider: any
|
||||||
|
providerKeys?: EndpointAPIKey[]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -393,6 +395,12 @@ const formatMenuOpen = ref<Record<string, boolean>>({})
|
|||||||
// 展开状态
|
// 展开状态
|
||||||
const expandedItems = ref<Set<number>>(new Set())
|
const expandedItems = ref<Set<number>>(new Set())
|
||||||
|
|
||||||
|
// 是否有 key 配置了自动获取上游模型
|
||||||
|
const hasAutoFetchKey = computed(() => {
|
||||||
|
const keys = props.providerKeys || providerKeys.value
|
||||||
|
return keys.some(k => k.auto_fetch_models)
|
||||||
|
})
|
||||||
|
|
||||||
// 生成作用域唯一键
|
// 生成作用域唯一键
|
||||||
function getApiFormatsKey(formats: string[] | undefined): string {
|
function getApiFormatsKey(formats: string[] | undefined): string {
|
||||||
if (!formats || formats.length === 0) return ''
|
if (!formats || formats.length === 0) return ''
|
||||||
|
|||||||
Reference in New Issue
Block a user