wangjia
ddf8b1d4d8
feat(client): 智能选择卡也走切换确认(防误触)
...
把节点卡的"已连接时切换先弹确认"逻辑抽成 _onSelect(code,name),节点卡与智能
选择卡共用。点智能选择卡:未连接直接选,已连接/连接中弹确认("切换到「智能选择」?")。
node_connect_confirm_test 增"已连接点智能选择卡弹确认→取消不切"用例。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 11:52:11 +08:00
wangjia
0820397a14
chore(client): 版本号 1.0.16+17(single-flight 刷新 + 托盘退出崩溃修复)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 11:46:16 +08:00
wangjia
4cc8f772e5
fix(client): 托盘「退出」崩溃(0xC000041D)——绕开 windowManager.destroy()
...
Windows 上从托盘菜单退出会崩:windowManager.destroy() 在 Win32 托盘回调里触发
DestroyWindow/WM_CLOSE 回调链(并回调 onWindowClose → await isPreventClose),
异常穿过内核回调边界 → STATUS_FATAL_USER_CALLBACK_EXCEPTION(0xC000041D),
flutter_windows.dll 处崩溃。WER 崩溃签名跨版本一致(自 1.0.0 起),非业务代码引入。
内核已在 onBeforeQuit 停掉、隧道已拆,改为先 trayManager.destroy() 摘图标,
再 exit(0) 干净退出进程,绕开原生窗口销毁回调链。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 11:30:59 +08:00
wangjia
29a6aa9112
fix(client): refresh token single-flight — 修跨平台「放久了/更新后被踢下线」
...
refresh token 是单次使用+轮换(服务端每次刷新 DEL 旧 JTI 发新的)。冷启动/进
页面会并发打多个接口,access(15min)过期后同时多次 401,各自拿同一个旧 refresh
token 去刷新:第一个成功轮换,其余拿已作废的 JTI 必被拒 → 误触发 logout 把用户
踢回登录页。与平台无关(共用 auth 逻辑),表现为「放久了/覆盖更新后要重新登录」。
修法:AuthNotifier.refresh() 用共享 in-flight future(single-flight)合并并发刷新,
旧 token 只被消费一次。新增 auth_refresh_singleflight_test 覆盖并发只刷一次 +
刷新后可再刷。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 11:05:16 +08:00
wangjia
eafc7167e2
chore(client): 版本号 1.0.15+16(自适应菜单 + 节点切换防误触)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 10:11:48 +08:00
wangjia
73da0bc9a2
feat(client): 节点列表防误触 — 已连接时切换节点先弹确认
...
未连接(off)点节点直接选→跳连接页(无破坏性,不弹框);已连接/连接中点其他
节点会断开重连,先弹确认框(标题含目标节点名),取消则维持当前连接。新增
nodeSwitchTitle/Body/Confirm 三条文案 + node_connect_confirm_test 覆盖 off/on 两路。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 10:11:20 +08:00
wangjia
6788501e4a
feat(client): 通用自适应弹出菜单(按屏幕位置上/下弹,不挡触发器)
...
新增 AdaptiveMenuButton:GlobalKey 量触发器矩形,据上下剩余空间决定向下/向上
弹出、右对齐裁剪到屏内,Overlay 全屏 barrier + 淡入缩放动画。「我的设备」⋯
菜单由 PopupMenuButton 换成它(重命名 + 强制退出/清除),修正小屏被遮挡问题。
devices_screen_test 同步改用 AdaptiveMenuButton 触发器断言。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 10:11:20 +08:00
wangjia
880fa32793
fix(devices): 本机也显示 ⋯ 菜单(只「重命名」)—— 修单设备无法改名(1.0.14)
...
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 16s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 4s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 15s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m10s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
之前 ⋯ 菜单对本机隐藏,而用户唯一设备就是本机 → 根本点不到、改不了名。
改:本机显示 ⋯ 菜单但只含「重命名」(自我强制退出/清除无意义,仍只对他设备)。
测试:本机菜单只有重命名断言;全量 flutter 绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 09:49:09 +08:00
wangjia
315c343ed5
feat(devices): 设备默认名「平台简写·主机名」+ 支持重命名(1.0.13)
...
ci-pangolin / Lint — shellcheck (push) Successful in 7s
ci-pangolin / OpenAPI Sync Check (push) Successful in 17s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 6s
ci-pangolin / Go — build + test (push) Successful in 11s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m3s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
① 默认名:DeviceIdentity 改「平台简写(Win/Mac/Linux/iOS/Andr)·主机名」,主机名截
到 8、总长≈12(替代裸主机名,更短)。
② 重命名:新端点 POST /v1/me/devices/{uuid}/rename(Service.RenameDevice 校验归属+
截 64);store.UpdateName;客户端 account_api.renameDevice + provider.rename +
「我的设备」⋯ 菜单加「重命名」+ 输入弹窗;l10n(zh/en)。
③ 版本 1.0.13。
测试:server RenameDevice(归属/空名/404)+ 客户端 rename widget;全量 go/flutter 绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 09:12:36 +08:00
wangjia
878cef9e52
build(client): 1.0.12 — 设备下拉接已登录设备 + 版本对齐(pubspec=iss=1.0.12)
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 17s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 6s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m6s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 08:41:37 +08:00
wangjia
8a1db07d19
fix(devices+stats): /v1/me/devices 401 修复 + 设备下拉接已登录设备 + 版本号
...
ci-pangolin / Lint — shellcheck (push) Successful in 9s
ci-pangolin / OpenAPI Sync Check (push) Successful in 19s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 15s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m2s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
① 「我的设备打不开」根因:devices handler 读 devices.CtxKeyUserID,而鉴权中间件
把 user id 写在 auth 的 key 下(类型不同→取不到)→ /v1/me/devices 一直 401。
改 handler 用 auth.UserIDFromContext(与 accountAPI 等一致)。
② 统计页设备下拉改读 devicesProvider(已登录设备),不再只列有用量的设备 →
windows 设备现在会出现。
③ pubspec version 1.0.2+3 → 1.0.11+12,client_version 不再显示陈旧的 v1.0.2。
测试:devices_screen + stats_device_filter widget(下拉读 /v1/me/devices)+全量绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 08:37:11 +08:00
wangjia
ea548ad7cf
fix(deploy): agent 不再随 server 停 —— 解耦 systemd 依赖( #8 静默掉线根因)
...
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 18s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 13s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m3s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
Requires=pangolin-server → Wants=(软依赖);Restart=on-failure → always +
StartLimitIntervalSec=0。根因:Requires= 使每次重启 server 都把 agent 一起拖停
且不自起 → 节点静默 down。agent 本就靠 gRPC 自重连,不该绑 server 生死。
线上 /etc/systemd 已同步 daemon-reload,并重启 server 验证 agent 全程存活+重连。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 08:22:20 +08:00
wangjia
3a8e27b5b0
build(client/windows): 版本 bump 1.0.10 → 1.0.11(设备会话管理+统计时区+设备过滤)
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 16s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 16s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m8s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 08:08:47 +08:00
wangjia
e333f59cb3
feat(stats): #10 第②层 —— 统计页按设备过滤(per-device 本地日曲线)
...
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 19s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 11s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m8s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
镜像账户级时区曲线到「按设备」:
- migration 000018 `usage_device_hourly`(每设备 UTC 小时桶,稀疏)。
- ReportUsage deviceID>0 时加 AccumulateDeviceHourly;NodeStore 接口+impl+mock。
- usage.Store.DeviceHourlyRange(JOIN devices 校验归属+解析 uuid→id);UsageCurve
增 deviceUUID 形参:空=账户级,非空=该设备本地日曲线(分桶逻辑复用)。
- /v1/usage?device=<uuid>;客户端 account_api.usage(device)、usageProvider key 改
记录 (days,device)、stats_page 接 statsDeviceProvider → 选设备即重取该设备曲线。
测试:per-device 曲线隔离+归属校验(A的设备不进B)、UsageCurve(deviceUUID)、
migration v18、客户端 widget(选设备→/v1/usage 带 device=)。全量 go/flutter 绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 08:04:33 +08:00
wangjia
5dcebb77fd
feat(stats): 统计页设备下拉接真实设备( #10 第①层)
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 21s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m6s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
_DeviceDropdown 改 ConsumerWidget:菜单 = 「全部」+ 近 30 天有用量的真实设备名
(来自 deviceUsageProvider);选中态存 statsDeviceProvider。无每设备用量时只显示
「全部」(稀疏,正常)。第②层「按设备过滤月/周/日卡+折线」待 per-device 每日曲线
API(#10 第②层),本提交只接下拉内容。tablet 统计 golden 无变化(空设备时同旧观感)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 07:04:20 +08:00
wangjia
f2499a64e1
fix(usage): 统计按客户端本地日聚合 —— 修「29号却显示28号数据」时区 bug
...
ci-pangolin / Lint — shellcheck (push) Successful in 7s
ci-pangolin / OpenAPI Sync Check (push) Successful in 16s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 4s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m8s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
根因:服务端用量全按 UTC 预切天,UTC+8 用户在中国 0-8 点时 UTC 还是前一天,
「今天」就显示前一天数据。
改法(用户拍板:小时桶+查询带时区偏移):
- migration 000017 `usage_hourly`(UTC 纪元小时整数桶,稀疏存储,空小时不落行)。
- ReportUsage 同时累加 usage_hourly(按 windowEnd 的 UTC 小时);usage_daily 保留作配额/今日。
- `UsageCurve(days, offsetMin)`:读 UTC 小时桶,按客户端时区偏移**重新聚合成本地日**曲线。
- `/v1/usage?tz_offset=分钟`;客户端 `usage()` 带 `DateTime.now().timeZoneOffset.inMinutes`。
- 客户端早已「取曲线最后一点当今日」,故只改服务端聚合 + 带偏移即可。
测试:store 时区分桶证明(UTC 18:00 在 UTC vs UTC+8 落不同本地日,锁住 bug 修复)+
migration v17 + usage_hourly 表;集成测试改喂 hourly;全量 go/flutter test 绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 07:02:04 +08:00
wangjia
606e5e9e54
docs(plan): P4 收口 —— 每设备归因链路已交付,展示层过滤归 #10
...
每设备流量归因基础设施由 P1-P3 完整交付(注册→dp_uuid→usage_device_daily,
store 测试已锁)。统计页设备下拉「真过滤」需 per-device 每日曲线 API(现 provider
只给窗口聚合,对不齐月/周/日卡),归入统计整改 #10;端到端需真连客户端人工验证。
不做 ConnectNode 兜底(登录已注册;connect 体无 name/platform)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 06:14:19 +08:00
wangjia
58526b09e6
feat(client): P6 DevicesScreen 重做 + DevicePlatform 枚举
...
ci-pangolin / Lint — shellcheck (push) Successful in 7s
ci-pangolin / OpenAPI Sync Check (push) Successful in 19s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 7s
ci-pangolin / Flutter — analyze + test (push) Successful in 23s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m12s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
回应「状态码用枚举更好」:新增 DevicePlatform 枚举(线格式 fromWire 解析,
UI 只碰枚举,穷尽 switch),Device.platformKind getter;platform 图标按枚举 switch。
DevicesScreen 按 §7 视觉稿重做:行内 名称+「本机」标 / 平台·客户端版本·最后登录 /
在线绿点光晕·离线灰点 + 行尾 ⋯ 菜单(强制退出 / 清除登录信息·危险红)+ 危险二次
确认弹窗;本机行不显示 ⋯(不自我踢)。l10n 新增在线/离线/最后登录/从未登录/强制
退出/清除登录信息/取消 + 确认文案(中英);「当前设备」改「本机」。
新图标 moreVertical/trash/alertTriangle。localDeviceIdProvider 供本机判定。
测试:devices_screen widget 3 例(本机标+在线/离线+版本渲染 / ⋯菜单→强制退出→
确认→POST logout / 清除→DELETE);全量 flutter test 58 绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 06:10:37 +08:00
wangjia
bcc114088c
feat(devices): P3 强制退出 + 清除增强(per-device 凭证吊销)
...
ci-pangolin / Lint — shellcheck (push) Successful in 9s
ci-pangolin / OpenAPI Sync Check (push) Successful in 17s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 26s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 12s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 15s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m4s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
后端:新端点 POST /v1/me/devices/{uuid}/logout(ForceLogout:吊销该设备会话+
丢 Redis JTI,设备留列表)。DeleteDevice 增强:先吊销会话再删设备(FK ON DELETE
CASCADE 清理会话行)+ 按 dp_uuid 吊销数据面凭证。CredentialRevoker 接口改
per-device RevokeDevice(dpUUID),由 nodes.Service 实现(查 connect_credentials
持有节点→推 CommandTypeRevoke + 删凭证行),main 注入替 NoopRevoker;devices 注入
SessionPort/JTIRevoker。修 SQLite 跨连接死锁(会话吊销移到 delete tx 之前)。
migration 000016 sessions FK 加 ON DELETE CASCADE。
客户端:account_api.forceLogout + devicesProvider.forceLogout(UI 留 P6)。
测试:ForceLogout(吊销会话+JTI+设备保留+403/404)+ DeleteDevice(级联+按 dp_uuid
吊销);NoopRevoker 改 dp_uuid;全量 server/flutter 测试绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 06:01:41 +08:00
wangjia
2f298f0a0a
feat(devices): P2 sessions 表 + 在线/最后登录/客户端版本
...
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 18s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 11s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m13s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
migration 000016(mysql+sqlite,含 down):新增 sessions 表(绑 device+refresh JTI)
+ devices 加 client_version/totp_trusted_until。devices 唯一键改 + platform CHECK
加 linux(需 SQLite 表重建)拆出后续迁移,降风险。
后端:新 internal/sessions Store(Create/Rotate/Revoke/RevokeByDevice/
LastLoginByDevice);TokenManager 外露 refresh JTI(IssueWithJTI/RefreshWithJTI/
ParseRefreshJTI);auth.Service 注入 SessionStore——登录建会话、刷新轮换、登出吊销;
DeviceRegistrar 返回 deviceID;ReportUsage 心跳 touch devices.last_seen(在线判定);
devices.ListDevices 经 LastLoginSource 注入返回 online(last_seen<3min)/client_version/
last_login;RegisterIfAbsent 存 client_version。
客户端:Device model 加 online/clientVersion/lastLogin(fromJson 自动解析)。
测试:sessions store 3 例 + ListDevices 在线/最后登录 + device model 2 例 +
migration v16;全量 go test/flutter test 绿。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 00:50:24 +08:00
wangjia
8370ee1eb7
chore: 删除误入库的一次性临时文件(tmphash / zz_tmpverify_test)
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 17s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 23s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m9s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
P1 提交时 git add -A 误带入早期改密码调试残留(注释自标「临时,不提交」)。
2026-06-29 00:28:54 +08:00
wangjia
c0c4b94e29
feat(devices): P1 设备注册打通 —— 登录/注册即写 devices 表
...
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 16s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 7s
ci-pangolin / Flutter — analyze + test (push) Successful in 26s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Failing after 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 15s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m10s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
后端:auth.Service 加 DeviceMeta + DeviceRegistrar 接口(consumer-side 解耦),
Login/Register 成功签发后 best-effort 注册设备(不强制设备上限,避免免费档重装
churn 锁死用户);handler 加 device 请求体;main 用 authDeviceRegistrar 适配
devices.Service 注入;normalizePlatform 加 linux。
客户端:新 device_identity.dart(SecureKV 接缝 + 稳定 UUIDv4 device_id 持久化 +
名称/平台/版本);弃用硬编码 'mac-001';auth_api login/register + connect 携带
device 元数据。加 uuid + device_info_plus 依赖。
测试:auth 设备注册(触发/best-effort/空 meta) + device_identity(生成/持久/
读失败不重生成/UUIDv4 形态);normalizePlatform linux=true。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 00:28:13 +08:00
wangjia
889cff4556
docs(plan): 设备&会话管理 实现计划 P1-P6(md执行源 + html阅读版 + 登记 + 链接)
...
新增 docs/superpowers/plans/2026-06-29-device-session-management.md(执行真相,
checkbox) + docs/device-session-management-plan.html(阅读版);登记进 index.html
「实现计划」;总方案顶部加「→ 实现计划」链接。P1 设备注册打通→P2 sessions表+
在线→P3 强制退出/清除→P4 每设备流量→P5 2FA(future)→P6 UI重做。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 00:15:35 +08:00
wangjia
7fd2fed441
docs(design): §7 UI 改真实 token 视觉稿(替换字符画)
...
用 design/colors_and_type.css 真实色值(clay/sand 暖色浅色主题)做 HTML/CSS
还原稿,替换粗糙 ASCII:A 设备列表(在线绿点光晕/离线灰点+最后登录/本机标)
+ B 行尾 ⋯ 操作菜单(强制退出/清除登录信息危险红) + C 清除危险二次确认弹窗。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 00:05:15 +08:00
wangjia
e8261e8984
docs(design): 换用户uuid不变(唯一键改 UNIQUE(user_id,uuid)) + 按设备去重健壮性
...
§3.2.1 ⑤:device_id 安装级、与账户无关→换用户不变;故 devices 唯一键须从
全局 UNIQUE(uuid) 改为 UNIQUE(user_id,uuid)(000016),同机两账号=两行各自
dp_uuid。⑥:别用终身严格去重,改按活跃/在线计数+N天自动回收+用户自助清理。
§3.2 schema/表同步标注唯一键变更。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 23:54:52 +08:00
wangjia
a3731ce11c
docs(design): 补 device uuid 生成机制(随机UUIDv4+安全存储+重装影响)
...
§3.2.1 ④:uuid=客户端首启 Uuid().v4() 随机生成、立即写 flutter_secure_storage
跨重启恒定;不绑硬件ID(五端唯一可靠合规);各平台安全区存储 + 卸载重装影响
(iOS Keychain 保留/Android 清);对设备计数的含义。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 23:46:37 +08:00
wangjia
c1994ad048
docs(design): devices 表补全字段 + name来源/三时间戳/按设备限登录数 释疑
...
§3.2 列出 devices 完整 9 列(含来源迁移 + platform CHECK 需加 linux);
新增 §3.2.1:① name 由客户端 device_info_plus 按平台取(主机名/机型)上报;
② created_at/last_seen/最后登录(session) 三时间戳辨析;③ 设备身份键
(user_id,uuid) + RegisterIfAbsent maxDevices 作「按设备控制登录数」抓手
(累计 vs 同时在线两种口径)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 23:43:37 +08:00
wangjia
31ac76e3d5
docs(design): 设备&会话管理 + 每设备流量归因 全局设计(HTML)
...
新增 docs/device-session-management-design.html 并登记进 docs/index.html
「设计方案」分类。覆盖三端:控制面 sessions 表绑设备 + RegisterIfAbsent
接线、数据面每设备 dp_uuid 记账(usage_device_daily)、前端「我的设备」
(在线/客户端版本/最后登录 + 强制退出/清除登录信息)。核心洞察:后端大半
已建但 RegisterIfAbsent 未接线致 devices 表空。含 P1–P5 实现路线。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 23:29:47 +08:00
wangjia
0bc39ebeba
docs(claude): 更新节点信息 racknerd → pangolin1(已迁移)
...
ci-pangolin / Lint — shellcheck (push) Successful in 7s
ci-pangolin / OpenAPI Sync Check (push) Successful in 30s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 23s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 4s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 6s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m20s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
线上节点已从 RackNerd 107.172.55.251(别名 racknerd)迁到
pangolin1 103.119.13.48(Debian12,2核/~1GB/2G swap),单机跑
server+agent+sing-box。旧别名/IP 标注作废。deploy 示例命令同步改名。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 22:54:11 +08:00
wangjia
c550eea5d8
feat(client/auth): 登录/注册页 Enter 键导航与提交
...
登录:邮箱框回车 → 跳到密码框;密码框回车 → 直接登录(校验条件同主按钮)。
注册:邮箱框回车 → 发送验证码并聚焦验证码框;验证码满 6 位回车 → 进入设密码步
并聚焦密码框;密码框(≥6 位)回车 → 直接注册。
经 TextField.onSubmitted + FocusNode.requestFocus 实现;桌面端回车即触发。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 22:44:34 +08:00
wangjia
7dcbe04934
build(client/windows): 版本 bump 1.0.9 → 1.0.10(输入框聚焦橙边修复)
...
ci-pangolin / Lint — shellcheck (push) Successful in 10s
ci-pangolin / OpenAPI Sync Check (push) Successful in 19s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 7s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 17s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m14s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 22:33:52 +08:00
wangjia
25e8330e3b
fix(client): 修聚焦时输入框橙边漏出错位/被裁(登录·注册·搜索·兑换码)
...
ci-pangolin / Lint — shellcheck (push) Successful in 10s
ci-pangolin / OpenAPI Sync Check (push) Successful in 31s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 18s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m13s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
主题 inputDecorationTheme 设了 focusedBorder: OutlineInputBorder(accent),
而登录/注册的邮箱·密码·验证码、节点页搜索框、兑换码框这几处的 TextField
只写 border: InputBorder.none、未覆盖 focusedBorder —— 聚焦瞬间主题的橙色
OutlineInputBorder 漏到内层 TextField 上,与外层自定义容器圆角错位/左右被裁。
统一加共享 kBareInput 装饰(pangolin_theme.dart)关掉所有边框状态泄漏,
四处替换。只压边框、不动 filled/fillColor —— 未聚焦态外观与改前一致,
不动 golden;聚焦指示仍由外层容器自己的 Border.all(accent) 负责。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 22:21:50 +08:00
wangjia
1adf088c68
build(client/windows): 版本 bump 1.0.8 → 1.0.9(节点页刷新)
...
ci-pangolin / OpenAPI Sync Check (push) Successful in 20s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 16s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m13s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
ci-pangolin / Lint — shellcheck (push) Failing after 11m42s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 22:00:26 +08:00
wangjia
0542ff027f
feat(client/nodes): 节点页刷新 — 下拉刷新 + 刷新按钮 + 进页刷新 + 10s 限流
...
- nodesProvider.refresh:10s 限流(下拉/按钮/进页多次触发只打一次远端);
不清空当前列表(后台拉、好了再换,失败保留旧数据),避免进页/下拉闪空
- nodes_page:initState 进页自动刷一次;RefreshIndicator 下拉刷新(移动端);
搜索框右侧 _RefreshButton 点击刷新(刷新中 spinner)
servers 页 golden 重生成(搜索行加按钮);CI 闸 golden 未动。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 22:00:26 +08:00
wangjia
51c171d815
build(client/windows): 版本 bump 1.0.7 → 1.0.8(节点 status 渲染等)
...
ci-pangolin / Lint — shellcheck (push) Successful in 7s
ci-pangolin / OpenAPI Sync Check (push) Successful in 23s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 18s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m17s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 21:47:54 +08:00
wangjia
8049659660
feat(client): 节点 status=down 在列表置灰+「不可用」+禁选( #7 客户端侧)
...
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 24s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 18s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m18s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 13s
#7 服务端已在 agent 离线时把节点判 down,但客户端 Node 模型没读 status、
列表照常显示。补:Node.status 字段 + 解析 /v1/nodes 的 status;ServerTile/
_NodeGridTile 在 isDown 时 Opacity 置灰 + 末尾「不可用」+ onTap 禁用。全平台
共享(lib/widgets+screens)。up 节点 Opacity 1.0 无变化,golden 不动。加 down
状态 widget 测试。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 21:35:52 +08:00
wangjia
f0832ccfcb
fix(client): 修 pro 会员启动闪广告/统计闪 0 — 加载门覆盖 auth 加载窗口
...
ci-pangolin / Lint — shellcheck (push) Successful in 6s
ci-pangolin / OpenAPI Sync Check (push) Successful in 21s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 7s
ci-pangolin / Flutter — analyze + test (push) Successful in 23s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 18s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m52s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
之前 meLoadingProvider=isLoading&&!hasValue 漏了两段:启动时 auth 异步读 token
期间 isLoggedIn=false → me 同步返回免费默认(广告);token 到后 me 拉真实值时
hasValue 已是免费默认 → !hasValue 不成立、仍不转圈。改为:
- meLoadingProvider:auth.isLoading 时转圈;未登录不转;已登录看 me.isLoading
- 统计页 loading:auth.isLoading || usageProvider.isLoading
未登录(确定访客)/golden(settle 后)不转圈,golden 不受影响。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 21:12:24 +08:00
wangjia
3785fdf1c1
style(client/shell): 会员卡字体调小,有效期完整显示
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 21s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 16s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m16s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
有效期行被 chevron 挤得截断。套餐名 12→11.5、有效期 10.5→9.5、chevron 15→14、
间距 10→9,让「有效期 YYYY-MM-DD」完整显示。golden 重生成。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 21:06:06 +08:00
wangjia
e27bbbd384
build(client/windows): 版本 bump 1.0.6 → 1.0.7(我的入口纠正)
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 21s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 23s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 8s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 16s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m27s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 13s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 20:33:30 +08:00
wangjia
2c5e8785c0
fix(client/shell): 「我的」入口改到底部会员卡(非顶部品牌)
...
按反馈纠正:顶部品牌区改回静态;底部 PlanBadgeCard(套餐/会员卡)做成可点 →
打开「我的」,选中态高亮 + 末尾 chevron。桌面/平板页 golden 重生成。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 20:33:30 +08:00
wangjia
09eab3b3b6
build(client/windows): installer 版本 bump 1.0.5 → 1.0.6(折线图/加载转圈/侧栏改版)
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 21s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 7s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 20s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m18s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 20:26:56 +08:00
wangjia
b1dd78fddd
feat(client/shell): 侧栏改版 — 我的移到顶部品牌按钮 + 联系放设置下面
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 20s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 23s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 17s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m16s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
- 顶部品牌区(logo+穿山甲)做成可点按钮 → 打开「我的」,选中态高亮;
从导航列表移除「我的」项(desktop+tablet)
- desktop 导航顺序:…统计 → 设置 → 联系(联系移到设置下面)
桌面/平板页 golden 重生成(CI 闸 components/auth 未动)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 20:24:03 +08:00
wangjia
ea1af967a0
fix(client): 统计页/连接页 加载时整页转圈,先拉数据再渲染(不闪默认态)
...
ci-pangolin / Lint — shellcheck (push) Successful in 5s
ci-pangolin / OpenAPI Sync Check (push) Successful in 17s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 22s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m11s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
之前 .valueOrNull ?? 默认 → 数据没到时先渲染默认态(统计 0 / 连接页免费广告),
me/usage 到了再跳真实态,闪烁体验差。改为关键 provider 首拉(loading 且无缓存)时
整页 CircularProgressIndicator:
- 统计页:gate on usageProvider(30)
- 连接页:gate on 新增 meLoadingProvider(me 是常驻 Notifier,只首启转一下)
未登录/golden 场景 me 同步返回默认=不加载,不影响 golden。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 20:17:39 +08:00
wangjia
07f09a1600
feat(client/stats): 两周流量折线图加 Y轴刻度 + X轴日期 + 14个数据点
...
ci-pangolin / Lint — shellcheck (push) Successful in 9s
ci-pangolin / OpenAPI Sync Check (push) Successful in 16s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 22s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 8s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m18s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 13s
之前折线太简单(只一条线+末点)。增强 UsageLineChart:
- Y 轴:3 条网格 + 左侧 GB 刻度(max/mid/0)
- X 轴:隔几天标一个日期(M/D,始终含末点)
- 14 个数据点全画出(surface 光晕+accent 实心,末点加大)
传入每点日期(chartDates)。token 色经参数传入(axis=fg3/surface),零硬编码。
统计页 golden 重生成。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 20:12:30 +08:00
wangjia
ed22965d18
chore(todo): 合并本地 main 的 2 个 open 待办(golden 清理 + 协议选择)
...
ci-pangolin / Lint — shellcheck (pull_request) Successful in 8s
ci-pangolin / OpenAPI Sync Check (pull_request) Successful in 17s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 5s
ci-pangolin / Flutter — analyze + test (pull_request) Successful in 22s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Successful in 4s
ci-pangolin / Go — build + test (pull_request) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (pull_request) Successful in 4m17s
ci-pangolin / Golden — 视觉回归 (components + auth) (pull_request) Successful in 13s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 19:28:08 +08:00
wangjia
0698dc6138
chore(todo): 更新 TODO 看板(stats-overhaul 收口期新增条目)
...
ci-pangolin / Lint — shellcheck (push) Successful in 10s
ci-pangolin / OpenAPI Sync Check (push) Successful in 16s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 29s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 12s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 13s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m22s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
ci-pangolin / Lint — shellcheck (pull_request) Successful in 4s
ci-pangolin / OpenAPI Sync Check (pull_request) Successful in 18s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 6s
ci-pangolin / Flutter — analyze + test (pull_request) Successful in 21s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Successful in 5s
ci-pangolin / Go — build + test (pull_request) Successful in 8s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (pull_request) Successful in 4m17s
ci-pangolin / Golden — 视觉回归 (components + auth) (pull_request) Successful in 13s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 18:14:05 +08:00
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
wangjia
b98ad9dce4
chore(design): stats-overhaul 设计 WIP — CONTRACT + ui_kits 统计页规格
...
stats-overhaul 的设计稿(CONTRACT.md + mobile/tablet/desktop ui_kits)。
注:这批 ui_kits 描述的是统计页「上聚合·下分设备」原方案;统计页后续已
重设计为「月/周/日 周期卡 + 设备下拉 + 两周折线」(见 client/lib/screens/
stats_page.dart)。设计稿与新页布局有出入,待更新到新布局(单列 TODO 跟踪)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 18:13:49 +08:00
wangjia
bf84492eef
feat(client/native): stats-overhaul Phase1 — 四端实时统计采集端
...
各原生侧把 libbox/Clash 的实时上下行/延迟经冻结的 pangolin/vpn/stats channel
生产真实帧:
- iOS/macOS 新增 StatsClient.swift(LibboxNewCommandClient,statusInterval 1s,
uplink/downlink/总量 + urltest 延迟映射契约字段),VpnManager/VpnChannel 状态
观察驱动 start/stop,pbxproj 登记。
- Android PangolinVpnService.kt 延迟修复。
契约字段 uploadBytes/downloadBytes/uploadSpeed/downloadSpeed/urltestResults 不改。
真机验证(连接后实时跳动)为运行时步骤,见计划 Phase1 待办。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 18:13:48 +08:00
wangjia
636a3bbf2f
feat(server/stats): stats-overhaul Phase2 — 每设备归因 + GB 综合配额
...
服务端记账从「账户」细到「每设备」(每设备独立 dp_uuid),配额单位分钟→GB
按账户综合卡控。000015_per_device_usage 迁移(mysql+sqlite 双份):devices.dp_uuid
+ usage_device_daily 表 + plans.daily_mb。handler_grpc 按 dp_uuid 回映射
(user_id,device_id) 双写账户+每设备;usage 服务/handler 暴露 /v1/usage(/devices)。
含 sqlite_per_device / usage handler 测试。
注:此迁移 prod 已 migrate up 运行、部署二进制已内嵌;本次补提交使 git 与线上一致。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 18:12:00 +08:00