1 Commits
Author SHA1 Message Date
clear e78ad55b4e Release v1.0.6 download completion summary 2026-09-27 18:31:09 +08:00
6 changed files with 83 additions and 27 deletions

No files matched your search

+3 -3
View File
@@ -1,8 +1,8 @@
# PGU-NetFileSyncWin 项目维护说明
当前应用版本:`v1.0.5`(2026-09-27)
当前应用版本:`v1.0.6`(2026-09-27)
本版本变更:极速服务 V3、CPU 自适应并发、HTTP 长连接、服务版本显示与旧版升级、连接断开后的 user linger、下载重试稳定性和项目文档整理。
本版本变更:下载完成结果弹窗、失败项目明细、用时和平均速度统计、完成后速度条清零;并保留极速服务 V3、CPU 自适应并发、HTTP 长连接、服务版本显示与旧版升级、连接断开后的 user linger。
## 项目定位
@@ -100,7 +100,7 @@ remote_path=/home/clear/Data
- `100MB/s` 映射到满格。
- 下载中蓝色。
- 下载完成后满格绿色。
- 下载完成弹窗关闭后速度条清零,恢复为等待状态。
局域网扫描端口:
+2 -1
View File
@@ -25,13 +25,14 @@ PGU-NetFileSyncWin 是一个 Windows 桌面文件同步工具,用于连接 PGU
## 当前版本
当前应用版本:`v1.0.5`
当前应用版本:`v1.0.6`
本版本重点修复极速下载稳定性:客户端会同时考虑 Windows 本机和 PGU 设备的 CPU 线程数;极速服务按远端 CPU 建立并发槽位,支持 HTTP 长连接、连接队列扩容、服务版本显示和旧版一键升级。
- 高速通道区域显示已安装的极速服务版本,例如 `极速 v3`。
- 检测到旧版时显示实际版本,并提供 `升级极速`。
- 大量小文件下载复用连接,减少速度波动和重复重试。
- 下载结束后弹窗显示成功/失败状态、已传输大小、用时、平均速度和失败项目;底部速度条自动清零。
## 发布版
+10 -1
View File
@@ -177,13 +177,22 @@ IP、端口、用户名和远程路径可以直接用记事本修改。密码请
如果最终仍有文件失败,软件会在下载结束后统一提示。
下载结束后会弹出结果窗口,显示:
- 是否全部成功或被取消。
- 已传输大小和计划大小。
- 总用时和平均速度。
- 失败项目数量及失败原因。
结果窗口关闭后,底部速度条会自动恢复为 0,等待下一次下载。
## 11. 速度条
底部进度条是速度条,不是总进度条。
- `100MB/s` 对应满格。
- 下载过程中为蓝色。
- 下载完成后会拉满并变为绿色。
- 下载结果弹窗关闭后自动清零,恢复为等待下一次下载的状态。
下载完成后会显示:
+44 -20
View File
@@ -83,7 +83,7 @@ from PyQt5.QtWidgets import (
APP_ORG = "ClearCore"
APP_NAME = "PGU4-Sync"
APP_VERSION = "1.0.5"
APP_VERSION = "1.0.6"
CONFIG_FILE_NAME = "PGU-NetFileSyncWin.ini"
PASSWORD_PROTECTED_KEY = "password_protected"
PASSWORD_LEGACY_KEY = "password"
@@ -4673,29 +4673,53 @@ class MainWindow(QMainWindow):
elapsed = max(0.001, time.monotonic() - self._download_start_time) if self._download_start_time else 0.001
avg_speed = self._done_bytes / elapsed
summary = f"{human_size(self._done_bytes)} 用时 {format_duration(elapsed)} 平均 {human_size(int(avg_speed))}/s"
if cancelled:
self.progress.setFormat(f"已取消 {summary} / {human_size(effective_total)}")
self.transfer_detail_label.setText(f"传输已取消 · {summary}")
self.statusBar().showMessage("下载已取消", 5000)
failures = list(self._download_errors)
if failures:
details = "\n".join(
f"{Path(path).name}: {message}" for path, message in failures[:12]
)
if len(failures) > 12:
details += f"\n... 还有 {len(failures) - 12} 个失败项目"
else:
self.set_meter_state("done")
self.set_progress_value(100, animate=False)
if self._download_errors:
self.progress.setFormat(f"下载完成 {summary} 失败 {len(self._download_errors)} 个")
self.transfer_detail_label.setText(
f"下载完成 · {summary} · 失败 {len(self._download_errors)} 个"
details = "没有失败项目。"
if cancelled:
title = "下载已取消"
message = (
f"已取消当前下载。\n\n"
f"已传输:{summary}\n"
f"计划大小:{human_size(effective_total)}\n\n"
f"失败项目:{len(failures)} 个"
)
self.statusBar().showMessage("下载已取消", 5000)
QMessageBox.information(self, title, message)
else:
if failures:
title = "下载完成,但有文件失败"
message = (
f"已完成下载流程,但有 {len(failures)} 个项目失败。\n\n"
f"已传输:{summary}\n"
f"计划大小:{human_size(effective_total)}\n\n"
f"失败项目:\n{details}"
)
self.statusBar().showMessage(f"下载完成,失败 {len(self._download_errors)} 个文件", 8000)
details = "\n".join(
f"{Path(path).name}: {message}" for path, message in self._download_errors[:8]
)
if len(self._download_errors) > 8:
details += f"\n... 还有 {len(self._download_errors) - 8} 个"
QMessageBox.warning(self, "部分文件下载失败", details)
self.statusBar().showMessage(f"下载完成,失败 {len(failures)} 个文件", 8000)
QMessageBox.warning(self, title, message)
else:
self.progress.setFormat(f"下载完成 {summary}")
self.transfer_detail_label.setText(f"下载完成 · {summary}")
title = "下载完成"
message = (
f"全部文件已成功下载。\n\n"
f"已传输:{summary}\n"
f"计划大小:{human_size(effective_total)}\n\n"
f"{details}"
)
self.statusBar().showMessage("下载完成", 5000)
QMessageBox.information(self, title, message)
self.set_meter_state("speed")
self.set_progress_value(0, animate=False)
self.progress.setFormat("就绪 速度 0 B/s / 100.0 MB/s")
self.speed_label.setText("速度 0 B/s")
self.transfer_detail_label.setText("等待下载")
self.controller = None
def _run_worker(self, worker: QObject, callback, start: bool = True) -> QThread:
+23 -1
View File
@@ -1,11 +1,13 @@
import os
import stat
import time
import unittest
from unittest.mock import patch
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from PyQt5.QtCore import QItemSelectionModel
from PyQt5.QtWidgets import QApplication, QStatusBar
from PyQt5.QtWidgets import QApplication, QMessageBox, QStatusBar
from pgu4_sync import ConnectionDialog, MainWindow, RemoteEntry, adaptive_worker_count
@@ -171,3 +173,23 @@ class CommercialUiTests(unittest.TestCase):
window.set_fast_button_state("upgrade", "2")
self.assertEqual("极速 v2 · 可升级", window.fast_status_badge.text())
def test_download_completion_reports_metrics_and_clears_speed_meter(self):
window = MainWindow()
self.addCleanup(window.close)
window.controller = object()
window._active_download = True
window._download_start_time = time.monotonic() - 2
window._total_bytes = 2048
window._done_bytes = 2048
window._download_errors = []
with patch.object(QMessageBox, "information") as information:
window.on_download_all_done(False)
information.assert_called_once()
message = information.call_args.args[2]
self.assertIn("用时", message)
self.assertIn("平均", message)
self.assertEqual(0, window.progress.value())
self.assertEqual("等待下载", window.transfer_detail_label.text())
+1 -1
View File
@@ -35,7 +35,7 @@ class UpdateTests(unittest.TestCase):
self.assertEqual([True], finished)
def test_version_comparison(self):
self.assertTrue(is_newer_version("1.0.6", APP_VERSION))
self.assertTrue(is_newer_version("1.0.7", APP_VERSION))
self.assertTrue(is_newer_version("v1.1.0", "1.0.9"))
self.assertTrue(is_newer_version("1.0.10", "1.0.2"))
self.assertFalse(is_newer_version("v1.0.4", APP_VERSION))