mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-03 06:52:13 +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" />
|
<AccountGroupsCell :groups="row.groups" :max-display="4" />
|
||||||
</template>
|
</template>
|
||||||
<template #cell-usage="{ row }">
|
<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>
|
||||||
<template #cell-proxy="{ row }">
|
<template #cell-proxy="{ row }">
|
||||||
<div v-if="row.proxy" class="flex items-center gap-2">
|
<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 ErrorPassthroughRulesModal from '@/components/admin/ErrorPassthroughRulesModal.vue'
|
||||||
import { buildOpenAIUsageRefreshKey } from '@/utils/accountUsageRefresh'
|
import { buildOpenAIUsageRefreshKey } from '@/utils/accountUsageRefresh'
|
||||||
import { formatDateTime, formatRelativeTime } from '@/utils/format'
|
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 { t } = useI18n()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const proxies = ref<Proxy[]>([])
|
const proxies = ref<AccountProxy[]>([])
|
||||||
const groups = ref<AdminGroup[]>([])
|
const groups = ref<AdminGroup[]>([])
|
||||||
const accountTableRef = ref<HTMLElement | null>(null)
|
const accountTableRef = ref<HTMLElement | null>(null)
|
||||||
const selPlatforms = computed<AccountPlatform[]>(() => {
|
const selPlatforms = computed<AccountPlatform[]>(() => {
|
||||||
@@ -402,6 +407,7 @@ const todayStatsLoading = ref(false)
|
|||||||
const todayStatsError = ref<string | null>(null)
|
const todayStatsError = ref<string | null>(null)
|
||||||
const todayStatsReqSeq = ref(0)
|
const todayStatsReqSeq = ref(0)
|
||||||
const pendingTodayStatsRefresh = ref(false)
|
const pendingTodayStatsRefresh = ref(false)
|
||||||
|
const usageManualRefreshToken = ref(0)
|
||||||
|
|
||||||
const buildDefaultTodayStats = (): WindowStats => ({
|
const buildDefaultTodayStats = (): WindowStats => ({
|
||||||
requests: 0,
|
requests: 0,
|
||||||
@@ -412,7 +418,11 @@ const buildDefaultTodayStats = (): WindowStats => ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const refreshTodayStatsBatch = async () => {
|
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
|
todayStatsLoading.value = false
|
||||||
todayStatsError.value = null
|
todayStatsError.value = null
|
||||||
return
|
return
|
||||||
@@ -464,13 +474,19 @@ const loadSavedColumns = () => {
|
|||||||
const saved = localStorage.getItem(HIDDEN_COLUMNS_KEY)
|
const saved = localStorage.getItem(HIDDEN_COLUMNS_KEY)
|
||||||
if (saved) {
|
if (saved) {
|
||||||
const parsed = JSON.parse(saved) as string[]
|
const parsed = JSON.parse(saved) as string[]
|
||||||
parsed.forEach(key => hiddenColumns.add(key))
|
parsed.forEach(key => {
|
||||||
|
hiddenColumns.add(key)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
DEFAULT_HIDDEN_COLUMNS.forEach(key => hiddenColumns.add(key))
|
DEFAULT_HIDDEN_COLUMNS.forEach(key => {
|
||||||
|
hiddenColumns.add(key)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to load saved columns:', 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)
|
hiddenColumns.add(key)
|
||||||
}
|
}
|
||||||
saveColumnsToStorage()
|
saveColumnsToStorage()
|
||||||
if (key === 'today_stats' && wasHidden) {
|
if ((key === 'today_stats' || key === 'usage') && wasHidden) {
|
||||||
refreshTodayStatsBatch().catch((error) => {
|
refreshTodayStatsBatch().catch((error) => {
|
||||||
console.error('Failed to load account today stats after showing column:', error)
|
console.error('Failed to load account today stats after showing column:', error)
|
||||||
})
|
})
|
||||||
@@ -768,11 +784,15 @@ const refreshAccountsIncrementally = async () => {
|
|||||||
|
|
||||||
const handleManualRefresh = async () => {
|
const handleManualRefresh = async () => {
|
||||||
await load()
|
await load()
|
||||||
|
// Force usage cells to refetch /usage on explicit user refresh.
|
||||||
|
usageManualRefreshToken.value += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const syncPendingListChanges = async () => {
|
const syncPendingListChanges = async () => {
|
||||||
hasPendingListSync.value = false
|
hasPendingListSync.value = false
|
||||||
await load()
|
await load()
|
||||||
|
// Keep behavior consistent with manual refresh.
|
||||||
|
usageManualRefreshToken.value += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const { pause: pauseAutoRefresh, resume: resumeAutoRefresh } = useIntervalFn(
|
const { pause: pauseAutoRefresh, resume: resumeAutoRefresh } = useIntervalFn(
|
||||||
@@ -888,7 +908,8 @@ const openMenu = (a: Account, e: MouseEvent) => {
|
|||||||
const viewportWidth = window.innerWidth
|
const viewportWidth = window.innerWidth
|
||||||
const viewportHeight = window.innerHeight
|
const viewportHeight = window.innerHeight
|
||||||
|
|
||||||
let left, top
|
let left: number
|
||||||
|
let top: number
|
||||||
|
|
||||||
if (viewportWidth < 768) {
|
if (viewportWidth < 768) {
|
||||||
// 居中显示,水平位置
|
// 居中显示,水平位置
|
||||||
|
|||||||
Reference in New Issue
Block a user