Merge pull request #1040 from 0xObjc/codex/fix-user-spending-ranking-others

fix(admin): polish spending ranking and usage defaults
This commit is contained in:
Wesley Liddick
2026-03-16 09:19:46 +08:00
committed by GitHub
10 changed files with 148 additions and 23 deletions

View File

@@ -241,6 +241,8 @@
:enable-ranking-view="true"
:ranking-items="rankingItems"
:ranking-total-actual-cost="rankingTotalActualCost"
:ranking-total-requests="rankingTotalRequests"
:ranking-total-tokens="rankingTotalTokens"
:loading="chartsLoading"
:ranking-loading="rankingLoading"
:ranking-error="rankingError"
@@ -334,6 +336,8 @@ const modelStats = ref<ModelStat[]>([])
const userTrend = ref<UserUsageTrendPoint[]>([])
const rankingItems = ref<UserSpendingRankingItem[]>([])
const rankingTotalActualCost = ref(0)
const rankingTotalRequests = ref(0)
const rankingTotalTokens = ref(0)
let chartLoadSeq = 0
let usersTrendLoadSeq = 0
let rankingLoadSeq = 0
@@ -347,7 +351,7 @@ const formatLocalDate = (date: Date): string => {
const getTodayLocalDate = () => formatLocalDate(new Date())
// Date range
const granularity = ref<'day' | 'hour'>('day')
const granularity = ref<'day' | 'hour'>('hour')
const startDate = ref(getTodayLocalDate())
const endDate = ref(getTodayLocalDate())
@@ -630,11 +634,15 @@ const loadUserSpendingRanking = async () => {
if (currentSeq !== rankingLoadSeq) return
rankingItems.value = response.ranking || []
rankingTotalActualCost.value = response.total_actual_cost || 0
rankingTotalRequests.value = response.total_requests || 0
rankingTotalTokens.value = response.total_tokens || 0
} catch (error) {
if (currentSeq !== rankingLoadSeq) return
console.error('Error loading user spending ranking:', error)
rankingItems.value = []
rankingTotalActualCost.value = 0
rankingTotalRequests.value = 0
rankingTotalTokens.value = 0
rankingError.value = true
} finally {
if (currentSeq === rankingLoadSeq) {

View File

@@ -122,7 +122,7 @@ type DistributionMetric = 'tokens' | 'actual_cost'
type EndpointSource = 'inbound' | 'upstream' | 'path'
const route = useRoute()
const usageStats = ref<AdminUsageStatsResponse | null>(null); const usageLogs = ref<AdminUsageLog[]>([]); const loading = ref(false); const exporting = ref(false)
const trendData = ref<TrendDataPoint[]>([]); const modelStats = ref<ModelStat[]>([]); const groupStats = ref<GroupStat[]>([]); const chartsLoading = ref(false); const granularity = ref<'day' | 'hour'>('day')
const trendData = ref<TrendDataPoint[]>([]); const modelStats = ref<ModelStat[]>([]); const groupStats = ref<GroupStat[]>([]); const chartsLoading = ref(false); const granularity = ref<'day' | 'hour'>('hour')
const modelDistributionMetric = ref<DistributionMetric>('tokens')
const groupDistributionMetric = ref<DistributionMetric>('tokens')
const endpointDistributionMetric = ref<DistributionMetric>('tokens')
@@ -159,6 +159,7 @@ const formatLD = (d: Date) => {
return `${year}-${month}-${day}`
}
const getTodayLocalDate = () => formatLD(new Date())
const getGranularityForRange = (start: string, end: string): 'day' | 'hour' => start === end ? 'hour' : 'day'
const startDate = ref(getTodayLocalDate()); const endDate = ref(getTodayLocalDate())
const filters = ref<AdminUsageQueryParams>({ user_id: undefined, model: undefined, group_id: undefined, request_type: undefined, billing_type: null, start_date: startDate.value, end_date: endDate.value })
const pagination = reactive({ page: 1, page_size: 20, total: 0 })
@@ -193,6 +194,7 @@ const applyRouteQueryFilters = () => {
start_date: startDate.value,
end_date: endDate.value
}
granularity.value = getGranularityForRange(startDate.value, endDate.value)
}
const loadLogs = async () => {
@@ -258,7 +260,7 @@ const loadChartData = async () => {
}
const applyFilters = () => { pagination.page = 1; loadLogs(); loadStats(); loadChartData() }
const refreshData = () => { loadLogs(); loadStats(); loadChartData() }
const resetFilters = () => { startDate.value = getTodayLocalDate(); endDate.value = getTodayLocalDate(); filters.value = { start_date: startDate.value, end_date: endDate.value, request_type: undefined, billing_type: null }; granularity.value = 'day'; applyFilters() }
const resetFilters = () => { startDate.value = getTodayLocalDate(); endDate.value = getTodayLocalDate(); filters.value = { start_date: startDate.value, end_date: endDate.value, request_type: undefined, billing_type: null }; granularity.value = getGranularityForRange(startDate.value, endDate.value); applyFilters() }
const handlePageChange = (p: number) => { pagination.page = p; loadLogs() }
const handlePageSizeChange = (s: number) => { pagination.page_size = s; pagination.page = 1; loadLogs() }
const cancelExport = () => exportAbortController?.abort()