diff --git a/frontend/src/components/admin/usage/UsageTable.vue b/frontend/src/components/admin/usage/UsageTable.vue index a21d2a5c..9bbdb380 100644 --- a/frontend/src/components/admin/usage/UsageTable.vue +++ b/frontend/src/components/admin/usage/UsageTable.vue @@ -326,6 +326,7 @@ import { ref } from 'vue' import { useI18n } from 'vue-i18n' import { formatDateTime, formatReasoningEffort } from '@/utils/format' +import { formatCacheTokens, formatMultiplier } from '@/utils/formatters' import { formatTokenPricePerMillion } from '@/utils/usagePricing' import { getUsageServiceTierLabel } from '@/utils/usageServiceTier' import { resolveUsageRequestType } from '@/utils/usageRequestType' @@ -376,19 +377,6 @@ const getBillingModeBadgeClass = (mode: string | null | undefined): string => { return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200' } -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() -} - -// 自适应精度:保留足够位数显示有效数字(如 0.001 → "0.001",1.5 → "1.50") -const formatMultiplier = (val: number): string => { - if (val >= 0.01) return val.toFixed(2) - if (val >= 0.001) return val.toFixed(3) - if (val >= 0.0001) return val.toFixed(4) - return val.toPrecision(2) -} const formatUserAgent = (ua: string): string => { return ua diff --git a/frontend/src/utils/formatters.ts b/frontend/src/utils/formatters.ts new file mode 100644 index 00000000..ac56b28f --- /dev/null +++ b/frontend/src/utils/formatters.ts @@ -0,0 +1,18 @@ +/** + * 格式化缓存 token 数量(1K/1M 缩写) + */ +export function formatCacheTokens(tokens: number): string { + if (tokens >= 1000000) return `${(tokens / 1000000).toFixed(1)}M` + if (tokens >= 1000) return `${(tokens / 1000).toFixed(1)}K` + return tokens.toLocaleString() +} + +/** + * 自适应精度格式化倍率(确保小数值如 0.001 不被截断) + */ +export function formatMultiplier(val: number): string { + if (val >= 0.01) return val.toFixed(2) + if (val >= 0.001) return val.toFixed(3) + if (val >= 0.0001) return val.toFixed(4) + return val.toPrecision(2) +} diff --git a/frontend/src/views/user/UsageView.vue b/frontend/src/views/user/UsageView.vue index eea468a4..401ec3f9 100644 --- a/frontend/src/views/user/UsageView.vue +++ b/frontend/src/views/user/UsageView.vue @@ -504,6 +504,7 @@ import type { UsageLog, ApiKey, UsageQueryParams, UsageStatsResponse } from '@/t import type { Column } from '@/components/common/types' import { formatDateTime, formatReasoningEffort } from '@/utils/format' import { getPersistedPageSize } from '@/composables/usePersistedPageSize' +import { formatCacheTokens, formatMultiplier } from '@/utils/formatters' import { formatTokenPricePerMillion } from '@/utils/usagePricing' import { getUsageServiceTierLabel } from '@/utils/usageServiceTier' import { resolveUsageRequestType } from '@/utils/usageRequestType' @@ -659,22 +660,6 @@ const formatTokens = (value: number): string => { return value.toLocaleString() } -// Compact format for cache tokens in table cells -const formatCacheTokens = (value: number): string => { - if (value >= 1_000_000) { - return `${(value / 1_000_000).toFixed(1)}M` - } else if (value >= 1_000) { - return `${(value / 1_000).toFixed(1)}K` - } - return value.toLocaleString() -} - -const formatMultiplier = (val: number): string => { - if (val >= 0.01) return val.toFixed(2) - if (val >= 0.001) return val.toFixed(3) - if (val >= 0.0001) return val.toFixed(4) - return val.toPrecision(2) -} const loadUsageLogs = async () => { if (abortController) {