mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
feat: Codex account_name 透传并优化池列表 OAuth 标识与额度重置倒计时展示
(cherry picked from commit 1b9176fc4a)
This commit is contained in:
@@ -104,6 +104,7 @@ export interface PoolKeyDetail {
|
||||
oauth_plan_type?: string | null
|
||||
oauth_account_id?: string | null
|
||||
oauth_account_user_id?: string | null
|
||||
oauth_account_name?: string | null
|
||||
oauth_organizations?: OAuthOrganizationInfo[] | null
|
||||
quota_updated_at?: number | null
|
||||
health_score?: number
|
||||
|
||||
@@ -288,6 +288,7 @@ export interface EndpointAPIKey {
|
||||
oauth_plan_type?: string | null // Codex 订阅类型: plus/free/team/enterprise
|
||||
oauth_account_id?: string | null // Codex ChatGPT 账号 ID
|
||||
oauth_account_user_id?: string | null // Codex ChatGPT account-user 联合 ID
|
||||
oauth_account_name?: string | null
|
||||
oauth_organizations?: OAuthOrganizationInfo[] | null // OAuth 关联组织/工作区摘要
|
||||
oauth_invalid_at?: number | null // OAuth Token 失效时间(Unix 时间戳)
|
||||
oauth_invalid_reason?: string | null // OAuth Token 失效原因
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import type { OAuthOrganizationInfo } from '@/api/endpoints/types/provider'
|
||||
|
||||
type OAuthIdentityDisplayValue = {
|
||||
oauth_account_name?: string | null
|
||||
oauth_organizations?: OAuthOrganizationInfo[] | null
|
||||
} | null | undefined
|
||||
|
||||
function formatOAuthIdentityShort(
|
||||
value: string | null | undefined,
|
||||
head = 8,
|
||||
@@ -11,24 +16,44 @@ function formatOAuthIdentityShort(
|
||||
return `${normalized.slice(0, head)}...${normalized.slice(-tail)}`
|
||||
}
|
||||
|
||||
function getPrimaryOAuthOrganizationId(
|
||||
value: { oauth_organizations?: OAuthOrganizationInfo[] | null } | null | undefined,
|
||||
): string | null {
|
||||
const organizations = Array.isArray(value?.oauth_organizations) ? value.oauth_organizations : []
|
||||
const defaultOrg = organizations.find(
|
||||
(org) => org?.is_default && typeof org?.id === 'string' && org.id.trim(),
|
||||
)
|
||||
if (defaultOrg?.id) return defaultOrg.id.trim()
|
||||
const firstWithId = organizations.find(
|
||||
(org) => typeof org?.id === 'string' && org.id.trim(),
|
||||
)
|
||||
return firstWithId?.id?.trim() || null
|
||||
function getPrimaryOAuthOrganization(
|
||||
value: OAuthIdentityDisplayValue,
|
||||
): { id: string; title: string } | null {
|
||||
const organizations: OAuthOrganizationInfo[] = Array.isArray(value?.oauth_organizations)
|
||||
? value.oauth_organizations
|
||||
: []
|
||||
let firstWithId: OAuthOrganizationInfo | null = null
|
||||
|
||||
for (let index = 0; index < organizations.length; index += 1) {
|
||||
const org = organizations[index]
|
||||
if (typeof org?.id !== 'string' || !org.id.trim()) continue
|
||||
if (!firstWithId) firstWithId = org
|
||||
if (org.is_default) {
|
||||
firstWithId = org
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!firstWithId?.id) return null
|
||||
|
||||
return {
|
||||
id: firstWithId.id.trim(),
|
||||
title: typeof firstWithId.title === 'string' ? firstWithId.title.trim() : '',
|
||||
}
|
||||
}
|
||||
|
||||
export function getOAuthOrgBadge(
|
||||
value: { oauth_organizations?: OAuthOrganizationInfo[] | null } | null | undefined,
|
||||
value: OAuthIdentityDisplayValue,
|
||||
): { id: string; label: string } | null {
|
||||
const id = getPrimaryOAuthOrganizationId(value)
|
||||
if (!id) return null
|
||||
return { id, label: formatOAuthIdentityShort(id) }
|
||||
const org = getPrimaryOAuthOrganization(value)
|
||||
if (!org) return null
|
||||
|
||||
const accountName = typeof value?.oauth_account_name === 'string'
|
||||
? value.oauth_account_name.trim()
|
||||
: ''
|
||||
|
||||
return {
|
||||
id: org.id,
|
||||
label: accountName || org.title || formatOAuthIdentityShort(org.id),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@
|
||||
:key="`${key.key_id}-quota-${idx}`"
|
||||
class="w-full"
|
||||
>
|
||||
<div class="min-h-4 grid grid-cols-[20px_minmax(0,1fr)_42px] items-center gap-1 text-[10px] leading-tight">
|
||||
<div class="min-h-4 grid grid-cols-[20px_minmax(0,1fr)_80px] items-center gap-1 text-[10px] leading-tight">
|
||||
<span
|
||||
class="text-muted-foreground whitespace-nowrap text-right tabular-nums"
|
||||
:title="getQuotaProgressTooltip(item)"
|
||||
@@ -530,12 +530,21 @@
|
||||
:style="{ width: `${item.remainingPercent}%` }"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="tabular-nums text-right whitespace-nowrap"
|
||||
:class="getQuotaRemainingClassByRemaining(item.remainingPercent)"
|
||||
>
|
||||
{{ item.remainingPercent.toFixed(1) }}%
|
||||
</span>
|
||||
<div class="flex flex-col items-end justify-center gap-0.5 text-right leading-tight">
|
||||
<span
|
||||
class="tabular-nums whitespace-nowrap"
|
||||
:class="getQuotaRemainingClassByRemaining(item.remainingPercent)"
|
||||
>
|
||||
{{ item.remainingPercent.toFixed(1) }}%
|
||||
</span>
|
||||
<span
|
||||
v-if="getQuotaProgressCountdownText(item)"
|
||||
class="text-[9px] text-muted-foreground whitespace-nowrap"
|
||||
:title="getQuotaProgressTooltip(item)"
|
||||
>
|
||||
{{ getQuotaProgressCountdownText(item) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -971,7 +980,7 @@
|
||||
:key="`${key.key_id}-quota-mobile-${idx}`"
|
||||
class="w-full"
|
||||
>
|
||||
<div class="grid grid-cols-[20px_minmax(0,1fr)_42px] items-center gap-1 text-[10px] leading-tight">
|
||||
<div class="grid grid-cols-[20px_minmax(0,1fr)_80px] items-center gap-1 text-[10px] leading-tight">
|
||||
<span
|
||||
class="text-muted-foreground whitespace-nowrap text-right tabular-nums"
|
||||
:title="getQuotaProgressTooltip(item)"
|
||||
@@ -985,12 +994,21 @@
|
||||
:style="{ width: `${item.remainingPercent}%` }"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="tabular-nums text-right whitespace-nowrap"
|
||||
:class="getQuotaRemainingClassByRemaining(item.remainingPercent)"
|
||||
>
|
||||
{{ item.remainingPercent.toFixed(1) }}%
|
||||
</span>
|
||||
<div class="flex flex-col items-end justify-center gap-0.5 text-right leading-tight">
|
||||
<span
|
||||
class="tabular-nums whitespace-nowrap"
|
||||
:class="getQuotaRemainingClassByRemaining(item.remainingPercent)"
|
||||
>
|
||||
{{ item.remainingPercent.toFixed(1) }}%
|
||||
</span>
|
||||
<span
|
||||
v-if="getQuotaProgressCountdownText(item)"
|
||||
class="text-[9px] text-muted-foreground whitespace-nowrap"
|
||||
:title="getQuotaProgressTooltip(item)"
|
||||
>
|
||||
{{ getQuotaProgressCountdownText(item) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1743,6 +1761,7 @@ function toEndpointApiKey(key: PoolKeyDetail): EndpointAPIKey {
|
||||
oauth_plan_type: key.oauth_plan_type ?? null,
|
||||
oauth_account_id: key.oauth_account_id ?? null,
|
||||
oauth_account_user_id: key.oauth_account_user_id ?? null,
|
||||
oauth_account_name: key.oauth_account_name ?? null,
|
||||
oauth_organizations: key.oauth_organizations ?? [],
|
||||
oauth_invalid_at: key.oauth_invalid_at ?? null,
|
||||
oauth_invalid_reason: key.oauth_invalid_reason ?? null,
|
||||
|
||||
Reference in New Issue
Block a user