Files
JNetApplet/docs/project-review.md
T
Jokul af7ae6b334 fix: 计数器回绕/重置时钳制负速度为0
网卡重启、/proc/net/dev 计数器溢出或接口重置时,字节差值为负,
QML 会显示负速度。对 rxDelta/txDelta 钳制为 0 避免此问题。
2026-07-23 00:06:43 +08:00

124 lines
8.6 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.
# JNetApplet 项目审查清单
> 审查日期:2026-07-22
> 审查范围:全部源码(C++ 后端 + QML 前端 + 构建脚本 + 文档)
---
## 一、缺陷(Bug / 逻辑错误)
### 🔴 高优先级
**1. ~~速度计算假设定时间隔严格为 1 秒~~ ✅ 已修复**
~~`calculateSpeed()` 直接用 `currentRxBytes - m_lastRxBytes` 作为 bytes/sec,未除以实际流逝时间。系统负载高或定时器抖动时,速度值会失真。~~
已改为记录上次采样的毫秒时间戳 `m_lastTimestampMs`,按真实流逝时间 `delta_bytes / elapsed_seconds` 计算速度;速度存储由 `qint64` 改为 `double` 保留精度;`elapsedSec > 0` 守卫避免除零。
**2. ~~计数器回绕/重置产生负速度~~ ✅ 已修复**
~~网卡重启、`/proc/net/dev` 计数器溢出或接口重置时,`currentRxBytes - m_lastRxBytes` 可能为负。代码无任何兜底,QML 会显示负速度。~~
已在 `calculateSpeed()` 中对 `rxDelta` / `txDelta` 钳制为 0,计数器回绕/接口重置/网卡重启时不再产生负速度。
**3. "总量统计"语义有误导**
`m_totalDownload = currentRxBytes` 只存储活动接口的当前计数器值,并非真正的累计流量。它会在以下场景跳变:切换网卡(跳到新接口计数器)、网卡重启(归零)、系统重启(归零)。README 宣称"累计上传/下载流量统计",但实际不是跨重启/跨接口的累计。
**4. 独立窗口不支持深色模式**
`AboutWindow.qml``SettingsWindow.qml``TextColorPicker.qml``TrafficChartWindow.qml` 全部硬编码浅色(`#FFFFFF``#333333``#f5f5f5` 等),不随系统主题适配。而 `networkview.qml``NetworkPopup.qml` 正确地从 `DockPalette` 派生颜色。deepin 深色模式下这些窗口视觉割裂严重。
**5. `detectInterfaces()` 过滤规则与 `readNetworkStats()` 不一致**
`init()` 先调 `detectInterfaces()`(读 `/sys/class/net`,仅过滤 `lo`),再调 `readNetworkStats()`(读 `/proc/net/dev`,过滤 `lo`/`veth`/`docker`/`br-`)。首次刷新前,docker/veth 接口会短暂出现在列表中,造成 UI 闪烁。且 `detectInterfaces()` 的结果会被 `readNetworkStats()` 完全覆盖,属于冗余调用。
### 🟡 中优先级
**6. `setActiveInterface()` 不校验接口有效性**
可传入不存在的接口名,会被持久化到配置文件。下次启动时虽然会被 `readNetworkStats()` 清空回退,但当前会话期间 `getActiveRxBytes()` 返回 0,速度恒为 0,用户困惑。
**7. 速度历史仅记录活动接口**
`m_speedHistory` 每秒只给 `m_activeInterface` 追加采样点。非活动接口永不采集,切换到新接口时趋势图为空,需等待数分钟才有数据。若要"切回仍能看到历史",应后台为所有接口持续采样。
**8. 窗口居中未考虑多显示器**
`AboutWindow``SettingsWindow``TrafficChartWindow``Screen.width/height` 居中,frameless 窗口在多屏环境下可能出现在非预期屏幕。
**9. SPDX 版权归属为占位符**
所有文件头 `SPDX-FileCopyrightText: 2024 MyCompany`"MyCompany" 是模板占位符,应改为实际版权持有者(如 `2024 Jokul`)。
**10. `version()` 无兜底**
`pluginMetaData().value("Version")` 返回空(元数据未加载),AboutWindow 版本行显示空白。networkview.qml 有 `"1.0"` 兜底,但 AboutWindow 的 `version` 属性直接来自 `applet.version`,无兜底。
---
## 二、代码质量 / 可维护性
**11. 大量重复代码跨组件复制**
以下代码在 `networkview.qml``NetworkPopup.qml` 中完全重复,`formatSpeed` 还在 `TrafficChartWindow.qml` 中第三份拷贝:
- `isPhysicalIf()` 函数
- `sortedInterfaces` 属性
- `formatSpeed()` / `formatTotal()` 函数
- 全套调色板定义(`basePalette``primaryText``accentBlue`…)
- `downloadValueColor` / `uploadValueColor`
改一处需同步改 2-3 处,极易遗漏。应抽取为公共 QML 文件(如 `Theme.qml` 单例 + `Format.js`)。
**12. 死代码:`interfaceStats` 属性未被使用**
`networkview.qml:43` 绑定了 `interfaceStats` 属性,但从未在任何 UI 中读取。C++ 侧的 `interfaceStats()` 函数和 `Q_PROPERTY` 也是死代码。且其 `QStringList``|` 分隔符编码结构化数据的方式本身也很脆弱。
**13. 死代码:`refresh()` Q_INVOKABLE 从未被 QML 调用**
注释(networkview.qml:276)说明此前 QML 调 `applet.refresh()` 导致问题后已移除调用,但 C++ 侧的 `Q_INVOKABLE void refresh()` 仍保留。若确无外部调用方,可删除或标注保留原因。
**14. `interfaceStats` 暴露的数据不完整**
`NetworkInterface` 结构体解析了 `rxErrors`/`txErrors`/`rxDropped`/`txDropped`,但 `interfaceStats()` 输出时丢弃了这些字段。若未来要展示丢包/错误率,需补全。
**15. README.md 和 AGENTS.md 严重过时**
- 项目结构只列 `AboutWindow.qml`,实际有 5 个组件(缺 `NetworkPopup``SettingsWindow``TextColorPicker``TrafficChartWindow`
- README 功能特性未提及:设置窗口、字体颜色自定义、流量波动图、IPv6 显示
- README 写"支持从弹窗一键卸载插件",但卸载功能实际在设置窗口
- AGENTS.md "Project structure" 同样过时
**16. `qsTr()` 源字符串为中文,无翻译基础设施**
QML 中 `qsTr("网络速度监控")` 等以中文为源串,但项目无 `.ts` 翻译文件、无 `lupdate`/`lrelease` 构建步骤、C++ 无翻译加载逻辑。`qsTr()` 实质为空操作。若仅面向中文用户可接受;若计划国际化,需补全 i18n 基础设施并以英文为源串。
**17. C++ 后端无单元测试**
项目无任何测试。`calculateSpeed``readNetworkStats` 的正则解析、`isPhysicalInterface``niceCeil`(QML)等纯逻辑函数适合且应该有单元测试覆盖。
---
## 三、可开发的新需求 / 功能增强
### 🟢 推荐开发
| # | 需求 | 说明 | 价值 |
|---|------|------|------|
| 18 | **日/月流量统计持久化** | 将每日累计流量写入 `settings.ini`,重启后保留。弹窗/设置窗口展示今日/本月用量 | 解决缺陷 #3,核心功能提升 |
| 19 | **深色模式适配** | AboutWindow/SettingsWindow/TextColorPicker/TrafficChartWindow 改用 DTK 主题色或 `DockPalette` 派生色 | 解决缺陷 #4,视觉一致性 |
| 20 | **公共代码抽取** | 颜色/格式化/排序逻辑抽取为共享文件,消除 3 处重复 | 解决 #11,降低维护成本 |
| 21 | **文档同步** | 更新 README + AGENTS.md 的项目结构、功能列表、组件说明 | 解决 #15,新人/AI 接手必备 |
| 22 | **网络断连检测** | 活动接口 `operState != Up` 或 IP 丢失时,任务栏显示断连图标 + tooltip 提示 | 用户体验提升 |
| 23 | **全接口持续采样** | 后台为所有接口采集速度历史,切换接口时趋势图立即有数据 | 解决缺陷 #7 |
| 24 | **速度单位切换** | 设置中可选 KB/s(二进制)或 Mbps(十进制),或智能自动切换 | 国际化/习惯适配 |
### 🔵 可选增强
| # | 需求 | 说明 |
|---|------|------|
| 25 | **刷新间隔可配置** | 设置中可选 1s/2s/5s 刷新频率,降低低端设备 CPU 占用 |
| 26 | **流量超限通知** | 设置阈值,下载/上传超限时发送系统通知 |
| 27 | **趋势图时间窗口可选** | 流量波动图支持 5min / 30min / 1h 切换(需持久化历史数据) |
| 28 | **多接口聚合速度** | 任务栏可选显示所有接口合计速度,而非仅活动接口 |
| 29 | **HiDPI 适配** | 独立窗口使用相对尺寸而非固定像素,适配高分辨率屏幕 |
| 30 | **i18n 翻译基础设施** | 源串改英文 + 添加中文 `.ts` + `lrelease` 构建集成 |
| 31 | **DTK 原生窗口框架** | 独立窗口改用 `DWindow` / DTK 窗口装饰,获得原生 deepin 标题栏、圆角、阴影 |
| 32 | **导出流量数据** | 将流量统计导出为 CSV/JSON,便于分析 |
| 33 | **C++ 后端单元测试** | 为速度计算、正则解析、接口检测添加 Qt Test 单元测试 |
| 34 | **丢包/错误率展示** | 弹窗中展示 `rxErrors`/`rxDropped`,网络质量诊断 |
| 35 | **开机自启保障** | 确保 dde-shell 启动时插件自动加载(可能需 dde-shell 配置) |
---
## 优先级建议
**第一优先级**(影响正确性):#1 速度计算间隔、#2 负速度、#5 接口过滤不一致
**第二优先级**(影响体验):#4 深色模式、#3 总量语义、#7 历史采样、#15 文档过时
**第三优先级**(工程质量):#11 重复代码、#12-14 死代码、#17 测试缺失
**第四优先级**(功能扩展):#18 日/月统计、#22 断连检测、#26 流量通知