feat: /admin/usage页面增加模型分布情况显示

This commit is contained in:
shaw
2025-12-20 10:06:55 +08:00
parent ef81aeb463
commit 0484c59ead
8 changed files with 518 additions and 213 deletions

View File

@@ -47,7 +47,7 @@
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">{{ t('usage.totalCost') }}</p>
<p class="text-xl font-bold text-green-600 dark:text-green-400">${{ (usageStats?.total_actual_cost || 0).toFixed(4) }}</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('usage.actualCost') }} / <span class="line-through">${{ (usageStats?.total_cost || 0).toFixed(4) }}</span> {{ t('usage.standardCost') }}
<span class="line-through">${{ (usageStats?.total_cost || 0).toFixed(4) }}</span> {{ t('usage.standardCost') }}
</p>
</div>
</div>
@@ -70,6 +70,35 @@
</div>
</div>
<!-- Charts Section -->
<div class="space-y-4">
<!-- Chart Controls -->
<div class="card p-4">
<div class="flex items-center gap-4">
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">{{ t('admin.dashboard.granularity') }}:</span>
<div class="w-28">
<Select
v-model="granularity"
:options="granularityOptions"
@change="onGranularityChange"
/>
</div>
</div>
</div>
<!-- Charts Grid -->
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
<ModelDistributionChart
:model-stats="modelStats"
:loading="chartsLoading"
/>
<TokenUsageTrend
:trend-data="trendData"
:loading="chartsLoading"
/>
</div>
</div>
<!-- Filters -->
<div class="card">
<div class="px-6 py-4">
@@ -324,7 +353,9 @@ import Pagination from '@/components/common/Pagination.vue'
import EmptyState from '@/components/common/EmptyState.vue'
import Select from '@/components/common/Select.vue'
import DateRangePicker from '@/components/common/DateRangePicker.vue'
import type { UsageLog } from '@/types'
import ModelDistributionChart from '@/components/charts/ModelDistributionChart.vue'
import TokenUsageTrend from '@/components/charts/TokenUsageTrend.vue'
import type { UsageLog, TrendDataPoint, ModelStat } from '@/types'
import type { Column } from '@/components/common/types'
import type { SimpleUser, SimpleApiKey, AdminUsageStatsResponse, AdminUsageQueryParams } from '@/api/admin/usage'
@@ -334,6 +365,18 @@ const appStore = useAppStore()
// Usage stats from API
const usageStats = ref<AdminUsageStatsResponse | null>(null)
// Chart data
const trendData = ref<TrendDataPoint[]>([])
const modelStats = ref<ModelStat[]>([])
const chartsLoading = ref(false)
const granularity = ref<'day' | 'hour'>('day')
// Granularity options for Select component
const granularityOptions = computed(() => [
{ value: 'day', label: t('admin.dashboard.day') },
{ value: 'hour', label: t('admin.dashboard.hour') },
])
const columns = computed<Column[]>(() => [
{ key: 'user', label: t('admin.usage.user'), sortable: false },
{ key: 'api_key', label: t('usage.apiKeyFilter'), sortable: false },
@@ -535,10 +578,45 @@ const loadUsageStats = async () => {
}
}
const loadChartData = async () => {
chartsLoading.value = true
try {
const params = {
start_date: filters.value.start_date || startDate.value,
end_date: filters.value.end_date || endDate.value,
granularity: granularity.value,
user_id: filters.value.user_id,
api_key_id: filters.value.api_key_id ? Number(filters.value.api_key_id) : undefined,
}
const [trendResponse, modelResponse] = await Promise.all([
adminAPI.dashboard.getUsageTrend(params),
adminAPI.dashboard.getModelStats({
start_date: params.start_date,
end_date: params.end_date,
user_id: params.user_id,
api_key_id: params.api_key_id,
}),
])
trendData.value = trendResponse.trend || []
modelStats.value = modelResponse.models || []
} catch (error) {
console.error('Failed to load chart data:', error)
} finally {
chartsLoading.value = false
}
}
const onGranularityChange = () => {
loadChartData()
}
const applyFilters = () => {
pagination.value.page = 1
loadUsageLogs()
loadUsageStats()
loadChartData()
}
const resetFilters = () => {
@@ -552,11 +630,13 @@ const resetFilters = () => {
start_date: undefined,
end_date: undefined
}
granularity.value = 'day'
// Reset date range to default (last 7 days)
initializeDateRange()
pagination.value.page = 1
loadUsageLogs()
loadUsageStats()
loadChartData()
}
const handlePageChange = (page: number) => {
@@ -614,6 +694,7 @@ onMounted(() => {
initializeDateRange()
loadUsageLogs()
loadUsageStats()
loadChartData()
document.addEventListener('click', handleClickOutside)
})