fix(api): 修复节点流量限额共享统计与父子显隐联动
统一节点流量统计与限额展示口径,节点详情新增昨日流量, 并让今日、昨日和本月使用清晰的半开时间窗口聚合 同 machine_id 或同 host 的节点现在共享当前账期已用流量, 管理端优先使用后端 traffic_limit_snapshot 展示月额度状态, mi-node 下发的 current_used 也改为共享账期统计 新增 parent_auto_hidden 标记与父节点显隐联动服务,父节点 因自动上线或流量限额变为不可展示时会隐藏当前显示的子节点, 恢复时只恢复这批自动隐藏的子节点,避免覆盖手动操作
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 5,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 5,
|
||||
"percent": 100,
|
||||
"current": "节点昨日流量统计已实现并完成验证",
|
||||
"updated_at": "2026-04-29 01:50:00"
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
# 变更提案: 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 build(admin-frontend)
|
||||
uiValidation: optional
|
||||
riskBoundary:
|
||||
- 不执行数据库删除、重置或生产环境操作
|
||||
- 不修改历史 StatServer 数据
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: 延续现有 Apple 风格节点详情卡,新增“昨日”作为同等层级数据行,不引入额外视觉系统。
|
||||
- **记忆点**: 今日与昨日紧邻展示,便于直接比较日流量方向变化。
|
||||
- **参考**: 现有节点流量 popover。
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 沿用现有白底、浅灰行底和蓝色总量强调。
|
||||
- **字体**: 沿用现有管理端字体栈,不新增字体依赖。
|
||||
- **布局**: 维持纵向统计行结构,顺序为今日、昨日、本月、累计。
|
||||
- **动效**: 沿用 Element Plus Popover 行为,不新增动效。
|
||||
- **氛围**: 与当前节点页一致。
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 不改变现有 hover/focus 触发方式。
|
||||
- **响应式**: Popover 宽度维持现状,新增一行不改变表格布局。
|
||||
@@ -0,0 +1,84 @@
|
||||
# 任务清单: node-traffic-yesterday-stats
|
||||
|
||||
> **@status:** completed | 2026-04-29 01:37
|
||||
|
||||
```yaml
|
||||
@feature: node-traffic-yesterday-stats
|
||||
@created: 2026-04-29
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## LIVE_STATUS
|
||||
|
||||
```json
|
||||
{"status":"completed","completed":5,"failed":0,"pending":0,"total":5,"percent":100,"current":"节点昨日流量统计已实现并完成验证","updated_at":"2026-04-29 01:50:00"}
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 5 | 0 | 0 | 5 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 后端统计窗口
|
||||
|
||||
- [√] 1.1 修改 `app/Http/Controllers/V2/Admin/Server/ManageController.php`
|
||||
- 预期变更: `traffic_stats` 增加 `yesterday`,今日/昨日/本月使用半开时间窗口聚合。
|
||||
- 完成标准: 接口保留 `today/month/total`,新增 `yesterday`,空数据返回 0。
|
||||
- 验证方式: `php -l app/Http/Controllers/V2/Admin/Server/ManageController.php`; `vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit/Admin/NodeTrafficStatsWindowTest.php`
|
||||
- depends_on: []
|
||||
- 完成备注: 已新增 `resolveNodeTrafficWindows()` 并让 `fillTrafficWindow()` 使用 `record_at >= start` 与 `record_at < end` 的半开窗口。
|
||||
|
||||
### 2. 前端展示
|
||||
|
||||
- [√] 2.1 修改 `admin-frontend/src/types/api.d.ts`
|
||||
- 预期变更: `AdminNodeTrafficStats` 类型增加 `yesterday: TrafficAmount`。
|
||||
- 完成标准: TypeScript 类型与后端响应字段一致。
|
||||
- 验证方式: `npm run build`
|
||||
- depends_on: [1.1]
|
||||
- 完成备注: `AdminNodeTrafficStats` 已包含 `yesterday`。
|
||||
- [√] 2.2 修改 `admin-frontend/src/utils/nodes.ts`
|
||||
- 预期变更: `getNodeTrafficDetails()` 在今日后展示昨日。
|
||||
- 完成标准: 节点详情卡顺序为今日、昨日、本月、累计,缺失字段时显示 0。
|
||||
- 验证方式: `npm run build`
|
||||
- depends_on: [2.1]
|
||||
- 完成备注: 节点流量详情顺序已调整为今日、昨日、本月、累计。
|
||||
|
||||
### 3. 验证与知识库
|
||||
|
||||
- [√] 3.1 新增或更新后端单元测试
|
||||
- 预期变更: 覆盖今日、昨日、本月和累计窗口边界。
|
||||
- 完成标准: 测试能证明未来记录不进入今日/月统计,昨日记录独立统计。
|
||||
- 验证方式: `vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit/Admin/NodeTrafficStatsWindowTest.php`
|
||||
- depends_on: [1.1]
|
||||
- 完成备注: 已新增窗口边界单元测试,覆盖普通日期和月初日期。
|
||||
- [√] 3.2 执行构建/测试并同步知识库
|
||||
- 预期变更: 运行可用验证命令,更新 `.helloagents` 模块文档和变更日志。
|
||||
- 完成标准: 验证结果记录在执行日志,知识库反映 `traffic_stats.yesterday`。
|
||||
- 验证方式: 文件检查 + 命令输出
|
||||
- depends_on: [2.2, 3.1]
|
||||
- 完成备注: 已通过 PHP 语法检查、PHPUnit 单元测试和管理端前端构建,知识库与 CHANGELOG 已同步。
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-29 01:23:00 | DESIGN | in_progress | 已完成上下文收集和方案包创建 |
|
||||
| 2026-04-29 01:38:00 | DEVELOP 1.1 | completed | 后端新增 yesterday 窗口并收紧 today/month 上界 |
|
||||
| 2026-04-29 01:40:00 | DEVELOP 2.1-2.2 | completed | 前端类型和节点详情卡展示已加入“昨日” |
|
||||
| 2026-04-29 01:44:00 | DEVELOP 3.1 | completed | 新增节点流量窗口边界单元测试 |
|
||||
| 2026-04-29 01:50:00 | DEVELOP 3.2 | completed | 验证命令通过,知识库同步完成 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
- 面板链路中 `StatServer.u` 对应上行、`StatServer.d` 对应下行;本次不反转历史语义。
|
||||
- 用户截图中的“今日下行多、本月上行多”本身可能是正常数据分布,因为本月包含今天及之前日期;新增昨日后便于判断差异来自哪一天。
|
||||
Reference in New Issue
Block a user