diff --git a/backend/cmd/server/VERSION b/backend/cmd/server/VERSION index fa91977d06..a793effa76 100644 --- a/backend/cmd/server/VERSION +++ b/backend/cmd/server/VERSION @@ -1 +1 @@ -0.1.93.23 +0.1.93.24 diff --git a/frontend/src/components/account/AccountCapacityCell.vue b/frontend/src/components/account/AccountCapacityCell.vue index 10374560a1..d3042f98ca 100644 --- a/frontend/src/components/account/AccountCapacityCell.vue +++ b/frontend/src/components/account/AccountCapacityCell.vue @@ -30,11 +30,6 @@ - - - - - @@ -44,7 +39,6 @@ import { useI18n } from 'vue-i18n' import type { Account } from '@/types' import CapacityBadge from '@/components/account/CapacityBadge.vue' import AffinityBadge from '@/components/account/AffinityBadge.vue' -import QuotaBadge from '@/components/account/QuotaBadge.vue' const props = defineProps<{ account: Account @@ -197,17 +191,6 @@ const affinityBuffer = computed((): number | null => { return null }) -// ====== 配额 ====== -const showDailyQuota = computed(() => - props.account.type === 'apikey' && props.account.quota_daily_limit != null && props.account.quota_daily_limit > 0 -) -const showWeeklyQuota = computed(() => - props.account.type === 'apikey' && props.account.quota_weekly_limit != null && props.account.quota_weekly_limit > 0 -) -const showTotalQuota = computed(() => - props.account.type === 'apikey' && props.account.quota_limit != null && props.account.quota_limit > 0 -) - const formatCost = (value: number | null | undefined) => { if (value === null || value === undefined) return '0' return value.toFixed(2) diff --git a/frontend/src/components/account/AccountUsageCell.vue b/frontend/src/components/account/AccountUsageCell.vue index cf684b670e..a696383990 100644 --- a/frontend/src/components/account/AccountUsageCell.vue +++ b/frontend/src/components/account/AccountUsageCell.vue @@ -334,6 +334,32 @@
+ +
+ + + +
-
@@ -822,6 +848,63 @@ const loadUsage = async () => { } } +// ===== API Key quota progress bars ===== + +interface QuotaBarInfo { + utilization: number + displayValue: string + resetsAt: string | null +} + +const fmtCost = (v: number) => v.toFixed(2) + +const makeQuotaBar = ( + used: number, + limit: number, + startKey?: string +): QuotaBarInfo => { + const utilization = limit > 0 ? (used / limit) * 100 : 0 + const displayValue = `${fmtCost(used)}/${fmtCost(limit)}` + 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, displayValue, 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(() => { loadUsage() })