mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-02 22:42:14 +08:00
feat: add today-stats and manual refresh token propagation to usage cells
- Pass todayStats/todayStatsLoading to AccountUsageCell for key accounts - Propagate usageManualRefreshToken to force usage reload on explicit refresh - Refresh today stats when toggling usage/today_stats columns visible
This commit is contained in:
@@ -203,7 +203,12 @@
|
||||
<AccountGroupsCell :groups="row.groups" :max-display="4" />
|
||||
</template>
|
||||
<template #cell-usage="{ row }">
|
||||
<AccountUsageCell :account="row" />
|
||||
<AccountUsageCell
|
||||
:account="row"
|
||||
:today-stats="todayStatsByAccountId[String(row.id)] ?? null"
|
||||
:today-stats-loading="todayStatsLoading"
|
||||
:manual-refresh-token="usageManualRefreshToken"
|
||||
/>
|
||||
</template>
|
||||
<template #cell-proxy="{ row }">
|
||||
<div v-if="row.proxy" class="flex items-center gap-2">
|
||||
@@ -323,13 +328,13 @@ import Icon from '@/components/icons/Icon.vue'
|
||||
import ErrorPassthroughRulesModal from '@/components/admin/ErrorPassthroughRulesModal.vue'
|
||||
import { buildOpenAIUsageRefreshKey } from '@/utils/accountUsageRefresh'
|
||||
import { formatDateTime, formatRelativeTime } from '@/utils/format'
|
||||
import type { Account, AccountPlatform, AccountType, Proxy, AdminGroup, WindowStats, ClaudeModel } from '@/types'
|
||||
import type { Account, AccountPlatform, AccountType, Proxy as AccountProxy, AdminGroup, WindowStats, ClaudeModel } from '@/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
const appStore = useAppStore()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const proxies = ref<Proxy[]>([])
|
||||
const proxies = ref<AccountProxy[]>([])
|
||||
const groups = ref<AdminGroup[]>([])
|
||||
const accountTableRef = ref<HTMLElement | null>(null)
|
||||
const selPlatforms = computed<AccountPlatform[]>(() => {
|
||||
@@ -402,6 +407,7 @@ const todayStatsLoading = ref(false)
|
||||
const todayStatsError = ref<string | null>(null)
|
||||
const todayStatsReqSeq = ref(0)
|
||||
const pendingTodayStatsRefresh = ref(false)
|
||||
const usageManualRefreshToken = ref(0)
|
||||
|
||||
const buildDefaultTodayStats = (): WindowStats => ({
|
||||
requests: 0,
|
||||
@@ -412,7 +418,11 @@ const buildDefaultTodayStats = (): WindowStats => ({
|
||||
})
|
||||
|
||||
const refreshTodayStatsBatch = async () => {
|
||||
if (hiddenColumns.has('today_stats')) {
|
||||
// Why this checks both columns:
|
||||
// - today_stats column shows dedicated today's metrics.
|
||||
// - usage column also embeds today's stats for Key/Bedrock rows.
|
||||
// So we only skip fetching when BOTH columns are hidden.
|
||||
if (hiddenColumns.has('today_stats') && hiddenColumns.has('usage')) {
|
||||
todayStatsLoading.value = false
|
||||
todayStatsError.value = null
|
||||
return
|
||||
@@ -464,13 +474,19 @@ const loadSavedColumns = () => {
|
||||
const saved = localStorage.getItem(HIDDEN_COLUMNS_KEY)
|
||||
if (saved) {
|
||||
const parsed = JSON.parse(saved) as string[]
|
||||
parsed.forEach(key => hiddenColumns.add(key))
|
||||
parsed.forEach(key => {
|
||||
hiddenColumns.add(key)
|
||||
})
|
||||
} else {
|
||||
DEFAULT_HIDDEN_COLUMNS.forEach(key => hiddenColumns.add(key))
|
||||
DEFAULT_HIDDEN_COLUMNS.forEach(key => {
|
||||
hiddenColumns.add(key)
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load saved columns:', e)
|
||||
DEFAULT_HIDDEN_COLUMNS.forEach(key => hiddenColumns.add(key))
|
||||
DEFAULT_HIDDEN_COLUMNS.forEach(key => {
|
||||
hiddenColumns.add(key)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,7 +560,7 @@ const toggleColumn = (key: string) => {
|
||||
hiddenColumns.add(key)
|
||||
}
|
||||
saveColumnsToStorage()
|
||||
if (key === 'today_stats' && wasHidden) {
|
||||
if ((key === 'today_stats' || key === 'usage') && wasHidden) {
|
||||
refreshTodayStatsBatch().catch((error) => {
|
||||
console.error('Failed to load account today stats after showing column:', error)
|
||||
})
|
||||
@@ -768,11 +784,15 @@ const refreshAccountsIncrementally = async () => {
|
||||
|
||||
const handleManualRefresh = async () => {
|
||||
await load()
|
||||
// Force usage cells to refetch /usage on explicit user refresh.
|
||||
usageManualRefreshToken.value += 1
|
||||
}
|
||||
|
||||
const syncPendingListChanges = async () => {
|
||||
hasPendingListSync.value = false
|
||||
await load()
|
||||
// Keep behavior consistent with manual refresh.
|
||||
usageManualRefreshToken.value += 1
|
||||
}
|
||||
|
||||
const { pause: pauseAutoRefresh, resume: resumeAutoRefresh } = useIntervalFn(
|
||||
@@ -888,7 +908,8 @@ const openMenu = (a: Account, e: MouseEvent) => {
|
||||
const viewportWidth = window.innerWidth
|
||||
const viewportHeight = window.innerHeight
|
||||
|
||||
let left, top
|
||||
let left: number
|
||||
let top: number
|
||||
|
||||
if (viewportWidth < 768) {
|
||||
// 居中显示,水平位置
|
||||
|
||||
Reference in New Issue
Block a user