diff --git a/CHANGELOG.md b/CHANGELOG.md index 80571b5..0199925 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,12 @@ Write each change in both `### English` and `### 中文` under `## Unreleased`. ### English +- Keep Qoder accounts routable when their base quota is exhausted but an available add-on or organization resource package still has credits, and show resource-package balance in the console + ### 中文 +- Qoder 主额度用尽但可用附加包或组织资源包仍有余额时继续参与路由,并在控制台展示资源包余额 + ## 0.4.3 - 2026-09-10 ### English diff --git a/frontend/src/api/types.ts b/frontend/src/api/types.ts index 3a59156..0ad4f08 100644 --- a/frontend/src/api/types.ts +++ b/frontend/src/api/types.ts @@ -8,7 +8,15 @@ export type AccountQuota = { has_add_on?: boolean add_on_used?: number add_on_total?: number + add_on_remaining?: number add_on_unit?: string + add_on_available?: boolean + has_resource_package?: boolean + resource_package_used?: number + resource_package_total?: number + resource_package_remaining?: number + resource_package_unit?: string + resource_package_available?: boolean fetched_at?: string } diff --git a/frontend/src/components/account/AccountCard.tsx b/frontend/src/components/account/AccountCard.tsx index eb96bf8..6da334e 100644 --- a/frontend/src/components/account/AccountCard.tsx +++ b/frontend/src/components/account/AccountCard.tsx @@ -292,6 +292,7 @@ export function AccountCard({ usedLabel={t('quotaUsed')} remainingLabel={t('quotaRemaining')} addOnLabel={t('quotaAddOn')} + resourcePackageLabel={t('quotaResourcePackage')} exceededLabel={t('quotaExceeded')} /> ) : {t('statsUnknown')}} diff --git a/frontend/src/components/account/QuotaMeter.tsx b/frontend/src/components/account/QuotaMeter.tsx index 7861cc4..91eb662 100644 --- a/frontend/src/components/account/QuotaMeter.tsx +++ b/frontend/src/components/account/QuotaMeter.tsx @@ -8,19 +8,23 @@ type Props = { usedLabel: string remainingLabel: string addOnLabel: string + resourcePackageLabel: string exceededLabel: string } -export function QuotaMeter({ quota, label, usedLabel, remainingLabel, addOnLabel, exceededLabel }: Props) { +export function QuotaMeter({ quota, label, usedLabel, remainingLabel, addOnLabel, resourcePackageLabel, exceededLabel }: Props) { const ratio = quotaUsedRatio(quota) const tone = quotaTone(quota) const color = tone === 'danger' ? 'danger' : tone === 'warn' ? 'warning' : 'success' const unit = quota.unit || 'credits' const used = `${formatQuotaAmount(quota.used)} / ${formatQuotaAmount(quota.total)} ${unit}` const remaining = `${formatQuotaAmount(quota.remaining)} ${unit}` - const addOn = quota.has_add_on + const addOn = quota.has_add_on && quota.add_on_available !== false ? `${addOnLabel} ${formatQuotaAmount(quota.add_on_used)} / ${formatQuotaAmount(quota.add_on_total)} ${quota.add_on_unit || 'credits'}` : '' + const resourcePackage = quota.has_resource_package && quota.resource_package_available !== false + ? `${resourcePackageLabel} ${remainingLabel} ${formatQuotaAmount(quota.resource_package_remaining)} ${quota.resource_package_unit || 'credits'}` + : '' return (