feat(usage): add account cost display to admin dashboard and usage pages

- Add account_cost column to dashboard aggregation tables (migration 107)
- DashboardStats: add TotalAccountCost/TodayAccountCost fields
- ModelStat/GroupStat: add AccountCost field with SQL aggregation
- GetStatsWithFilters: always return TotalAccountCost (remove accountID filter)
- Dashboard Token cards: show user(green)/cost(orange)/standard(gray)
- Usage stats card: show account cost and standard below main value
- Model/Group distribution tables: add orange cost column
This commit is contained in:
erio
2026-04-15 13:47:38 +08:00
parent 7c671b5373
commit 6ade6d30a8
12 changed files with 89 additions and 34 deletions

View File

@@ -28,17 +28,14 @@
<div class="min-w-0 flex-1">
<p class="text-xs font-medium text-gray-500">{{ t('usage.totalCost') }}</p>
<p class="text-xl font-bold text-green-600">
${{ ((stats?.total_account_cost ?? stats?.total_actual_cost) || 0).toFixed(4) }}
${{ (stats?.total_actual_cost || 0).toFixed(4) }}
</p>
<p class="text-xs text-gray-400" v-if="stats?.total_account_cost != null">
{{ t('usage.userBilled') }}:
<span class="text-gray-300">${{ (stats?.total_actual_cost || 0).toFixed(4) }}</span>
· {{ t('usage.standardCost') }}:
<span class="text-gray-300">${{ (stats?.total_cost || 0).toFixed(4) }}</span>
</p>
<p class="text-xs text-gray-400" v-else>
{{ t('usage.standardCost') }}:
<span class="line-through">${{ (stats?.total_cost || 0).toFixed(4) }}</span>
<p class="text-xs text-gray-400">
<span class="text-orange-500">${{ (stats?.total_account_cost || 0).toFixed(4) }}</span>
<span> {{ t('usage.accountCost') }}</span>
<span> · </span>
<span>${{ (stats?.total_cost || 0).toFixed(4) }}</span>
<span> {{ t('usage.standardCost') }}</span>
</p>
</div>
</div>

View File

@@ -45,6 +45,7 @@
<th class="pb-2 text-right">{{ t('admin.dashboard.requests') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.tokens') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.actual') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.accountCost') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.standard') }}</th>
</tr>
</thead>
@@ -75,13 +76,16 @@
<td class="py-1.5 text-right text-green-600 dark:text-green-400">
${{ formatCost(group.actual_cost) }}
</td>
<td class="py-1.5 text-right text-orange-500 dark:text-orange-400">
${{ formatCost(group.account_cost) }}
</td>
<td class="py-1.5 text-right text-gray-400 dark:text-gray-500">
${{ formatCost(group.cost) }}
</td>
</tr>
<!-- User breakdown sub-rows -->
<tr v-if="expandedKey === `group-${group.group_id}`">
<td colspan="5" class="p-0">
<td colspan="6" class="p-0">
<UserBreakdownSubTable
:items="breakdownItems"
:loading="breakdownLoading"

View File

@@ -114,6 +114,7 @@
<th class="pb-2 text-right">{{ t('admin.dashboard.requests') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.tokens') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.actual') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.accountCost') }}</th>
<th class="pb-2 text-right">{{ t('admin.dashboard.standard') }}</th>
</tr>
</thead>
@@ -142,12 +143,15 @@
<td class="py-1.5 text-right text-green-600 dark:text-green-400">
${{ formatCost(model.actual_cost) }}
</td>
<td class="py-1.5 text-right text-orange-500 dark:text-orange-400">
${{ formatCost(model.account_cost) }}
</td>
<td class="py-1.5 text-right text-gray-400 dark:text-gray-500">
${{ formatCost(model.cost) }}
</td>
</tr>
<tr v-if="expandedKey === `model-${model.model}`">
<td colspan="5" class="p-0">
<td colspan="6" class="p-0">
<UserBreakdownSubTable
:items="breakdownItems"
:loading="breakdownLoading"