Skip to content

feat: 用户排行榜增强 — 分模型统计展开 + 用户级统计仪表盘 (Per-Model Breakdown & User Statistics Dashboard) #861

@sususu98

Description

@sususu98

功能描述

希望增强排行榜的 用户排名 界面,提供两层用户用量洞察能力:

  1. 展开行:分模型统计 — 在用户排行榜中展开每行,查看该用户按模型维度的用量明细
  2. 用户统计仪表盘 — 点击用户名,进入该用户的专属统计页面,包含趋势图、模型分布等仪表盘级别的可视化

背景

目前用户排行榜仅展示汇总数据(总请求数、总 Token、总费用)。在多模型混用场景下(claude-sonnet / claude-opus / gemini 等),管理员缺乏以下能力:

  • 查看单个用户在不同模型上的消费分布
  • 查看单个用户的费用/请求趋势变化
  • 对用户的用量模式进行深入分析(哪些模型用得多、缓存命中率如何等)

目前 my-usage 页面已经为普通用户自己提供了类似功能(StatisticsSummaryCard 组件展示请求数/费用/Token/缓存统计 + 分模型明细),但管理员无法从排行榜角度查看任意用户的同等信息


Part 1: 排行榜展开行 — 分模型统计

需求

在用户排行榜的每一行末尾增加展开按钮,展开后显示该用户按模型维度的统计子表。

预期效果

模型 请求数 Token 费用
claude-sonnet-4-20250514 1,234 12.5M $45.60
claude-opus-4-20250514 89 2.1M $28.30
gemini-2.5-pro 456 5.8M $12.10

现有架构支持

  • usage_ledger 表已包含 modeloriginal_model 字段,可 GROUP BY (userId, model) 二次聚合
  • LeaderboardTable 组件已通过 renderExpandedContent prop 支持可展开行(当前用于供应商缓存命中率 Tab)
  • findProviderCacheHitRateLeaderboardWithTimezone 已实现"先按父实体聚合 -> 再按模型二次聚合"的模式,可直接参考

建议实现

  1. src/repository/leaderboard.ts 新增 UserModelStat 接口和二次聚合查询
  2. 扩展 LeaderboardEntry 增加 modelStats: UserModelStat[]
  3. leaderboard-view.tsxscope === "user" 添加 renderExpandedContent

Part 2: 用户级统计仪表盘

需求

在用户排行榜中,点击用户名可跳转到(或弹出)该用户的专属统计仪表盘,提供与主仪表盘概览页类似的可视化体验,但数据范围限定为该用户。

预期包含的可视化元素

2.1 概览指标卡片

类似 BentoMetricCard 的用户级版本:

  • 今日请求数(与昨日同期对比)
  • 今日费用(与昨日同期对比)
  • 平均响应时间
  • 缓存命中率

注:getOverviewMetricsWithComparison 已支持 userId 参数,可直接复用。

2.2 时间趋势图

类似 StatisticsChartCard 的用户级版本(Recharts AreaChart):

  • 费用趋势(按天/小时)
  • 请求量趋势(按天/小时)
  • 支持 today / 7days / 30days / thisMonth 时间范围切换
  • 以该用户的各 API Key 为维度展示多条曲线

注:getUserStatistics Action 的底层查询(getKeyStatisticsFromDB)已支持按 userId 过滤,StatisticsChartCard 组件可直接复用。

2.3 模型消费分布

类似 my-usage 页面的 StatisticsSummaryCard 中的 Model Breakdown:

  • 按模型分组展示:请求数、Token(输入/输出/缓存)、费用、费用占比
  • 可点击展开查看 Token 详情(input/output/cache read/cache write)和缓存命中率

注:getMyStatsSummary Action 的查询模式可参考,但需改为支持 targetUserId 参数。

建议实现方案

方案 A: 新页面(推荐)

  • 新增路由 /dashboard/leaderboard/user/[userId]
  • 排行榜用户名变为超链接
  • 页面复用现有组件:BentoMetricCard + StatisticsChartCard + ModelBreakdownColumn

方案 B: 对话框

  • 在排行榜行末增加"查看详情"按钮
  • 弹出全屏对话框(类似 key-stats-dialog.tsx 模式)
  • 优点:无需离开排行榜页面

相关文件

排行榜(Part 1)

  • src/repository/leaderboard.ts — 排行榜查询逻辑
  • src/app/[locale]/dashboard/leaderboard/_components/leaderboard-view.tsx — 排行榜 UI
  • src/app/[locale]/dashboard/leaderboard/_components/leaderboard-table.tsx — 通用表格(已支持 renderExpandedContent

统计图表(Part 2)

  • src/app/[locale]/dashboard/_components/bento/statistics-chart-card.tsx — 时间趋势面积图(Recharts AreaChart, 支持 Cost/Calls 切换, Overlay/Stacked 模式)
  • src/app/[locale]/dashboard/_components/bento/metric-card.tsx — 指标卡片组件
  • src/repository/overview.tsgetOverviewMetricsWithComparison(userId?) 已支持用户过滤
  • src/actions/statistics.tsgetUserStatistics 统计数据源
  • src/repository/statistics.ts — 底层时间序列聚合查询(支持按用户/密钥分组)

参考实现(my-usage 页面)

  • src/app/[locale]/my-usage/_components/statistics-summary-card.tsx — 用户自有统计卡(含分模型明细,可作为 Part 2.3 参考)
  • src/actions/my-usage.tsgetMyStatsSummary 模型级统计查询

数据层

  • src/drizzle/schema.tsusage_ledger 表(model, original_model, userId, costUsd, tokens 等字段齐全)
  • src/app/api/leaderboard/route.ts — 排行榜 API

环境信息

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions