fix(routing): filter providers by selected model

This commit is contained in:
AAEE86
2026-09-04 15:25:32 +08:00
parent 18d78dd6c9
commit 1eb2d10dec
4 changed files with 102 additions and 2 deletions
@@ -0,0 +1,31 @@
import { describe, expect, it } from 'vitest'
import { DEFAULT_ROUTING_POLICY_MODEL } from '../utils/routingPolicy'
import { buildRoutingProviderSummaryQuery } from '../utils/providerQuery'
describe('routing provider query', () => {
it('filters provider sorting by the selected GlobalModel ID', () => {
expect(buildRoutingProviderSummaryQuery(
'claude-fable-5-1',
'global-claude-fable-5-1',
'provider',
)).toEqual({
page: 1,
page_size: 9999,
model_id: 'global-claude-fable-5-1',
})
})
it('keeps unified sorting and key sorting unfiltered', () => {
const expected = { page: 1, page_size: 9999 }
expect(buildRoutingProviderSummaryQuery(DEFAULT_ROUTING_POLICY_MODEL, undefined, 'provider'))
.toEqual(expected)
expect(buildRoutingProviderSummaryQuery('claude-fable-5-1', 'global-claude-fable-5-1', 'global_key'))
.toEqual(expected)
})
it('does not fall back to all providers before a model ID is available', () => {
expect(buildRoutingProviderSummaryQuery('claude-fable-5-1', undefined, 'provider')).toBeNull()
})
})
@@ -324,6 +324,7 @@ import {
type RoutingPriorityMode,
type RoutingSchedulingMode,
} from '../utils/routingPolicy'
import { buildRoutingProviderSummaryQuery } from '../utils/providerQuery'
interface ProviderPriorityRow {
id: string
@@ -367,6 +368,7 @@ interface GlobalKeySource {
const props = defineProps<{
config: RoutingGroupConfig
model?: string
modelId?: string
priorityMode?: RoutingPriorityMode
schedulingMode?: RoutingSchedulingMode
showPriorityMode?: boolean
@@ -398,6 +400,7 @@ const draggedKeyId = ref<string | null>(null)
const dragOverKeyId = ref<string | null>(null)
const providerMultiSelectEnabled = ref(false)
const selectedProviderIds = ref<Set<string>>(new Set())
let providerLoadRequestId = 0
const config = computed(() => normalizeRoutingGroupConfig(props.config))
const targetModel = computed(() => props.model?.trim() || DEFAULT_ROUTING_POLICY_MODEL)
@@ -505,6 +508,12 @@ watch(effectivePriorityMode, mode => {
providerMultiSelectEnabled.value = false
selectedProviderIds.value = new Set()
}
void loadProviders()
})
// 父组件异步解析全局模型 ID 后,重新加载对应模型的提供商列表。
watch([targetModel, () => props.modelId], () => {
void loadProviders()
})
watch(providerRows, rows => {
@@ -561,16 +570,31 @@ function updateSchedulingMode(mode: RoutingSchedulingMode): void {
}
async function loadProviders(): Promise<void> {
const requestId = ++providerLoadRequestId
loadingProviders.value = true
loadError.value = null
try {
const response = await getProvidersSummary({ page: 1, page_size: 9999 })
const query = buildRoutingProviderSummaryQuery(
targetModel.value,
props.modelId,
effectivePriorityMode.value,
)
if (!query) {
providers.value = []
return
}
const response = await getProvidersSummary(query)
if (requestId !== providerLoadRequestId) return
providers.value = response.items
} catch (err) {
if (requestId !== providerLoadRequestId) return
loadError.value = parseApiError(err, '加载 Provider 失败')
providers.value = []
} finally {
loadingProviders.value = false
if (requestId === providerLoadRequestId) {
loadingProviders.value = false
}
}
}
@@ -0,0 +1,39 @@
import type { ProviderSummaryQuery } from '@/api/endpoints/providers'
import {
DEFAULT_ROUTING_POLICY_MODEL,
type RoutingPriorityMode,
} from './routingPolicy'
const PROVIDER_SUMMARY_PAGE_SIZE = 9999
/**
* 构造路由排序编辑器的提供商查询参数。
* 按模型配置时必须使用 GlobalModel ID 过滤,避免把模型名称误当成 ID;统一调度和
* Key 排序仍需要完整的提供商集合。
*/
export function buildRoutingProviderSummaryQuery(
model: string | undefined,
modelId: string | undefined,
priorityMode: RoutingPriorityMode,
): ProviderSummaryQuery | null {
const query: ProviderSummaryQuery = {
page: 1,
page_size: PROVIDER_SUMMARY_PAGE_SIZE,
}
const isModelScoped = (model?.trim() || DEFAULT_ROUTING_POLICY_MODEL)
!== DEFAULT_ROUTING_POLICY_MODEL
if (!isModelScoped || priorityMode !== 'provider') {
return query
}
const normalizedModelId = modelId?.trim()
// 模型 ID 尚未由父组件解析出来时,不能回退到全量列表,否则会短暂显示错误的提供商。
if (!normalizedModelId) return null
return {
...query,
model_id: normalizedModelId,
}
}
@@ -745,6 +745,7 @@
<RoutingPriorityPolicyEditor
:config="activeConfigForReading"
:model="activePerModelPolicy.model"
:model-id="globalModelIdFor(activePerModelPolicy.model)"
:priority-mode="modelPriorityMode(activePerModelPolicy.model)"
:scheduling-mode="modelSchedulingMode(activePerModelPolicy.model)"
:show-priority-mode="false"
@@ -1458,6 +1459,11 @@ function globalModelLabel(modelName: string): string {
return `${model.display_name} (${model.name})`
}
function globalModelIdFor(modelName: string): string | undefined {
const normalizedName = modelName.trim()
return globalModels.value.find(item => item.name.trim() === normalizedName)?.id
}
function replaceGroup(group: RoutingGroupRecord, select = true): void {
const normalized = normalizeRecord(group)
const index = groups.value.findIndex(item => item.id === normalized.id)