feat: OpenAI OAuth账号显示Codex使用量
从响应头提取x-codex-*使用量信息并保存到账号Extra字段, 前端账号列表展示5h/7d窗口的使用进度条。
This commit is contained in:
@@ -68,7 +68,31 @@
|
||||
<SetupTokenTimeWindow :account="account" />
|
||||
</template>
|
||||
|
||||
<!-- OpenAI accounts: no usage window API, show dash -->
|
||||
<!-- OpenAI OAuth accounts: show Codex usage from extra field -->
|
||||
<template v-else-if="account.platform === 'openai' && account.type === 'oauth'">
|
||||
<div v-if="hasCodexUsage" class="space-y-1">
|
||||
<!-- 5h Window (Secondary) -->
|
||||
<UsageProgressBar
|
||||
v-if="codexSecondaryUsedPercent !== null"
|
||||
label="5h"
|
||||
:utilization="codexSecondaryUsedPercent"
|
||||
:resets-at="codexSecondaryResetAt"
|
||||
color="indigo"
|
||||
/>
|
||||
|
||||
<!-- Weekly Window (Primary) -->
|
||||
<UsageProgressBar
|
||||
v-if="codexPrimaryUsedPercent !== null"
|
||||
label="7d"
|
||||
:utilization="codexPrimaryUsedPercent"
|
||||
:resets-at="codexPrimaryResetAt"
|
||||
color="emerald"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="text-xs text-gray-400">-</div>
|
||||
</template>
|
||||
|
||||
<!-- Other accounts: no usage window -->
|
||||
<template v-else>
|
||||
<div class="text-xs text-gray-400">-</div>
|
||||
</template>
|
||||
@@ -100,9 +124,44 @@ const showUsageWindows = computed(() =>
|
||||
props.account.type === 'oauth' || props.account.type === 'setup-token'
|
||||
)
|
||||
|
||||
// OpenAI Codex usage computed properties
|
||||
const hasCodexUsage = computed(() => {
|
||||
const extra = props.account.extra
|
||||
return extra && (
|
||||
extra.codex_primary_used_percent !== undefined ||
|
||||
extra.codex_secondary_used_percent !== undefined
|
||||
)
|
||||
})
|
||||
|
||||
const codexPrimaryUsedPercent = computed(() => {
|
||||
const extra = props.account.extra
|
||||
if (!extra || extra.codex_primary_used_percent === undefined) return null
|
||||
return extra.codex_primary_used_percent
|
||||
})
|
||||
|
||||
const codexSecondaryUsedPercent = computed(() => {
|
||||
const extra = props.account.extra
|
||||
if (!extra || extra.codex_secondary_used_percent === undefined) return null
|
||||
return extra.codex_secondary_used_percent
|
||||
})
|
||||
|
||||
const codexPrimaryResetAt = computed(() => {
|
||||
const extra = props.account.extra
|
||||
if (!extra || extra.codex_primary_reset_after_seconds === undefined) return null
|
||||
const resetTime = new Date(Date.now() + extra.codex_primary_reset_after_seconds * 1000)
|
||||
return resetTime.toISOString()
|
||||
})
|
||||
|
||||
const codexSecondaryResetAt = computed(() => {
|
||||
const extra = props.account.extra
|
||||
if (!extra || extra.codex_secondary_reset_after_seconds === undefined) return null
|
||||
const resetTime = new Date(Date.now() + extra.codex_secondary_reset_after_seconds * 1000)
|
||||
return resetTime.toISOString()
|
||||
})
|
||||
|
||||
const loadUsage = async () => {
|
||||
// Only fetch usage for Anthropic OAuth accounts
|
||||
// OpenAI doesn't have a usage window API - usage is updated from response headers during forwarding
|
||||
// OpenAI usage comes from account.extra field (updated during forwarding)
|
||||
if (props.account.platform !== 'anthropic' || props.account.type !== 'oauth') return
|
||||
|
||||
loading.value = true
|
||||
|
||||
Reference in New Issue
Block a user