Rainytoken/docs/heatmap-plan.md
WaterRain 025f971f7a
feat(heatmap): 首页OCGO快捷入口 + 多语言兼容修复
- 首页:OCGO用量卡与服务卡「查看用量详情」右侧新增 Token 活动快捷入口
- 首页入口描述改为「OCGO Token 活动」;统计卡片改 2×2 布局
- 多语言:热力图月份/日期/数字单位 locale-aware(英文 K/M/B + MMM d)
- 浮层/读数条句子走 stringResource;月份名资源数组(三语言)
- 遗留修复:Codex 窗口标签中性化(weekly/usage)、Ollama plan 空串兜底、
  isFiveHourLabel 语言无关判断、字段标签资源化、Widget usageLabel
- 单测同步:Codex/Ollama/FormatUtils/FormatCodexPrimaryLabel 全绿(119 用例)
2026-08-07 03:28:23 +00:00

8.8 KiB
Raw Blame History

Token 活动热力图 — 设计方案

参考实现:reference/react-activity-calendar(grubersjoe/react-activity-calendar,MIT) 该库为 React/SVG Web 组件,本项目用 Jetpack Compose Canvas 重新实现,仅参考其布局逻辑和数据结构。


一、入口与数据源

  • 主页 OCGO 用量卡片「查看详情」右侧新增「Token 活动」快捷入口,点击进入独立的 Token 活动热力图页面(另有独立入口卡片)
  • 首页入口卡片标题「OCGO Token 活动」、副标题「OCGO 每日 Token 使用热力图」(数据来源更准确)
  • 只统计 OCGO 服务的数据,不涉及 CCGO / Codex / Ollama

二、页面布局

  • 标题左对齐:「Token 活动」
  • 标题右侧视图切换:每日 / 每周 / 累计
    • 选中项:主要文字颜色 + 中等字重
    • 未选中项:弱文字颜色
    • 不使用大号按钮背景或明显的 Tab 胶囊样式

三、每日视图(默认)

  • GitHub Contribution Calendar 结构:
    • 53 列 × 7 行
    • 每列代表一周,每行代表星期中的一天
    • 越靠右越接近当前日期
    • 按所选自然年显示:今年 = 1月1日 ~ 今天;往年 = 1月1日 ~ 12月31日(完整自然年,取代早期「最近滚动 365 天」窗口,详见「十一、年份选择器」)
  • 格子参数:
    • 尺寸 10~12dp
    • 间距 3dp
    • 圆角 3dp
  • 月份标签:12sp,底部显示
  • 不显示左侧星期标签

注:2026-08 起已改为**年份选择器(自然年)**取代固定滚动 365 天窗口,详见「十一、年份选择器」。

四、颜色等级

  • 6 级:Level 0(空白)+ Level 1~5(逐渐加深的粉色)
  • 使用项目现有配色(Color.kt 中的粉色系)
  • 映射方案:分位数法
    • 收集所有非零日 Token 数,排序,计算分位阈值
    • Level 0:token = 0(空白)
    • Level 1:0 ~ 25% 分位
    • Level 2:25% ~ 50% 分位
    • Level 3:50% ~ 75% 分位
    • Level 4:75% ~ 95% 分位
    • Level 5:95% 以上
    • 颜色会随数据变化是预期行为(与 GitHub 热力图一致)

五、每周视图

  • 与每日视图共用同一 7 行 × 约 53 列网格尺寸(列数按所选自然年浮动 52~54),切换视图时布局保持一致
  • 语义为离散柱状图:横轴 = 自然周,每一列 = 一周,纵向高度 = 该周 Token 用量
  • 每列从底部向上填充格子,用量越多填充越高;整列 7 格全部绘制:底部 barHeight 格 = 该周等级颜色(柱),其余格 = Level 0 浅色(空白格不隐藏,网格完整),最大高度 = 7 格满柱
  • 高度映射:非零周按 token 去重排序的排名比例映射 2~7 格(height = 2 + rankIndex×5/(uniqueCount-1),排名不同高度必不同,如 3.7亿 → 2 格、10.7亿 → 7 格;唯一非零值时满柱 7 格)
  • 填充格使用该周的等级颜色(6 级粉色分位,与图例"少→多"一致)
  • 列内格子不表示周日~周六(与每日视图的日期语义解耦)
  • 周列与日视图一致按周日对齐;第一列 = 该年 1月1日 所在周(可能含去年 12 月空位),最后一列 = 结束日所在周(今年 = 今天所在周,往年可能跨到次年 1 月初)
  • 点击:每周视图列内任意格子可点击查看该周浮层("X月X日-X月X日 使用了X token"),含 0 用量周(显示"使用了0token");选中周整列加主题色描边强调(再次点击或点击其他周取消)

六、累计视图

  • 和每日视图同样的小格子风格
  • 53 列 × 7 行
  • 每个格子的颜色代表从起始日到该日的累计 Token 总量
  • 同样用分位数法映射到 6 级

