Files
pangolin/docs/stats-overhaul-plan.html
T
wangjia 1a6eb7ac9a docs(stats): stats-overhaul 计划/测试清单 + index 登记
- stats-overhaul 实现计划(md 真相源 + html 阅读版)
- 功能×测试覆盖清单(feature-test-coverage-checklist.html)
- docs/index.html 登记上述文档

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 18:13:49 +08:00

112 lines
6.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>统计体系整改 · 实现计划(阅读版)</title>
<style>
:root{
--bg:#0f1117; --panel:#171a22; --panel2:#1d2129; --fg:#e6e8ee; --fg2:#a8afbd;
--accent:#e0884f; --accent2:#5fb0c9; --ok:#5ec27a; --bad:#e06a6a; --warn:#e0b84f;
--border:#272c36; --mono:"SF Mono",ui-monospace,Menlo,Consolas,monospace;
--sans:-apple-system,"PingFang SC","Helvetica Neue",Arial,sans-serif;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--sans);line-height:1.7;font-size:15px}
.wrap{max-width:920px;margin:0 auto;padding:48px 24px 96px}
h1{font-size:30px;line-height:1.3;margin:0 0 8px;letter-spacing:-.01em}
.sub{color:var(--fg2);font-size:15px;margin:0 0 32px}
h2{font-size:21px;margin:40px 0 14px;padding-bottom:8px;border-bottom:1px solid var(--border)}
h3{font-size:16.5px;margin:24px 0 8px;color:var(--accent)}
p{margin:10px 0}
code{font-family:var(--mono);font-size:.88em;background:var(--panel2);padding:1px 6px;border-radius:5px;color:#f0d9c4}
a{color:var(--accent2);text-decoration:none}
a:hover{text-decoration:underline}
ul{margin:8px 0;padding-left:22px}
li{margin:5px 0}
.lead{background:linear-gradient(180deg,rgba(224,136,79,.10),transparent);border:1px solid var(--border);border-radius:12px;padding:18px 20px;margin:0 0 8px}
.small{color:var(--fg2);font-size:13px}
.phase{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:16px 18px;margin:14px 0}
.phase .badge{display:inline-block;font-size:11px;font-weight:700;padding:2px 9px;border-radius:999px;margin-bottom:8px}
.b1{background:rgba(94,194,122,.16);color:var(--ok)}
.b2{background:rgba(224,184,79,.16);color:var(--warn)}
.b3{background:rgba(95,176,201,.16);color:var(--accent2)}
.note{color:var(--fg2);font-size:13px;border-left:3px solid var(--border);padding-left:12px;margin:10px 0}
</style>
</head>
<body>
<div class="wrap">
<h1>统计体系整改 · 实现计划</h1>
<p class="sub">todo #5 · 四端实时统计 + 多设备归因 + GB 配额 + 统计页重设计 · 阅读版</p>
<div class="lead">
<strong>执行真相源(带 checkbox):</strong><code>docs/superpowers/plans/2026-06-24-stats-overhaul.md</code>。本 HTML 仅供阅读,不驱动执行。
</div>
<h2>目标</h2>
<p>四端实时统计真生效(上传/下载/延迟/累计流量)+ 服务端按设备归因并按 GB 账户综合卡控 + 统计页按新设计(上聚合·下分设备)像素级还原。</p>
<p class="note">已敲定决策:租户=用户账户(无需层级表);配额改 GB、按账户综合卡;每设备独立 <code>dp_uuid</code>;分三期;页面改动先设计后开发、用真相源、四端统一元素。</p>
<h2>现状关键事实(探查结论)</h2>
<h3>客户端实时管线</h3>
<p>Dart 契约(<code>pangolin/vpn/stats</code>)与 UI 都正确,缺口全在原生侧:</p>
<ul>
<li><b>iOS</b><code>PacketTunnelProvider</code> 起了 libbox 但 <code>writeStatus/writeGroups</code> 空实现,stats EventChannel 注册了无人 push → 0 数据。</li>
<li><b>macOS 原生</b><code>VpnChannel.swift</code> 硬编码推 0;扩展回调全空。</li>
<li><b>Android</b>:上下行已工作;延迟(<code>writeGroups</code> urltest)疑似 stale。</li>
<li><b>Windows</b>:上下行已工作(Clash <code>/connections</code>);延迟解析 <code>/proxies</code> urltest 疑似拿不到 URLTest 组。</li>
</ul>
<h3>服务端用量/配额/归因</h3>
<ul>
<li>记账链路通:agent V2Ray stats(按 dp_uuid)→ <code>ReportUsage</code><code>dp_uuid→user_id</code><code>usage_daily(user_id,date)</code></li>
<li><b>无法按设备归因</b>:每账户仅一个 <code>users.dp_uuid</code><code>devices</code> 无 dp_uuid 列,<code>usage_daily</code> 无设备维度。</li>
<li>配额分钟制(<code>plans.daily_minutes</code>,连接时凭证 TTL 卡,非持续)。</li>
<li>多租户:user==account 已成立,JWT 全程隔离,无需新表。</li>
</ul>
<h3>统计页设计/实现</h3>
<p>现有 stats 设计在 mobile/tablet/desktop <b>仅聚合</b><b>分设备明细任何端都没设计</b> → Phase 3 必须 design-first。<code>_MetricCard</code> 私有于 stats_page,应提升为公共组件。</p>
<h2>三期方案</h2>
<div class="phase">
<span class="badge b1">Phase 1 · 无 schema 改动</span>
<h3 style="margin-top:0">四端实时统计修复</h3>
<ul>
<li><b>iOS/macOS(核心)</b>:主 App 用 <code>LibboxCommandClient</code> 连 App Group 容器订阅扩展 CommandServer 的 <code>writeStatus/writeGroups</code>,转推 stats channel——对齐 Android StatsHandler 模型。</li>
<li><b>Android</b>:修延迟(groups 订阅 + latestUrltest 刷新)。</li>
<li><b>Windows</b>:修 <code>extractUrltestResults()</code> 解析 + 核下发配置含 URLTest 组。</li>
<li><b>服务端核实</b>:节点 stats API 启用、agent 真上报,使累计流量/周柱有值。</li>
</ul>
</div>
<div class="phase">
<span class="badge b2">Phase 2 · 后端重型</span>
<h3 style="margin-top:0">每设备归因 + GB 综合配额</h3>
<ul>
<li><b>Schema(双驱动)</b><code>devices.dp_uuid</code> 每设备凭证;新表 <code>usage_device_daily</code><code>plans.daily_gb</code></li>
<li><b>每设备 dp_uuid</b>:注册时 mint,connect 按设备下发;控制面 <code>dp_uuid→(user_id,device_id)</code> 解析,双写设备表 + 账户 rollup。</li>
<li><b>GB 综合卡控</b>:账户当日综合 GB 超额即拒;跨阈值 revoke 凭证近持续卡控。</li>
<li><b>API</b>:暴露按设备用量。</li>
</ul>
</div>
<div class="phase">
<span class="badge b3">Phase 3 · design-first</span>
<h3 style="margin-top:0">统计页重设计 + 四端实现</h3>
<ul>
<li><b>设计</b>:走 design-distill,为分设备明细出 mobile/tablet/desktop 原型 + 更新 CONTRACT.md。</li>
<li><b>实现</b>:提升 <code>metric_card.dart</code>、新增 <code>device_stat_row.dart</code>;四端接分设备 provider;语义 token;红线扫描。</li>
<li><b>验收</b>:截图 diff + 新增分设备 golden。</li>
</ul>
</div>
<h2>执行顺序</h2>
<p>先 Phase 1(见效快、零 schema 风险)→ 合并验收 → Phase 2(后端)→ Phase 3(设计可与 Phase 2 并行起草,实现接线依赖 Phase 2 API)。</p>
<p class="small">不在本次范围:组织级多租户层级、协议选择(#8)、KillSwitch#1/#2/#3)。</p>
</div>
</body>
</html>