feat(antigravity): 添加账户类型(tier)显示功能
This commit is contained in:
@@ -36,9 +36,30 @@ type LoadCodeAssistRequest struct {
|
|||||||
} `json:"metadata"`
|
} `json:"metadata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TierInfo 账户类型信息
|
||||||
|
type TierInfo struct {
|
||||||
|
ID string `json:"id"` // standard-tier, free-tier, g1-pro-tier, g1-ultra-tier
|
||||||
|
Name string `json:"name"` // 显示名称
|
||||||
|
Description string `json:"description"` // 描述
|
||||||
|
}
|
||||||
|
|
||||||
// LoadCodeAssistResponse loadCodeAssist 响应
|
// LoadCodeAssistResponse loadCodeAssist 响应
|
||||||
type LoadCodeAssistResponse struct {
|
type LoadCodeAssistResponse struct {
|
||||||
CloudAICompanionProject string `json:"cloudaicompanionProject"`
|
CloudAICompanionProject string `json:"cloudaicompanionProject"`
|
||||||
|
CurrentTier *TierInfo `json:"currentTier,omitempty"`
|
||||||
|
PaidTier *TierInfo `json:"paidTier,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTier 获取账户类型
|
||||||
|
// 优先返回 paidTier(付费订阅级别),否则返回 currentTier
|
||||||
|
func (r *LoadCodeAssistResponse) GetTier() string {
|
||||||
|
if r.PaidTier != nil && r.PaidTier.ID != "" {
|
||||||
|
return r.PaidTier.ID
|
||||||
|
}
|
||||||
|
if r.CurrentTier != nil {
|
||||||
|
return r.CurrentTier.ID
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client Antigravity API 客户端
|
// Client Antigravity API 客户端
|
||||||
|
|||||||
@@ -145,8 +145,15 @@ func (r *AntigravityQuotaRefresher) refreshAccountQuota(ctx context.Context, acc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用 API 获取配额
|
|
||||||
client := antigravity.NewClient(proxyURL)
|
client := antigravity.NewClient(proxyURL)
|
||||||
|
|
||||||
|
// 获取账户类型(tier)
|
||||||
|
loadResp, _ := client.LoadCodeAssist(ctx, accessToken)
|
||||||
|
if loadResp != nil {
|
||||||
|
r.updateAccountTier(account, loadResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用 API 获取配额
|
||||||
modelsResp, err := client.FetchAvailableModels(ctx, accessToken, projectID)
|
modelsResp, err := client.FetchAvailableModels(ctx, accessToken, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -170,6 +177,18 @@ func (r *AntigravityQuotaRefresher) isTokenExpired(account *Account) bool {
|
|||||||
return time.Now().Add(5 * time.Minute).After(*expiresAt)
|
return time.Now().Add(5 * time.Minute).After(*expiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateAccountTier 更新账户类型信息
|
||||||
|
func (r *AntigravityQuotaRefresher) updateAccountTier(account *Account, loadResp *antigravity.LoadCodeAssistResponse) {
|
||||||
|
if account.Extra == nil {
|
||||||
|
account.Extra = make(map[string]any)
|
||||||
|
}
|
||||||
|
|
||||||
|
tier := loadResp.GetTier()
|
||||||
|
if tier != "" {
|
||||||
|
account.Extra["tier"] = tier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// updateAccountQuota 更新账户的配额信息
|
// updateAccountQuota 更新账户的配额信息
|
||||||
func (r *AntigravityQuotaRefresher) updateAccountQuota(account *Account, modelsResp *antigravity.FetchAvailableModelsResponse) {
|
func (r *AntigravityQuotaRefresher) updateAccountQuota(account *Account, modelsResp *antigravity.FetchAvailableModelsResponse) {
|
||||||
if account.Extra == nil {
|
if account.Extra == nil {
|
||||||
|
|||||||
@@ -95,6 +95,18 @@
|
|||||||
|
|
||||||
<!-- Antigravity OAuth accounts: show quota from extra field -->
|
<!-- Antigravity OAuth accounts: show quota from extra field -->
|
||||||
<template v-else-if="account.platform === 'antigravity' && account.type === 'oauth'">
|
<template v-else-if="account.platform === 'antigravity' && account.type === 'oauth'">
|
||||||
|
<!-- 账户类型徽章 -->
|
||||||
|
<div v-if="antigravityTierLabel" class="mb-1">
|
||||||
|
<span
|
||||||
|
:class="[
|
||||||
|
'inline-block rounded px-1.5 py-0.5 text-[10px] font-medium',
|
||||||
|
antigravityTierClass
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
{{ antigravityTierLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="hasAntigravityQuota" class="space-y-1">
|
<div v-if="hasAntigravityQuota" class="space-y-1">
|
||||||
<!-- Gemini 3 Pro -->
|
<!-- Gemini 3 Pro -->
|
||||||
<UsageProgressBar
|
<UsageProgressBar
|
||||||
@@ -391,6 +403,41 @@ const antigravityClaude45Usage = computed(() =>
|
|||||||
getAntigravityUsage(['claude-sonnet-4-5', 'claude-opus-4-5-thinking'])
|
getAntigravityUsage(['claude-sonnet-4-5', 'claude-opus-4-5-thinking'])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Antigravity 账户类型
|
||||||
|
const antigravityTier = computed(() => {
|
||||||
|
const extra = props.account.extra as Record<string, unknown> | undefined
|
||||||
|
if (!extra || typeof extra.tier !== 'string') return null
|
||||||
|
return extra.tier as string
|
||||||
|
})
|
||||||
|
|
||||||
|
// 账户类型显示标签
|
||||||
|
const antigravityTierLabel = computed(() => {
|
||||||
|
switch (antigravityTier.value) {
|
||||||
|
case 'free-tier':
|
||||||
|
return t('admin.accounts.tier.free')
|
||||||
|
case 'g1-pro-tier':
|
||||||
|
return t('admin.accounts.tier.pro')
|
||||||
|
case 'g1-ultra-tier':
|
||||||
|
return t('admin.accounts.tier.ultra')
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 账户类型徽章样式
|
||||||
|
const antigravityTierClass = computed(() => {
|
||||||
|
switch (antigravityTier.value) {
|
||||||
|
case 'free-tier':
|
||||||
|
return 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-300'
|
||||||
|
case 'g1-pro-tier':
|
||||||
|
return 'bg-blue-100 text-blue-600 dark:bg-blue-900/40 dark:text-blue-300'
|
||||||
|
case 'g1-ultra-tier':
|
||||||
|
return 'bg-purple-100 text-purple-600 dark:bg-purple-900/40 dark:text-purple-300'
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const loadUsage = async () => {
|
const loadUsage = async () => {
|
||||||
// Fetch usage for Anthropic OAuth and Setup Token accounts
|
// Fetch usage for Anthropic OAuth and Setup Token accounts
|
||||||
// OpenAI usage comes from account.extra field (updated during forwarding)
|
// OpenAI usage comes from account.extra field (updated during forwarding)
|
||||||
|
|||||||
@@ -1162,6 +1162,11 @@ export default {
|
|||||||
gemini3Flash: 'G3F',
|
gemini3Flash: 'G3F',
|
||||||
gemini3Image: 'G3I',
|
gemini3Image: 'G3I',
|
||||||
claude45: 'C4.5'
|
claude45: 'C4.5'
|
||||||
|
},
|
||||||
|
tier: {
|
||||||
|
free: 'Free',
|
||||||
|
pro: 'Pro',
|
||||||
|
ultra: 'Ultra'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -972,6 +972,11 @@ export default {
|
|||||||
gemini3Image: 'G3I',
|
gemini3Image: 'G3I',
|
||||||
claude45: 'C4.5'
|
claude45: 'C4.5'
|
||||||
},
|
},
|
||||||
|
tier: {
|
||||||
|
free: 'Free',
|
||||||
|
pro: 'Pro',
|
||||||
|
ultra: 'Ultra'
|
||||||
|
},
|
||||||
form: {
|
form: {
|
||||||
nameLabel: '账号名称',
|
nameLabel: '账号名称',
|
||||||
namePlaceholder: '请输入账号名称',
|
namePlaceholder: '请输入账号名称',
|
||||||
|
|||||||
Reference in New Issue
Block a user