Files
Xboard/.helloagents/archive/2026-04/202604290123_node-traffic-yesterday-stats/proposal.md
T
yinjianm e847252e12 fix(api): 修复节点流量限额共享统计与父子显隐联动
统一节点流量统计与限额展示口径,节点详情新增昨日流量,
并让今日、昨日和本月使用清晰的半开时间窗口聚合

同 machine_id 或同 host 的节点现在共享当前账期已用流量,
管理端优先使用后端 traffic_limit_snapshot 展示月额度状态,
mi-node 下发的 current_used 也改为共享账期统计

新增 parent_auto_hidden 标记与父节点显隐联动服务,父节点
因自动上线或流量限额变为不可展示时会隐藏当前显示的子节点,
恢复时只恢复这批自动隐藏的子节点,避免覆盖手动操作
2026-04-29 02:24:57 +08:00

182 lines
7.3 KiB
Markdown
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.
# 变更提案: node-traffic-yesterday-stats
## 元信息
```yaml
类型: 修复 + 新功能
方案类型: implementation
优先级: P1
状态: 已规划
创建: 2026-04-29
```
---
## 1. 需求
### 背景
管理后台 `#/nodes` 的节点流量详情卡当前展示“今日 / 本月 / 累计”。用户反馈某节点“今日下行很多,但本月上行最多”看起来不匹配,并要求统计加入“昨日”。
### 目标
- 核对节点统计的上行/下行字段映射,确认是否存在前后端反转或聚合口径错误。
- 在节点流量详情卡中新增“昨日”统计,口径与“今日”一致。
- 收紧统计窗口边界,保证“今日 / 昨日 / 本月 / 累计”各自窗口清晰。
### 约束条件
```yaml
时间约束:
性能约束: 节点列表接口仍按当前批量聚合方式查询,避免逐节点查询
兼容性约束: 保持现有 traffic_stats.today/month/total 字段兼容,新增 yesterday 字段
业务约束: 不改变 StatServer.u/d 的含义,不迁移历史数据
```
### 验收标准
- [ ] `server/manage/getNodes` 响应中的 `traffic_stats` 包含 `yesterday`
- [ ] `today` 只统计当天 `[today, tomorrow)``yesterday` 只统计 `[yesterday, today)``month` 只统计 `[monthStart, nextMonthStart)`
- [ ] 前端节点流量详情卡按“今日 / 昨日 / 本月 / 累计”展示。
- [ ] 后端测试覆盖新窗口边界,前端构建通过。
---
## 2. 方案
### 技术方案
`ManageController` 内扩展节点流量窗口构建:
- `emptyNodeTrafficStats()` 增加 `yesterday` 默认值。
- `buildNodeTrafficStats()` 使用 `strtotime('today')``strtotime('tomorrow')``strtotime('yesterday')` 和下月月初计算窗口。
- `fillTrafficWindow()` 支持可选结束时间,查询使用半开区间:`record_at >= startAt``record_at < endAt`
前端同步:
- `AdminNodeTrafficStats` 增加 `yesterday: TrafficAmount`
- `NodeTrafficDetail.key` 增加 `yesterday`
- `getNodeTrafficDetails()` 在“今日”和“本月”之间插入“昨日”。
测试:
- 新增/扩展 `ManageController` 单元测试,通过反射调用私有构建方法,构造跨天、跨月和未来记录,验证各窗口不会互相污染。
### 影响范围
```yaml
涉及模块:
- admin-frontend: 节点流量详情卡类型与展示行
- backend-admin-api: 节点列表接口 traffic_stats 聚合窗口
- tests: 节点统计窗口单元测试
预计变更文件: 4-6
```
### 风险评估
| 风险 | 等级 | 应对 |
|------|------|------|
| 历史数据中 u/d 语义本身来自节点端上报,若节点端上报方向定义与面板相反,面板无法单独纠正 | 中 | 本次只核对面板字段链路;不改变历史语义,避免误修 |
| 新增窗口可能增加查询次数 | 低 | 仍为按 server_id 批量聚合,仅从 3 个窗口增至 4 个窗口 |
| 月统计加入上界后不再包含未来 record_at | 低 | 这是更严格的窗口口径,符合预期 |
### 方案取舍
```yaml
唯一方案理由: 后端统一输出 yesterday 字段,前端只按接口字段展示,可以保持统计口径单一且兼容现有调用方。
放弃的替代路径:
- 仅前端用 today/month/total 推导昨日: 无法准确还原昨日上行/下行。
- 修改 StatServerJob 的 u/d 写入方向: 当前面板链路内 u=上行、d=下行一致,贸然反转会破坏历史数据和用户统计。
- 新增独立节点详情接口: 本次只影响列表详情卡,新增接口会扩大维护面。
回滚边界: 可独立回退 ManageController 的 yesterday/window 变更、前端类型/展示变更和测试文件,不涉及数据库迁移。
```
---
## 3. 技术设计
### API 设计
#### GET server/manage/getNodes
- **响应新增字段**: `traffic_stats.yesterday`
- **结构**:
```json
{
"traffic_stats": {
"today": {"upload": 0, "download": 0, "total": 0},
"yesterday": {"upload": 0, "download": 0, "total": 0},
"month": {"upload": 0, "download": 0, "total": 0},
"total": {"upload": 0, "download": 0, "total": 0}
}
}
```
### 数据模型
不新增数据表或字段,继续读取 `v2_stat_server` 的日统计记录:
| 字段 | 类型 | 说明 |
|------|------|------|
| `u` | bigint | 上行流量 |
| `d` | bigint | 下行流量 |
| `record_at` | int | 日统计归属日的 00:00:00 Unix 时间戳 |
| `record_type` | char | 本节点页只读取 `d` |
---
## 4. 核心场景
### 场景: 节点流量详情卡查看昨日统计
**模块**: admin-frontend
**条件**: 管理员打开 `#/nodes` 并悬停节点名称
**行为**: 前端读取 `traffic_stats.yesterday` 并渲染“昨日”行
**结果**: 管理员可以直接对比今日、昨日、本月和累计的上行/下行分布
### 场景: 节点列表接口按清晰窗口聚合
**模块**: backend-admin-api
**条件**: `v2_stat_server` 存在昨天、今天、本月其他日期和未来日期记录
**行为**: `server/manage/getNodes` 构建半开时间窗口
**结果**: 今日、昨日、本月统计互不串窗,累计仍覆盖全部历史记录
---
## 5. 技术决策
### node-traffic-yesterday-stats#D001: 保持 u/d 语义并新增后端 yesterday 字段
**日期**: 2026-04-29
**状态**: ✅采纳
**背景**: 用户反馈上行/下行看起来不匹配,同时要求加入昨日统计。代码链路显示前端、接口和入库任务均使用 `u=upload``d=download`
**选项分析**:
| 选项 | 优点 | 缺点 |
|------|------|------|
| A: 后端新增 `traffic_stats.yesterday` 并收紧窗口 | 口径统一、可测试、兼容当前字段 | 增加一个聚合查询 |
| B: 前端推导昨日 | 不改后端 | 无法准确得到昨日上行/下行 |
| C: 反转 u/d 字段 | 可能符合某些节点端方向理解 | 会破坏现有面板语义和历史统计 |
**决策**: 选择方案 A
**理由**: 问题核心是缺少可对比的昨日窗口和窗口边界不够明确,不是面板链路内字段反转。
**影响**: `server/manage/getNodes` 响应字段增加,节点页详情卡增加一行展示。
---
## 6. 验证策略
```yaml
verifyMode: test-first
reviewerFocus:
- app/Http/Controllers/V2/Admin/Server/ManageController.php 的窗口边界和兼容字段
- admin-frontend/src/utils/nodes.ts 的展示顺序与空值兜底
testerFocus:
- php artisan test --filter NodeTrafficStatsTest
- npm run buildadmin-frontend
uiValidation: optional
riskBoundary:
- 不执行数据库删除、重置或生产环境操作
- 不修改历史 StatServer 数据
```
---
## 7. 成果设计
### 设计方向
- **美学基调**: 延续现有 Apple 风格节点详情卡,新增“昨日”作为同等层级数据行,不引入额外视觉系统。
- **记忆点**: 今日与昨日紧邻展示,便于直接比较日流量方向变化。
- **参考**: 现有节点流量 popover。
### 视觉要素
- **配色**: 沿用现有白底、浅灰行底和蓝色总量强调。
- **字体**: 沿用现有管理端字体栈,不新增字体依赖。
- **布局**: 维持纵向统计行结构,顺序为今日、昨日、本月、累计。
- **动效**: 沿用 Element Plus Popover 行为,不新增动效。
- **氛围**: 与当前节点页一致。
### 技术约束
- **可访问性**: 不改变现有 hover/focus 触发方式。
- **响应式**: Popover 宽度维持现状,新增一行不改变表格布局。