feat(pool,ui,trace): 号池按页配额刷新、配额倒计时、Trace 全量候选与 UI 用语统一

- 号池管理支持按当前页 Key 刷新配额,后端 refresh-quota 接口支持 key_ids 参数筛选
- 配额进度条 tooltip 展示重置倒计时,前端解析后端重置时间并实时倒计时
- Provider 选择器在无号池提供商时禁用,切换/刷新后保持选中状态对齐
- 启停账号后立即更新调度标签并刷新列表
- Trace 监控展示全量候选记录,不再过滤 available/unused 状态
- 请求时间线号池节点与 Provider 节点去重
- 全局 UI 用语统一:已停用/已禁用 -> 停用/禁用
- 导航菜单调整模型管理与号池管理顺序
This commit is contained in:
fawney19
2026-03-03 11:32:41 +08:00
parent 022aec5720
commit 7ebce161e8
24 changed files with 359 additions and 75 deletions

View File

@@ -754,6 +754,11 @@ const getProviderDisplayName = (attempt: CandidateRecord | null | undefined): st
return providerName ? normalizeProviderName(providerName) : '未知'
}
const normalizeProviderIdentity = (value: unknown): string => {
if (typeof value !== 'string') return ''
return normalizeProviderName(value).trim().toLowerCase()
}
const buildProviderGroups = (items: CandidateRecord[]): NodeGroup[] => {
const groups: NodeGroup[] = []
let currentGroup: NodeGroup | null = null
@@ -829,7 +834,31 @@ const groupedTimeline = computed<NodeGroup[]>(() => {
isPoolGroup: true,
}
return [poolGroup, ...providerGroups]
const poolProviderIds = new Set(
poolAttempts
.map(item => String(item.provider_id || '').trim())
.filter(Boolean),
)
const poolProviderNames = new Set(
poolAttempts
.map(item => normalizeProviderIdentity(item.provider_name))
.filter(Boolean),
)
const dedupedProviderGroups = providerGroups.filter((group) => {
const sameProviderById = group.allAttempts.some((attempt) => {
const providerId = String(attempt.provider_id || '').trim()
return providerId !== '' && poolProviderIds.has(providerId)
})
if (sameProviderById) return false
const groupName = normalizeProviderIdentity(group.primary.provider_name || group.providerName)
if (groupName && poolProviderNames.has(groupName)) return false
return true
})
return [poolGroup, ...dedupedProviderGroups]
})
// 格式转换分界点索引(首个 hasConversion=true 的 group index