完善模板编辑与模型管理体验

This commit is contained in:
zwt13703
2026-07-03 11:14:24 +08:00
parent 52eb058070
commit a796301ae8
19 changed files with 1065 additions and 246 deletions
+75 -9
View File
@@ -20,12 +20,21 @@
<div class="mc-provider">密钥{{ item.api_key_preview || '未设置' }}</div>
<div class="mc-provider">流式传输{{ item.supports_streaming ? '支持' : '关闭' }}</div>
<div class="mc-provider">思考模式{{ item.enable_reasoning ? '开启' : '关闭' }}</div>
<div v-if="isDeepSeek(item) && balanceMap[item.id]" class="mc-provider">
余额{{ formatBalanceText(balanceMap[item.id]) }}
</div>
</div>
<div :class="['mc-status', item.status === 'enabled' ? 'on' : 'off']">
{{ item.status === 'enabled' ? '已启用' : '已禁用' }}
</div>
<div class="mc-actions">
<a-button size="small" @click="runTest(item)">测试</a-button>
<a-button size="small" :loading="testingMap[item.id]" @click="runTest(item)">
<template #icon><reload-outlined /></template>
刷新测试
</a-button>
<a-button v-if="isDeepSeek(item)" size="small" :loading="balanceLoadingMap[item.id]" @click="fetchBalance(item)">
查看余额
</a-button>
<a-button size="small" @click="openEdit(item)">编辑</a-button>
<a-button size="small" @click="toggleStatus(item)">{{ item.status === 'enabled' ? '禁用' : '启用' }}</a-button>
</div>
@@ -39,7 +48,13 @@
<a-input v-model:value="form.name" />
</a-form-item>
<a-form-item label="供应厂商">
<a-input v-model:value="form.provider" />
<a-select v-model:value="providerPreset" @change="applyProviderPreset">
<a-select-option value="deepseek">DeepSeek</a-select-option>
<a-select-option value="custom">自定义</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="providerPreset === 'custom'" label="自定义厂商名称">
<a-input v-model:value="form.provider" placeholder="例如 OpenAI / Anthropic / 其他" />
</a-form-item>
<a-form-item label="API 格式">
<a-select v-model:value="form.api_format">
@@ -66,7 +81,8 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { Modal, message } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { ReloadOutlined } from '@ant-design/icons-vue'
import { useModelStore } from '@/stores/model'
const store = useModelStore()
@@ -75,6 +91,41 @@ const modalOpen = ref(false)
const isEdit = ref(false)
const editId = ref(0)
const form = ref({ name: '', provider: '', api_format: 'openai', api_endpoint: '', api_key: '', supports_streaming: false, enable_reasoning: false })
const providerPreset = ref<'deepseek' | 'custom'>('custom')
const testingMap = ref<Record<number, boolean>>({})
const balanceLoadingMap = ref<Record<number, boolean>>({})
const balanceMap = ref<Record<number, { is_available: boolean; balance_infos: Array<{ currency: string; total_balance: string; granted_balance: string; topped_up_balance: string }> }>>({})
function isDeepSeek(item: any) {
const provider = (item?.provider || '').trim().toLowerCase()
return provider === 'deepseek'
}
function applyProviderPreset(value: 'deepseek' | 'custom') {
if (value === 'deepseek') {
form.value.provider = 'DeepSeek'
form.value.api_format = 'openai'
if (!form.value.api_endpoint || form.value.api_endpoint.includes('deepseek')) {
form.value.api_endpoint = 'https://api.deepseek.com'
}
return
}
if (form.value.provider === 'DeepSeek') {
form.value.provider = ''
}
}
function inferProviderPreset(item?: any) {
providerPreset.value = isDeepSeek(item || form.value) ? 'deepseek' : 'custom'
}
function formatBalanceText(data: { is_available: boolean; balance_infos: Array<{ currency: string; total_balance: string; granted_balance: string; topped_up_balance: string }> }) {
const infos = data?.balance_infos || []
if (!infos.length) return data?.is_available ? '可用' : '不可用'
return infos
.map((item) => `${item.currency} ${item.total_balance}(充值 ${item.topped_up_balance} / 赠送 ${item.granted_balance}`)
.join('')
}
async function refreshList() {
await store.fetchList()
@@ -88,6 +139,8 @@ onMounted(async () => {
function openAdd() {
isEdit.value = false
form.value = { name: '', provider: '', api_format: 'openai', api_endpoint: '', api_key: '', supports_streaming: false, enable_reasoning: false }
providerPreset.value = 'deepseek'
applyProviderPreset('deepseek')
modalOpen.value = true
}
@@ -103,6 +156,7 @@ function openEdit(item: any) {
supports_streaming: !!item.supports_streaming,
enable_reasoning: !!item.enable_reasoning,
}
inferProviderPreset(item)
modalOpen.value = true
}
@@ -124,15 +178,27 @@ async function toggleStatus(item: any) {
}
async function runTest(item: any) {
testingMap.value[item.id] = true
try {
const result: any = await store.test(item.id)
Modal.info({
title: '连接测试结果',
width: 680,
content: JSON.stringify(result.data, null, 2),
})
message.success(result.data?.message || `模型 ${item.name} 测试成功`, 2)
} catch (error: any) {
message.error(error.message || '连接测试失败')
message.error(error.message || '连接测试失败', 2)
} finally {
testingMap.value[item.id] = false
}
}
async function fetchBalance(item: any) {
balanceLoadingMap.value[item.id] = true
try {
const result: any = await store.balance(item.id)
balanceMap.value[item.id] = result.data
message.success(`已刷新 ${item.name} 余额`, 2)
} catch (error: any) {
message.error(error.message || '余额查询失败', 2)
} finally {
balanceLoadingMap.value[item.id] = false
}
}
</script>