fix(providers): 修复 Key 表单状态同步与 streaming 候选状态码处理

前端:
- KeyAllowedModelsEditDialog 同时监听 open 和 apiKey 变化,避免切换 key 时状态未刷新
- KeyFormDialog 新增 api_formats 过滤与默认值逻辑,可用格式变化时自动同步表单
- ProviderDetailDrawer 合并 provider 和 endpoint 的 api_formats 传递给 Key 表单,
  数据刷新后同步 currentEndpoint 和 editingKey 引用

后端:
- mark_candidate_streaming 移除 status_code 参数,streaming 阶段不再提前写入状态码
- 简化 active_requests 中 streaming 请求的完成判断,不再依赖 status_code 条件
This commit is contained in:
fawney19
2026-03-07 17:11:19 +08:00
parent 239238fe47
commit a00e137ffc
6 changed files with 154 additions and 51 deletions
@@ -936,7 +936,7 @@
:editing-key="editingKey"
:provider-id="provider ? provider.id : null"
:provider-type="provider?.provider_type || null"
:available-api-formats="provider?.api_formats || []"
:available-api-formats="availableKeyApiFormats"
@close="keyFormDialogOpen = false"
@saved="handleKeyChanged"
/>
@@ -1258,6 +1258,65 @@ const allKeys = computed(() => {
return result
})
const availableKeyApiFormats = computed(() => {
const formatSet = new Set<string>()
for (const format of provider.value?.api_formats || []) {
if (format) {
formatSet.add(format)
}
}
for (const endpoint of endpoints.value) {
if (endpoint.api_format) {
formatSet.add(endpoint.api_format)
}
}
return sortApiFormats([...formatSet])
})
function syncCurrentSelections(
nextEndpoints: ProviderEndpointWithKeys[] = endpoints.value,
nextProviderKeys: EndpointAPIKey[] = providerKeys.value
) {
if (currentEndpoint.value) {
currentEndpoint.value = nextEndpoints.find(endpoint => endpoint.id === currentEndpoint.value?.id) ?? null
}
if (!editingKey.value) {
return
}
const latestKeys: EndpointAPIKey[] = []
const seenKeyIds = new Set<string>()
for (const key of nextProviderKeys) {
if (!seenKeyIds.has(key.id)) {
seenKeyIds.add(key.id)
latestKeys.push(key)
}
}
for (const endpoint of nextEndpoints) {
for (const key of endpoint.keys || []) {
if (!seenKeyIds.has(key.id)) {
seenKeyIds.add(key.id)
latestKeys.push(key)
}
}
}
const latestEditingKey = latestKeys.find(key => key.id === editingKey.value?.id) || null
editingKey.value = latestEditingKey
if (!latestEditingKey) {
keyFormDialogOpen.value = false
keyPermissionsDialogOpen.value = false
oauthKeyEditDialogOpen.value = false
}
}
// ===== 账号列表智能分页 =====
const keysListRef = ref<HTMLElement | null>(null)
const {
@@ -1558,6 +1617,7 @@ async function handleRefreshOAuth(key: EndpointAPIKey) {
const freshKeys = await getProviderKeys(props.providerId).catch(() => null)
if (freshKeys) {
providerKeys.value = freshKeys
syncCurrentSelections(endpoints.value, freshKeys)
}
}
// Antigravity:token 刷新后可能完成了账号激活,触发配额获取
@@ -2640,7 +2700,7 @@ async function loadEndpoints() {
providerKeys.value = providerKeysResult
providerModels.value = modelsResult
// 按 API 格式排序
endpoints.value = endpointsList.sort((a, b) => {
const sortedEndpoints = endpointsList.sort((a, b) => {
const aIdx = API_FORMAT_ORDER.indexOf(a.api_format)
const bIdx = API_FORMAT_ORDER.indexOf(b.api_format)
if (aIdx === -1 && bIdx === -1) return 0
@@ -2648,6 +2708,8 @@ async function loadEndpoints() {
if (bIdx === -1) return -1
return aIdx - bIdx
})
endpoints.value = sortedEndpoints
syncCurrentSelections(sortedEndpoints, providerKeysResult)
} catch (err: unknown) {
if (requestId !== endpointsLoadRequestId) return
showError(parseApiError(err, '加载端点失败'), '错误')