mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
feat: 优先级管理对话框显示 API 格式标签和余额信息 (#109)
This commit is contained in:
@@ -122,6 +122,26 @@
|
|||||||
停用
|
停用
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- API 格式标签 -->
|
||||||
|
<div
|
||||||
|
v-if="provider.api_formats?.length"
|
||||||
|
class="flex items-center gap-1 shrink-0"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-for="fmt in provider.api_formats"
|
||||||
|
:key="fmt"
|
||||||
|
class="text-[10px] px-1.5 py-0.5 rounded bg-muted text-muted-foreground"
|
||||||
|
>
|
||||||
|
{{ API_FORMAT_SHORT[fmt] || fmt }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- 余额显示-->
|
||||||
|
<span
|
||||||
|
v-if="formatBalanceDisplay(provider.id)"
|
||||||
|
class="text-xs shrink-0"
|
||||||
|
>
|
||||||
|
<span class="font-semibold text-foreground/90">{{ formatBalanceDisplay(provider.id) }}</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -416,6 +436,8 @@ import { useToast } from '@/composables/useToast'
|
|||||||
import { updateProvider, updateProviderKey } from '@/api/endpoints'
|
import { updateProvider, updateProviderKey } from '@/api/endpoints'
|
||||||
import type { ProviderWithEndpointsSummary } from '@/api/endpoints'
|
import type { ProviderWithEndpointsSummary } from '@/api/endpoints'
|
||||||
import { adminApi } from '@/api/admin'
|
import { adminApi } from '@/api/admin'
|
||||||
|
import { batchQueryBalance, type ActionResultResponse, type BalanceInfo } from '@/api/providerOps'
|
||||||
|
import { API_FORMAT_SHORT } from '@/api/endpoints/types'
|
||||||
|
|
||||||
interface KeyWithMeta {
|
interface KeyWithMeta {
|
||||||
id: string
|
id: string
|
||||||
@@ -482,6 +504,60 @@ const editingProviderPriority = ref<string | null>(null) // providerId
|
|||||||
// 调度模式状态
|
// 调度模式状态
|
||||||
const schedulingMode = ref<'fixed_order' | 'load_balance' | 'cache_affinity'>('cache_affinity')
|
const schedulingMode = ref<'fixed_order' | 'load_balance' | 'cache_affinity'>('cache_affinity')
|
||||||
|
|
||||||
|
// 余额数据缓存 {providerId: ActionResultResponse}
|
||||||
|
const balanceCache = ref<Record<string, ActionResultResponse>>({})
|
||||||
|
|
||||||
|
// 类型守卫函数
|
||||||
|
function isBalanceInfo(data: unknown): data is BalanceInfo {
|
||||||
|
return data !== null && typeof data === 'object' && 'total_available' in data
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 provider 的余额显示
|
||||||
|
function getProviderBalance(providerId: string): { available: number | null; currency: string } | null {
|
||||||
|
const result = balanceCache.value[providerId]
|
||||||
|
if (!result || result.status !== 'success' || !result.data) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (!isBalanceInfo(result.data)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
available: result.data.total_available,
|
||||||
|
currency: result.data.currency || 'USD'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化余额显示
|
||||||
|
function formatBalanceDisplay(providerId: string): string {
|
||||||
|
const balance = getProviderBalance(providerId)
|
||||||
|
if (!balance || balance.available == null) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const symbol = balance.currency === 'USD' ? '$' : balance.currency
|
||||||
|
return `${symbol}${balance.available.toFixed(2)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异步加载余额数据(使用批量接口)
|
||||||
|
async function loadBalances() {
|
||||||
|
try {
|
||||||
|
const opsProviderIds = sortedProviders.value
|
||||||
|
.filter(p => p.ops_configured)
|
||||||
|
.map(p => p.id)
|
||||||
|
if (opsProviderIds.length === 0) return
|
||||||
|
|
||||||
|
const results = await batchQueryBalance(opsProviderIds)
|
||||||
|
|
||||||
|
// 将成功的结果存入缓存
|
||||||
|
for (const [providerId, result] of Object.entries(results)) {
|
||||||
|
if (result.status === 'success') {
|
||||||
|
balanceCache.value[providerId] = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[loadBalances] 加载余额数据失败:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 可用的 API 格式
|
// 可用的 API 格式
|
||||||
const availableFormats = computed(() => {
|
const availableFormats = computed(() => {
|
||||||
return Object.keys(keysByFormat.value).sort()
|
return Object.keys(keysByFormat.value).sort()
|
||||||
@@ -499,6 +575,8 @@ watch(internalOpen, async (open) => {
|
|||||||
if (open) {
|
if (open) {
|
||||||
await loadCurrentPriorityMode()
|
await loadCurrentPriorityMode()
|
||||||
await loadKeysByFormat()
|
await loadKeysByFormat()
|
||||||
|
// 异步加载余额数据
|
||||||
|
loadBalances()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user