mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
feat(pool,ui,trace): 号池按页配额刷新、配额倒计时、Trace 全量候选与 UI 用语统一
- 号池管理支持按当前页 Key 刷新配额,后端 refresh-quota 接口支持 key_ids 参数筛选 - 配额进度条 tooltip 展示重置倒计时,前端解析后端重置时间并实时倒计时 - Provider 选择器在无号池提供商时禁用,切换/刷新后保持选中状态对齐 - 启停账号后立即更新调度标签并刷新列表 - Trace 监控展示全量候选记录,不再过滤 available/unused 状态 - 请求时间线号池节点与 Provider 节点去重 - 全局 UI 用语统一:已停用/已禁用 -> 停用/禁用 - 导航菜单调整模型管理与号池管理顺序
This commit is contained in:
@@ -1102,7 +1102,7 @@ function getKeyTooltip(key: RoutingKeyInfo): string {
|
||||
parts.push(`名称: ${key.name}`)
|
||||
parts.push(`健康度: ${((key.health_score || 0) * 100).toFixed(0)}%`)
|
||||
if (!key.is_active) {
|
||||
parts.push('状态: 已禁用')
|
||||
parts.push('状态: 禁用')
|
||||
} else if (key.circuit_breaker_open) {
|
||||
parts.push(`熔断中: ${key.circuit_breaker_formats.join(', ')}`)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
variant="secondary"
|
||||
class="text-xs"
|
||||
>
|
||||
已停用
|
||||
停用
|
||||
</Badge>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
: key.is_active
|
||||
? 'text-foreground/70 hover:bg-muted hover:text-foreground'
|
||||
: 'text-muted-foreground hover:bg-muted hover:text-foreground'"
|
||||
:title="!key.provider_active ? 'Provider 已停用' : key.is_active ? '点击停用' : '点击启用'"
|
||||
:title="!key.provider_active ? 'Provider 停用' : key.is_active ? '点击停用' : '点击启用'"
|
||||
:disabled="!key.provider_active"
|
||||
@click.stop="toggleKeyActive(format, key)"
|
||||
>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
:variant="provider.is_active ? 'default' : 'secondary'"
|
||||
class="text-xs shrink-0"
|
||||
>
|
||||
{{ provider.is_active ? '活跃' : '已停用' }}
|
||||
{{ provider.is_active ? '活跃' : '停用' }}
|
||||
</Badge>
|
||||
</div>
|
||||
<div class="flex items-center gap-1 shrink-0">
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
:variant="provider.is_active ? 'success' : 'secondary'"
|
||||
class="text-xs"
|
||||
>
|
||||
{{ provider.is_active ? '活跃' : '已停用' }}
|
||||
{{ provider.is_active ? '活跃' : '停用' }}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
|
||||
@@ -372,7 +372,7 @@ function getVideoPricingTooltip(model: Model): string {
|
||||
// 获取状态指示灯样式
|
||||
function getStatusIndicatorClass(model: Model): string {
|
||||
if (!model.is_active) {
|
||||
// 已停用 - 灰色
|
||||
// 停用 - 灰色
|
||||
return 'bg-gray-400 dark:bg-gray-600'
|
||||
}
|
||||
if (model.is_available) {
|
||||
@@ -386,7 +386,7 @@ function getStatusIndicatorClass(model: Model): string {
|
||||
// 获取状态提示文本
|
||||
function getStatusTitle(model: Model): string {
|
||||
if (!model.is_active) {
|
||||
return '已停用'
|
||||
return '停用'
|
||||
}
|
||||
if (model.is_available) {
|
||||
return '活跃且可用'
|
||||
|
||||
@@ -75,7 +75,7 @@ export function getEndpointTooltip(endpoint: EndpointHealthDetail): string {
|
||||
|
||||
switch (status) {
|
||||
case 'disabled':
|
||||
return `${format}: 端点已禁用`
|
||||
return `${format}: 端点禁用`
|
||||
case 'no_keys':
|
||||
return `${format}: 未配置密钥`
|
||||
case 'keys_disabled':
|
||||
|
||||
@@ -19,7 +19,7 @@ export function useProviderFilters(
|
||||
const statusFilters: FilterOption[] = [
|
||||
{ value: 'all', label: '全部状态' },
|
||||
{ value: 'active', label: '活跃' },
|
||||
{ value: 'inactive', label: '已停用' },
|
||||
{ value: 'inactive', label: '停用' },
|
||||
]
|
||||
|
||||
const apiFormatFilters: FilterOption[] = [
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user