From 4cd6d864260edd8739b6c0b6fd3faa8c3aef9ff7 Mon Sep 17 00:00:00 2001 From: erio Date: Sun, 8 Mar 2026 21:35:26 +0800 Subject: [PATCH] feat(frontend): add API Key quota progress bars to usage window column Display daily/weekly/total quota utilization as progress bars in the usage window column for API Key accounts, providing visual feedback consistent with other account types (OAuth/Gemini). - Daily quota: "1d" label with reset countdown - Weekly quota: "7d" label with reset countdown - Total quota: "total" label (no reset) --- .../components/account/AccountUsageCell.vue | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/frontend/src/components/account/AccountUsageCell.vue b/frontend/src/components/account/AccountUsageCell.vue index 0026920d..f5cab570 100644 --- a/frontend/src/components/account/AccountUsageCell.vue +++ b/frontend/src/components/account/AccountUsageCell.vue @@ -333,6 +333,29 @@
+ +
+ + + +
-
@@ -809,6 +832,59 @@ const loadUsage = async () => { } } +// ===== API Key quota progress bars ===== + +interface QuotaBarInfo { + utilization: number + resetsAt: string | null +} + +const makeQuotaBar = ( + used: number, + limit: number, + startKey?: string +): QuotaBarInfo => { + const utilization = limit > 0 ? (used / limit) * 100 : 0 + let resetsAt: string | null = null + if (startKey) { + const extra = props.account.extra as Record | undefined + const startStr = extra?.[startKey] as string | undefined + if (startStr) { + const startDate = new Date(startStr) + const periodMs = startKey.includes('daily') ? 24 * 60 * 60 * 1000 : 7 * 24 * 60 * 60 * 1000 + resetsAt = new Date(startDate.getTime() + periodMs).toISOString() + } + } + return { utilization, resetsAt } +} + +const hasApiKeyQuota = computed(() => { + if (props.account.type !== 'apikey') return false + return ( + (props.account.quota_daily_limit ?? 0) > 0 || + (props.account.quota_weekly_limit ?? 0) > 0 || + (props.account.quota_limit ?? 0) > 0 + ) +}) + +const quotaDailyBar = computed((): QuotaBarInfo | null => { + const limit = props.account.quota_daily_limit ?? 0 + if (limit <= 0) return null + return makeQuotaBar(props.account.quota_daily_used ?? 0, limit, 'quota_daily_start') +}) + +const quotaWeeklyBar = computed((): QuotaBarInfo | null => { + const limit = props.account.quota_weekly_limit ?? 0 + if (limit <= 0) return null + return makeQuotaBar(props.account.quota_weekly_used ?? 0, limit, 'quota_weekly_start') +}) + +const quotaTotalBar = computed((): QuotaBarInfo | null => { + const limit = props.account.quota_limit ?? 0 + if (limit <= 0) return null + return makeQuotaBar(props.account.quota_used ?? 0, limit) +}) + onMounted(() => { if (!shouldAutoLoadUsageOnMount.value) return loadUsage()