七、格子交互

  • 滑动查看(三种视图,OCGO 风格):在图表上手指拖动或长按,按速度/时长仲裁两种模式:
    • 长按(按住不动 ≥ 系统长按时长)→ 查看模式:手指所在格子直接高亮预览(所见即所得),底部读数条显示该格数据;按住期间拖动可切换预览格子,抬起后保留
    • 慢速横向拖动(< 约150dp/s)→ 查看模式:图表锁定不滚动(保证稳定),所见即所得——手指所在格子加主题色边框高亮预览,底部读数条实时显示该格数据(抬起后保留,切换视图/年份清除)
    • 快速横向拖动(≥ 约150dp/s)→ 滚动模式:放行给图表正常左右滚动浏览(含惯性)
    • 读数条语义与视图一致:每日/累计=该天"X月X日 使用了X token"(累计视图 tokens 为累计值);每周=该周范围"X月X日-X月X日 使用了X token"(与周浮层同口径,末周夹取到数据最后一天、跨年带年份前缀)
  • 点击格子显示浮层,内容为日期和当天使用的 Token 数
  • 浮层格式示例:
    7月9日 使用了1.9亿token
    7月10日 使用了1124.5万token
    7月11日 使用了11.2万token
    7月12日 使用了16783token
    
    (Token 数按数量级自然中文读法显示)
  • 浮层保留卡片外观,但不拦截图表交互(Popup focusable=false):点击/滑动直接作用于图表——点其他格子即切换浮层,再次点击同一格子关闭,手指滑动查看图表不受浮层影响
  • 图表支持手指横向滑动查看(配合年份选择器浏览任意年份),页面纵向滚动
  • 不需要"查看详情"按钮
  • 热力格支持键盘聚焦,提供日期与 Token 数的无障碍描述

八、视图切换动画

  • 切换视图使用约 150ms 的淡入淡出
  • 不要明显的滑动或弹跳动画

九、Token 定义

  • 热力图中的「使用 token」= inputTokens + cacheReadTokens + reasoningTokens + outputTokens
    • inputTokens:未命中缓存的输入 token
    • cacheReadTokens:命中缓存的输入 token
    • reasoningTokens:推理 token(思维链 CoT)
    • outputTokens:输出 token
  • 不包含 cacheWrite5mTokens 和 cacheWrite1hTokens(缓存写入 token)

十、Token 数显示格式

  • 按数量级自然转换为中文读法(locale-aware):
    • 中文:亿级 1.9亿 / 千万级 1124.5万 / 万级 11.2万 / 万以下原始数字(繁体用 萬/億)
    • 非中文:≥1e9 → 1.9B / ≥1e6 → 11.2M / ≥1e3 → 16.8K / 否则原数字
  • 日期格式同理:中文 "7月9日"(跨年 "2024年7月9日");非中文 "Jul 9"(跨年 "Jul 9, 2024")
  • 浮层/读数条句子("X月X日 使用了X token")走 stringResource(heatmap_day_used/heatmap_week_used),按语言拼接

十一、年份选择器(2026-08 新增)

  • 标题「Token 活动」右侧为年份下拉选择器(「2026 ▾」),点击弹出年份列表
  • 语义:按自然年查看
    • 今年:1月1日 ~ 今天(默认选中年份)
    • 往年:1月1日 ~ 12月31日(完整自然年)
    • 取代原先固定「最近滚动 365 天」窗口
  • 可选年份范围:最早有数据的年份 ~ 今年
  • 三种视图(每日/每周/累计)均跟随所选年份,分位数按所选年份独立计算(颜色随年份数据变化是预期行为)
  • 周视图按自然年时列数浮动(52~54 列,闰年且 1月1日 为周六时可达 54 列):
    • 第一列为该年 1月1日 所在周(可能含去年 12 月空位)
    • 最后一列为结束日所在周(今年=今天所在周;往年可能跨到次年 1 月初)
  • 浮层日期:日期所在年份与今年不同时前缀加年份(如「2024年7月9日 使用了1.9亿token」)

十二、图例与滚动(2026-08 新增)

  • 底部「少 → 多」颜色图例固定显示,不随热力图横向滚动
  • 页面打开 / 切换视图 / 切换年份时,热力图横向滚动自动定位到最右(最新数据)
  • 0 token 的天可以点击查看浮层(显示「7月9日 使用了0token」);每周视图 0 用量周显示 1 格 Level 0 浅色格、同样可点击(柱状图语义,见「五、每周视图」)

十三、年度统计(2026-08 新增)

  • 视图切换器下方 2×2 网格 4 个统计卡片(每行 2 个,窄屏友好),按所选年份计算(切换年份跟随变化),与图表口径一致
    • 累计 token:当年全部天之和(= 累计视图最后一天的累计值)
    • 峰值 token:当年单日最大 token(无数据=0)
    • 当前连续:从数据最后一天往前数连续 >0 的天数(最后一天为 0 则=0)
    • 最长连续:当年内连续 >0 的最大天数
  • 实现:HeatmapViewModel 的 computeStats(dailyData)(companion 内,internal),结果存于 HeatmapUiState.stats;加载与切换年份时随 dailyData 一起更新
  • 连续天数的"有 token"判定:当日 token > 0(0 token 的天视为断档);数据为 1月1日~结束日的完整日序列,含 0 token 的天
  • Token 数值显示沿用「十、Token 数显示格式」(亿/万中文读法);天数显示为「N 天」