diff --git a/frontend/src/api/endpoints/providers.ts b/frontend/src/api/endpoints/providers.ts index b70996b..8fcd183 100644 --- a/frontend/src/api/endpoints/providers.ts +++ b/frontend/src/api/endpoints/providers.ts @@ -58,3 +58,16 @@ export async function deleteProvider(providerId: string): Promise<{ message: str return response.data } +/** + * 测试模型连接性 + */ +export async function testModel(data: { + provider_id: string + model_name: string + api_key_id?: string + message?: string +}): Promise { + const response = await client.post('/api/admin/provider-query/test-model', data) + return response.data +} + diff --git a/frontend/src/components/ui/dialog/Dialog.vue b/frontend/src/components/ui/dialog/Dialog.vue index 9e45f5f..c0cba50 100644 --- a/frontend/src/components/ui/dialog/Dialog.vue +++ b/frontend/src/components/ui/dialog/Dialog.vue @@ -163,7 +163,9 @@ const contentZIndex = computed(() => (props.zIndex || 60) + 10) useEscapeKey(() => { if (isOpen.value) { handleClose() + return true // 阻止其他监听器(如父级抽屉的 ESC 监听器) } + return false }, { disableOnInput: true, once: false diff --git a/frontend/src/composables/useConfirm.ts b/frontend/src/composables/useConfirm.ts index f821235..f9ef15f 100644 --- a/frontend/src/composables/useConfirm.ts +++ b/frontend/src/composables/useConfirm.ts @@ -47,11 +47,11 @@ export function useConfirm() { /** * 便捷方法:危险操作确认(红色主题) */ - const confirmDanger = (message: string, title?: string): Promise => { + const confirmDanger = (message: string, title?: string, confirmText?: string): Promise => { return confirm({ message, title: title || '危险操作', - confirmText: '删除', + confirmText: confirmText || '删除', variant: 'danger' }) } diff --git a/frontend/src/composables/useEscapeKey.ts b/frontend/src/composables/useEscapeKey.ts index 4d85c65..84604a6 100644 --- a/frontend/src/composables/useEscapeKey.ts +++ b/frontend/src/composables/useEscapeKey.ts @@ -4,11 +4,11 @@ import { onMounted, onUnmounted, ref } from 'vue' * ESC 键监听 Composable(简化版本,直接使用独立监听器) * 用于按 ESC 键关闭弹窗或其他可关闭的组件 * - * @param callback - 按 ESC 键时执行的回调函数 + * @param callback - 按 ESC 键时执行的回调函数,返回 true 表示已处理事件,阻止其他监听器执行 * @param options - 配置选项 */ export function useEscapeKey( - callback: () => void, + callback: () => void | boolean, options: { /** 是否在输入框获得焦点时禁用 ESC 键,默认 true */ disableOnInput?: boolean @@ -42,8 +42,11 @@ export function useEscapeKey( if (isInputElement) return } - // 执行回调 - callback() + // 执行回调,如果返回 true 则阻止其他监听器 + const handled = callback() + if (handled === true) { + event.stopImmediatePropagation() + } // 移除当前元素的焦点,避免残留样式 if (document.activeElement instanceof HTMLElement) { diff --git a/frontend/src/features/providers/components/ModelMappingDialog.vue b/frontend/src/features/providers/components/ModelMappingDialog.vue index ce5f84f..ef243b7 100644 --- a/frontend/src/features/providers/components/ModelMappingDialog.vue +++ b/frontend/src/features/providers/components/ModelMappingDialog.vue @@ -17,7 +17,7 @@ v-model:open="modelSelectOpen" :model-value="formData.modelId" :disabled="!!editingGroup" - @update:model-value="formData.modelId = $event" + @update:model-value="handleModelChange" > @@ -518,6 +518,15 @@ function initForm() { upstreamModels.value = [] } } + +// 处理模型选择变更 +function handleModelChange(value: string) { + formData.value.modelId = value + const selectedModel = props.models.find(m => m.id === value) + if (selectedModel) { + upstreamModelSearch.value = selectedModel.provider_model_name + } +} // 切换 API 格式 function toggleApiFormat(format: string) { diff --git a/frontend/src/features/providers/components/ProviderDetailDrawer.vue b/frontend/src/features/providers/components/ProviderDetailDrawer.vue index d4aef38..fdde2a9 100644 --- a/frontend/src/features/providers/components/ProviderDetailDrawer.vue +++ b/frontend/src/features/providers/components/ProviderDetailDrawer.vue @@ -531,6 +531,7 @@ (null) const batchAssignDialogOpen = ref(false) +// ModelAliasesTab 组件引用 +const modelAliasesTabRef = ref | null>(null) + // 拖动排序相关状态 const dragState = ref({ isDragging: false, @@ -756,7 +760,9 @@ const hasBlockingDialogOpen = computed(() => deleteKeyConfirmOpen.value || modelFormDialogOpen.value || deleteModelConfirmOpen.value || - batchAssignDialogOpen.value + batchAssignDialogOpen.value || + // 检测 ModelAliasesTab 子组件的 Dialog 是否打开 + modelAliasesTabRef.value?.dialogOpen ) // 监听 providerId 变化 diff --git a/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue b/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue index 6115b8c..7d2aff7 100644 --- a/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue +++ b/frontend/src/features/providers/components/provider-tabs/ModelAliasesTab.vue @@ -110,16 +110,30 @@
- - - {{ mapping.priority }} - - - - {{ mapping.name }} - +
+ + + {{ mapping.priority }} + + + + {{ mapping.name }} + +
+ +
@@ -166,13 +180,14 @@ diff --git a/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue b/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue index 1465c4e..628a8fa 100644 --- a/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue +++ b/frontend/src/features/providers/components/provider-tabs/ModelsTab.vue @@ -156,6 +156,17 @@
+