feat: Grok 用量条补齐本站 24h/7d/30d 聚合

把已有的本地窗口统计接到 Free 24h 与付费 7d/30d 进度条,避免只显示官方百分比。
This commit is contained in:
IanShaw027
2026-08-18 14:50:57 +08:00
parent 938f1868ae
commit 269fbcac0e
2 changed files with 165 additions and 2 deletions
@@ -365,6 +365,7 @@
label="24h"
:title="t('admin.accounts.usageWindow.grokFreeQuota24hHint', { limit: formatCompactNumber(grokFreeTokenBar.limit) })"
:utilization="grokFreeTokenBar.utilization"
:window-stats="grokFreeQuotaUsage"
:show-now-when-idle="true"
color="emerald"
/>
@@ -378,6 +379,7 @@
label="7d"
:utilization="grokWeeklyBillingBar.utilization"
:resets-at="grokWeeklyBillingBar.resetsAt"
:window-stats="grokWeeklyBillingBar.windowStats"
:show-now-when-idle="true"
color="indigo"
/>
@@ -386,6 +388,7 @@
label="30d"
:utilization="grokMonthlyBillingBar.utilization"
:resets-at="grokMonthlyBillingBar.resetsAt"
:window-stats="grokMonthlyBillingBar.windowStats"
:show-now-when-idle="true"
color="indigo"
/>
@@ -1108,9 +1111,16 @@ const geminiUsageBars = computed(() => {
interface GrokQuotaBarInfo {
utilization: number
resetsAt: string | null
windowStats?: WindowStats | null
}
const grokBilling = computed(() => usageInfo.value?.grok_billing || null)
const grokLocalUsage7d = computed(() => (
usageInfo.value?.grok_local_usage_7d || usageInfo.value?.seven_day?.window_stats || null
))
const grokLocalUsageMonthly = computed(() => (
usageInfo.value?.grok_local_usage_monthly || usageInfo.value?.thirty_day?.window_stats || null
))
const grokWeeklyBillingBar = computed((): GrokQuotaBarInfo | null => {
const billing = grokBilling.value
if (billing?.period_type?.toLowerCase() !== 'weekly' || billing.usage_percent == null) {
@@ -1118,7 +1128,8 @@ const grokWeeklyBillingBar = computed((): GrokQuotaBarInfo | null => {
}
return {
utilization: Math.min(100, Math.max(0, billing.usage_percent)),
resetsAt: billing.period_end || null
resetsAt: billing.period_end || null,
windowStats: grokLocalUsage7d.value
}
})
// Monthly used/limit % from billing probe (used_percent or derived from cents).
@@ -1142,7 +1153,8 @@ const grokMonthlyBillingBar = computed((): GrokQuotaBarInfo | null => {
}
return {
utilization: Math.min(100, Math.max(0, utilization)),
resetsAt: billing.billing_period_end || billing.period_end || null
resetsAt: billing.billing_period_end || billing.period_end || null,
windowStats: grokLocalUsageMonthly.value
}
})
const formatGrokMoney = (value?: number | null) => {
@@ -1017,6 +1017,157 @@ describe('AccountUsageCell', () => {
expect(wrapper.text()).toContain('24h|100')
})
it('Grok Free 24h bar shows rolling local usage chips', async () => {
getUsage.mockResolvedValue({
grok_free_token_limit: 1_000_000,
grok_billing: { period_type: 'weekly', usage_percent: null, plan: '' },
grok_local_usage: {
requests: 2,
tokens: 250_000,
cost: 0,
standard_cost: 0
},
grok_local_usage_24h: {
requests: 12,
tokens: 750_000,
cost: 0.12,
standard_cost: 0.12,
user_cost: 0.04
}
})
const wrapper = mount(AccountUsageCell, {
props: {
account: makeAccount({ id: 4410, platform: 'grok', type: 'oauth', extra: {} })
},
global: {
stubs: {
UsageProgressBar: {
props: ['label', 'utilization', 'windowStats'],
template: '<div class="usage-bar">{{ label }}|{{ utilization }}|{{ windowStats?.tokens }}</div>'
},
AccountQuotaInfo: true
}
}
})
await flushPromises()
expect(wrapper.text()).toContain('24h|75|750000')
expect(wrapper.text()).not.toContain('|250000')
expect(wrapper.text()).not.toContain('7d|')
})
it('Grok SuperGrok and Heavy bars show period-aligned local 7d and 30d usage', async () => {
getUsage.mockResolvedValue({
subscription_tier: 'SuperGrok Heavy',
grok_billing: {
period_type: 'weekly',
usage_percent: 37,
used_percent: 12,
monthly_limit_cents: 150_000,
period_end: '2026-07-16T03:25:00Z',
billing_period_end: '2026-08-01T00:00:00Z',
plan: 'SuperGrok Heavy'
},
grok_local_usage: {
requests: 1,
tokens: 99,
cost: 0,
standard_cost: 0
},
grok_local_usage_24h: {
requests: 2,
tokens: 100,
cost: 0,
standard_cost: 0
},
grok_local_usage_7d: {
requests: 8,
tokens: 2_200_000,
cost: 4.42,
standard_cost: 4.42
},
grok_local_usage_monthly: {
requests: 20,
tokens: 8_000_000,
cost: 18.5,
standard_cost: 18.5
}
})
const wrapper = mount(AccountUsageCell, {
props: {
account: makeAccount({ id: 4411, platform: 'grok', type: 'oauth', extra: {} })
},
global: {
stubs: {
UsageProgressBar: {
props: ['label', 'utilization', 'windowStats'],
template: '<div class="usage-bar">{{ label }}|{{ utilization }}|{{ windowStats?.tokens }}</div>'
},
AccountQuotaInfo: true
}
}
})
await flushPromises()
expect(wrapper.text()).toContain('7d|37|2200000')
expect(wrapper.text()).toContain('30d|12|8000000')
expect(wrapper.text()).not.toContain('|99')
expect(wrapper.text()).not.toContain('|100')
expect(wrapper.text()).not.toContain('24h|')
})
it('Grok paid bars fall back to official seven_day and thirty_day window_stats', async () => {
getUsage.mockResolvedValue({
subscription_tier: 'SuperGrok',
grok_billing: {
period_type: 'weekly',
usage_percent: 20,
used_percent: 8,
monthly_limit_cents: 25_000,
plan: 'SuperGrok'
},
seven_day: {
utilization: 20,
window_stats: {
requests: 6,
tokens: 1_500_000,
cost: 3.1,
standard_cost: 3.1
}
},
thirty_day: {
utilization: 8,
window_stats: {
requests: 14,
tokens: 4_400_000,
cost: 9.2,
standard_cost: 9.2
}
}
})
const wrapper = mount(AccountUsageCell, {
props: {
account: makeAccount({ id: 4412, platform: 'grok', type: 'oauth', extra: {} })
},
global: {
stubs: {
UsageProgressBar: {
props: ['label', 'utilization', 'windowStats'],
template: '<div class="usage-bar">{{ label }}|{{ utilization }}|{{ windowStats?.tokens }}</div>'
},
AccountQuotaInfo: true
}
}
})
await flushPromises()
expect(wrapper.text()).toContain('7d|20|1500000')
expect(wrapper.text()).toContain('30d|8|4400000')
})
it('Key 账号在 today stats loading 时显示骨架屏', async () => {
const wrapper = mount(AccountUsageCell, {
props: {