diff --git a/client/src/settings_ui.py b/client/src/settings_ui.py index da68e69..b39b8f4 100644 --- a/client/src/settings_ui.py +++ b/client/src/settings_ui.py @@ -513,6 +513,16 @@ class SettingsPage(QWidget): self.updateStatusLabel.setText(message) + def set_update_versions(self, current_version: str, latest_version: str) -> None: + """同时显示本地版本和线上版本,便于判断是否需要更新。""" + + self.currentVersionLabel.setText( + f"本地 {current_version};线上 {latest_version}" + ) + self.currentVersionLabel.setAccessibleName( + f"本地版本 {current_version},线上版本 {latest_version}" + ) + def set_saved_android_device(self, serial: str) -> None: """显示已经保存并实际用于自动化的 Android 设备。""" diff --git a/client/src/ui_main.py b/client/src/ui_main.py index 00aeae6..81eb4d3 100644 --- a/client/src/ui_main.py +++ b/client/src/ui_main.py @@ -80,12 +80,22 @@ class MainWindow(FluentWindow): self.pddTaskPageEvent.update_admin_base_url ) self.addSubInterface(self.pddTaskPage, FIF.HOME, "pdd") - self.addSubInterface( + self.settingsNavigationItem = self.addSubInterface( self.settingsPage, FIF.SETTING, "设置", NavigationItemPosition.BOTTOM, ) + self._settings_navigation_text = self.settingsNavigationItem.text() + self._settings_navigation_light_color = ( + self.settingsNavigationItem.lightTextColor + ) + self._settings_navigation_dark_color = ( + self.settingsNavigationItem.darkTextColor + ) + self.settingsPage.eventBinder.updateEventBinder.updateAvailabilityChanged.connect( + self._set_update_navigation_reminder + ) self.setWindowTitle("采集采购工具") self.setMinimumSize(820, 560) @@ -93,6 +103,31 @@ class MainWindow(FluentWindow): self._moveToScreenCenter() self.pddTaskPageEvent.load_initial_tasks() + def _set_update_navigation_reminder( + self, + available: bool, + current_version: str, + latest_version: str, + ) -> None: + """用颜色和文字共同提醒更新,不让提示只依赖颜色。""" + + if available: + self.settingsNavigationItem.setText( + f"{self._settings_navigation_text}(有更新)" + ) + self.settingsNavigationItem.setTextColor("#B45309", "#FBBF24") + self.settingsNavigationItem.setToolTip( + f"发现新版本 {latest_version},当前版本 {current_version}" + ) + return + + self.settingsNavigationItem.setText(self._settings_navigation_text) + self.settingsNavigationItem.setTextColor( + self._settings_navigation_light_color, + self._settings_navigation_dark_color, + ) + self.settingsNavigationItem.setToolTip(self._settings_navigation_text) + def _moveToScreenCenter(self): screen = QApplication.primaryScreen() if screen is None: diff --git a/client/src/update_ui_event.py b/client/src/update_ui_event.py index f8d9d08..d2c1a85 100644 --- a/client/src/update_ui_event.py +++ b/client/src/update_ui_event.py @@ -117,6 +117,8 @@ class UpdateDownloadWorker(QObject): class UpdateUiEventBinder(QObject): """管理更新配置、保存反馈和两个后台线程。""" + updateAvailabilityChanged = pyqtSignal(bool, str, str) + def __init__( self, page, @@ -300,13 +302,27 @@ class UpdateUiEventBinder(QObject): def _on_check_succeeded(self, result: UpdateCheckResult) -> None: if self._closing: return + self._page.set_update_versions( + result.current_version, + result.latest_version, + ) if not result.available or result.update is None: + self.updateAvailabilityChanged.emit( + False, + result.current_version, + result.latest_version, + ) self._page.set_update_status( f"当前已是最新版本({result.current_version})" ) return update = result.update + self.updateAvailabilityChanged.emit( + True, + result.current_version, + update.version, + ) size_mb = update.size / (1024 * 1024) dialog = MessageBox( f"发现新版本 {update.version}", diff --git a/client/test/test_pdd_ui_event.py b/client/test/test_pdd_ui_event.py index e3cadfd..74f79b6 100644 --- a/client/test/test_pdd_ui_event.py +++ b/client/test/test_pdd_ui_event.py @@ -1113,6 +1113,22 @@ class PDDTaskPageEventTest(unittest.TestCase): window.close() window.deleteLater() + def test_main_window_marks_and_clears_update_navigation(self): + window = MainWindow( + task_repository=self.repository, + settings_repository=SettingsRepository(self.db_path), + admin_gateway=MockAdminGateway(), + ) + + window._set_update_navigation_reminder(True, "0.1.0", "0.2.0") + self.assertIn("有更新", window.settingsNavigationItem.text()) + self.assertIn("0.2.0", window.settingsNavigationItem.toolTip()) + + window._set_update_navigation_reminder(False, "0.2.0", "0.2.0") + self.assertNotIn("有更新", window.settingsNavigationItem.text()) + window.close() + window.deleteLater() + def test_admin_base_url_change_reaches_persistent_claim_worker(self): settings = self._saved_settings() page = PDDTaskPage() diff --git a/client/test/test_update_ui_event.py b/client/test/test_update_ui_event.py index 6809ce1..f3cdc1b 100644 --- a/client/test/test_update_ui_event.py +++ b/client/test/test_update_ui_event.py @@ -153,6 +153,35 @@ class UpdateUiEventTest(unittest.TestCase): page.eventBinder.shutdown() page.deleteLater() + def test_successful_check_exposes_versions_and_availability(self): + update = UpdateInfo( + version="0.3.0", + notes="", + update_url="https://updates.example.test/CMAutoBuy_0.3.0.zip", + file_name="CMAutoBuy_0.3.0.zip", + size=1024, + sha256="0" * 64, + ) + page = self._page(FakeUpdateService()) + changes = [] + page.eventBinder.updateEventBinder.updateAvailabilityChanged.connect( + lambda available, current, latest: changes.append( + (available, current, latest) + ) + ) + + with patch("src.update_ui_event.MessageBox.exec", return_value=False): + page.eventBinder.updateEventBinder._on_check_succeeded( + UpdateCheckResult("0.1.0", "0.3.0", True, update) + ) + + self.assertEqual(changes, [(True, "0.1.0", "0.3.0")]) + self.assertEqual( + page.currentVersionLabel.text(), "本地 0.1.0;线上 0.3.0" + ) + page.eventBinder.shutdown() + page.deleteLater() + def test_save_uses_sqlite_for_non_secret_and_credential_store_for_password(self): page = self._page(FakeUpdateService()) diff --git a/docs/client/05-ui-specification.md b/docs/client/05-ui-specification.md index 87ea382..c16d8b0 100644 --- a/docs/client/05-ui-specification.md +++ b/docs/client/05-ui-specification.md @@ -21,6 +21,10 @@ 1. **PDD 任务**:主要业务页面。 2. **设置**:固定在导航底部。 +启动检查确认存在新版本时,设置导航显示“有更新”文字并使用提醒色,不能只靠颜色表达。 +只有确认线上版本不高于本地版本时才清除提醒;进入设置页不会自动清除提醒,检查失败也 +不会制造更新提示。软件更新区域同时显示本地版本和线上版本。 + 页面必须使用稳定对象名: - `pddTaskPage`