diff --git a/frontend/src/components/admin/usage/UsageTable.vue b/frontend/src/components/admin/usage/UsageTable.vue index 91e71e42..63694925 100644 --- a/frontend/src/components/admin/usage/UsageTable.vue +++ b/frontend/src/components/admin/usage/UsageTable.vue @@ -1,22 +1,153 @@ - - - {{ row.user?.email || '-' }}#{{ row.user_id }} - {{ value }} - In: {{ row.input_tokens.toLocaleString() }} / Out: {{ row.output_tokens.toLocaleString() }} - ${{ row.actual_cost.toFixed(6) }} - {{ formatDateTime(value) }} - - - + + + + + + {{ row.user?.email || '-' }} + #{{ row.user_id }} + + + + + {{ row.api_key?.name || '-' }} + + + + {{ row.account?.name || '-' }} + + + + {{ value }} + + + + + {{ row.group.name }} + + - + + + + + {{ row.stream ? t('usage.stream') : t('usage.sync') }} + + + + + + + + + {{ row.input_tokens?.toLocaleString() || 0 }} + + + + {{ row.output_tokens?.toLocaleString() || 0 }} + + + + + + {{ formatCacheTokens(row.cache_read_tokens) }} + + + + {{ formatCacheTokens(row.cache_creation_tokens) }} + + + + + + + ${{ row.actual_cost?.toFixed(6) || '0.000000' }} + + + + + {{ row.billing_type === 1 ? t('usage.subscription') : t('usage.balance') }} + + + + + {{ formatDuration(row.first_token_ms) }} + - + + + + {{ formatDuration(row.duration_ms) }} + + + + {{ formatDateTime(value) }} + + + + + {{ row.request_id }} + + + + + + - + + + + + + \ No newline at end of file + +const formatCacheTokens = (tokens: number): string => { + if (tokens >= 1000000) return `${(tokens / 1000000).toFixed(1)}M` + if (tokens >= 1000) return `${(tokens / 1000).toFixed(1)}K` + return tokens.toString() +} + +const formatDuration = (ms: number | null | undefined): string => { + if (ms == null) return '-' + if (ms < 1000) return `${ms}ms` + return `${(ms / 1000).toFixed(2)}s` +} + +const copyRequestId = async (requestId: string) => { + try { + await navigator.clipboard.writeText(requestId) + copiedRequestId.value = requestId + appStore.showSuccess(t('admin.usage.requestIdCopied')) + setTimeout(() => { copiedRequestId.value = null }, 2000) + } catch { + appStore.showError(t('common.copyFailed')) + } +} +