feat(usage): 使用记录增加计费模式字段 — 记录/展示/筛选 token/按次/图片
- DB: usage_logs 表新增 billing_mode VARCHAR(20) 列 - 后端: RecordUsage 写入时根据 image_count 判定计费模式 - 前端: 使用记录表格新增计费模式 badge 列 + 筛选下拉
This commit is contained in:
@@ -133,6 +133,12 @@
|
||||
<Select v-model="filters.billing_type" :options="billingTypeOptions" @change="emitChange" />
|
||||
</div>
|
||||
|
||||
<!-- Billing Mode Filter -->
|
||||
<div class="w-full sm:w-auto sm:min-w-[200px]">
|
||||
<label class="input-label">{{ t('admin.usage.billingMode') }}</label>
|
||||
<Select v-model="filters.billing_mode" :options="billingModeOptions" @change="emitChange" />
|
||||
</div>
|
||||
|
||||
<!-- Group Filter -->
|
||||
<div class="w-full sm:w-auto sm:min-w-[200px]">
|
||||
<label class="input-label">{{ t('admin.usage.group') }}</label>
|
||||
@@ -232,6 +238,13 @@ const billingTypeOptions = ref<SelectOption[]>([
|
||||
{ value: 1, label: t('admin.usage.billingTypeSubscription') }
|
||||
])
|
||||
|
||||
const billingModeOptions = ref<SelectOption[]>([
|
||||
{ value: null, label: t('admin.usage.allBillingModes') },
|
||||
{ value: 'token', label: t('admin.usage.billingModeToken') },
|
||||
{ value: 'per_request', label: t('admin.usage.billingModePerRequest') },
|
||||
{ value: 'image', label: t('admin.usage.billingModeImage') }
|
||||
])
|
||||
|
||||
const emitChange = () => emit('change')
|
||||
|
||||
const debounceUserSearch = () => {
|
||||
|
||||
@@ -69,6 +69,12 @@
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #cell-billing_mode="{ row }">
|
||||
<span class="inline-flex items-center rounded px-2 py-0.5 text-xs font-medium" :class="getBillingModeBadgeClass(row.billing_mode)">
|
||||
{{ getBillingModeLabel(row.billing_mode) }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #cell-tokens="{ row }">
|
||||
<!-- 图片生成请求 -->
|
||||
<div v-if="row.image_count > 0" class="flex items-center gap-1.5">
|
||||
@@ -350,6 +356,18 @@ const getRequestTypeBadgeClass = (row: AdminUsageLog): string => {
|
||||
return 'bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200'
|
||||
}
|
||||
|
||||
const getBillingModeLabel = (mode: string | null | undefined): string => {
|
||||
if (mode === 'per_request') return t('admin.usage.billingModePerRequest')
|
||||
if (mode === 'image') return t('admin.usage.billingModeImage')
|
||||
return t('admin.usage.billingModeToken')
|
||||
}
|
||||
|
||||
const getBillingModeBadgeClass = (mode: string | null | undefined): string => {
|
||||
if (mode === 'per_request') return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'
|
||||
if (mode === 'image') return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
|
||||
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`
|
||||
|
||||
Reference in New Issue
Block a user