mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
fix(frontend): 合并 OAuth 状态展示并移除 Codex 积分信息
- providerKeyStatus: 合并 snapshot 与 legacy OAuth 状态,按严重程度取优并补全失效原因 - ProviderDetailDrawer: 移除 Codex 积分摘要与相关字段显示
This commit is contained in:
@@ -568,18 +568,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
v-if="getCodexCreditsSummary(getCodexQuotaDisplay(key))"
|
|
||||||
class="flex items-center justify-between text-[10px] mb-2"
|
|
||||||
>
|
|
||||||
<span class="text-muted-foreground">积分</span>
|
|
||||||
<span
|
|
||||||
class="font-medium"
|
|
||||||
:class="getCodexQuotaDisplay(key)?.has_credits === false ? 'text-red-600 dark:text-red-400' : 'text-foreground/80'"
|
|
||||||
>
|
|
||||||
{{ getCodexCreditsSummary(getCodexQuotaDisplay(key)) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<!-- 限额并排显示:Team/Plus/Enterprise 账号 2列, Free 账号 1列 -->
|
<!-- 限额并排显示:Team/Plus/Enterprise 账号 2列, Free 账号 1列 -->
|
||||||
<div
|
<div
|
||||||
class="grid gap-3"
|
class="grid gap-3"
|
||||||
@@ -1938,13 +1926,6 @@ function getCodexQuotaDisplay(key: EndpointAPIKey): CodexUpstreamMetadata | null
|
|||||||
display.secondary_window_minutes = secondaryWindow.window_minutes
|
display.secondary_window_minutes = secondaryWindow.window_minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof quota.credits?.has_credits === 'boolean') {
|
|
||||||
display.has_credits = quota.credits.has_credits
|
|
||||||
}
|
|
||||||
if (typeof quota.credits?.balance === 'number') {
|
|
||||||
display.credits_balance = quota.credits.balance
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(display).length > 0 ? display : null
|
return Object.keys(display).length > 0 ? display : null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1953,28 +1934,9 @@ function hasCodexQuotaDisplayData(key: EndpointAPIKey): boolean {
|
|||||||
return !!codex && (
|
return !!codex && (
|
||||||
codex.primary_used_percent !== undefined
|
codex.primary_used_percent !== undefined
|
||||||
|| codex.secondary_used_percent !== undefined
|
|| codex.secondary_used_percent !== undefined
|
||||||
|| codex.has_credits !== undefined
|
|
||||||
|| codex.credits_balance !== undefined
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCodexCreditsSummary(codex: CodexUpstreamMetadata | null | undefined): string | null {
|
|
||||||
if (!codex) return null
|
|
||||||
if (codex.has_credits === true && typeof codex.credits_balance === 'number') {
|
|
||||||
return `积分 ${codex.credits_balance.toFixed(2)}`
|
|
||||||
}
|
|
||||||
if (codex.has_credits === true) {
|
|
||||||
return '有积分'
|
|
||||||
}
|
|
||||||
if (codex.has_credits === false) {
|
|
||||||
return '无可用积分'
|
|
||||||
}
|
|
||||||
if (typeof codex.credits_balance === 'number') {
|
|
||||||
return `积分 ${codex.credits_balance.toFixed(2)}`
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
function getKiroQuotaDisplay(key: EndpointAPIKey): KiroUpstreamMetadata | null {
|
function getKiroQuotaDisplay(key: EndpointAPIKey): KiroUpstreamMetadata | null {
|
||||||
const quota = getQuotaSnapshotForProvider(key, 'kiro')
|
const quota = getQuotaSnapshotForProvider(key, 'kiro')
|
||||||
if (!quota) return null
|
if (!quota) return null
|
||||||
|
|||||||
@@ -62,6 +62,37 @@ describe('providerKeyStatus', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('prefers legacy oauth invalidation over a stale valid snapshot', () => {
|
||||||
|
const future = Math.floor(Date.now() / 1000) + 2 * 24 * 3600
|
||||||
|
const status = getOAuthStatusDisplay(
|
||||||
|
{
|
||||||
|
auth_type: 'oauth',
|
||||||
|
oauth_expires_at: future,
|
||||||
|
oauth_invalid_reason: '[REFRESH_FAILED] Token 续期失败 (401): refresh_token_reused',
|
||||||
|
status_snapshot: {
|
||||||
|
oauth: {
|
||||||
|
code: 'valid',
|
||||||
|
expires_at: future,
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
code: 'ok',
|
||||||
|
blocked: false,
|
||||||
|
},
|
||||||
|
quota: { code: 'ok', exhausted: false },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(status).toEqual({
|
||||||
|
text: '已失效',
|
||||||
|
isExpired: false,
|
||||||
|
isExpiringSoon: false,
|
||||||
|
isInvalid: true,
|
||||||
|
invalidReason: '[REFRESH_FAILED] Token 续期失败 (401): refresh_token_reused',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('falls back to countdown for account block without oauth invalidation', () => {
|
it('falls back to countdown for account block without oauth invalidation', () => {
|
||||||
const status = getOAuthStatusDisplay(
|
const status = getOAuthStatusDisplay(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -127,11 +127,44 @@ function getLegacyOAuthState(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getOAuthStatusSeverity(status: OAuthStatusInfo | null): number {
|
||||||
|
if (!status) return 0
|
||||||
|
if (status.isInvalid) return 3
|
||||||
|
if (status.isExpired) return 2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeOAuthStatusDisplay(
|
||||||
|
snapshotStatus: OAuthStatusInfo | null,
|
||||||
|
legacyStatus: OAuthStatusInfo | null,
|
||||||
|
): OAuthStatusInfo | null {
|
||||||
|
if (getOAuthStatusSeverity(legacyStatus) > getOAuthStatusSeverity(snapshotStatus)) {
|
||||||
|
return legacyStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
snapshotStatus?.isInvalid
|
||||||
|
&& !snapshotStatus.invalidReason
|
||||||
|
&& legacyStatus?.isInvalid
|
||||||
|
&& legacyStatus.invalidReason
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
...snapshotStatus,
|
||||||
|
invalidReason: legacyStatus.invalidReason,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return snapshotStatus ?? legacyStatus
|
||||||
|
}
|
||||||
|
|
||||||
export function getOAuthStatusDisplay(
|
export function getOAuthStatusDisplay(
|
||||||
input: ProviderKeyStatusCarrier,
|
input: ProviderKeyStatusCarrier,
|
||||||
tick: number,
|
tick: number,
|
||||||
): OAuthStatusInfo | null {
|
): OAuthStatusInfo | null {
|
||||||
return getSnapshotOAuthState(input, tick) ?? getLegacyOAuthState(input, tick)
|
return mergeOAuthStatusDisplay(
|
||||||
|
getSnapshotOAuthState(input, tick),
|
||||||
|
getLegacyOAuthState(input, tick),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOAuthStatusTitle(
|
export function getOAuthStatusTitle(
|
||||||
|
|||||||
Reference in New Issue
Block a user