"""应用与主窗口装配。 本文件只负责把窗口、导航和页面拼起来,不写业务逻辑。 改动本文件前必读 `client/AGENTS.md`。以下几条最容易踩: - 图标一律用 `FluentIcon`,**不得使用表情符号充当图标**。 - 不得在这里发起 Admin 请求、SQLite 长查询或 uiautomator2 调用, 这些会卡死 Qt 主线程。业务事件放到各页面的 `*_ui_event.py`。 - 页面的 `objectName` 必须唯一且稳定,改名会破坏导航。 - 用布局和伸缩项排版,**不要用固定坐标**。 - 不要用全局 QSS 覆盖 Fluent 控件;局部样式必须保留悬停、按下、 焦点和禁用四种状态。 - 需要文件路径时走 `data_dir()` / `app_dir()`,不要硬编码, 见 `docs/client/03-data-model.md` §2.2。 """ import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication from qfluentwidgets import ( FluentIcon as FIF, FluentWindow, NavigationItemPosition, Theme, setTheme, ) from .pdd_ui import PDDTaskPage from .pdd_ui_event import PDDTaskPageEvent from .pdd_u2_purchase_adapter import ( create_u2_live_purchase_adapter, create_u2_purchase_adapter, ) from .pdd_u2_purchase_reconcile_adapter import ( create_u2_purchase_reconcile_adapter, ) from .settings_ui import SettingsPage from .task_repository import TaskRepository from .update_service import mark_current_version_healthy class MainWindow(FluentWindow): """应用主窗口。""" def __init__( self, task_repository=None, settings_repository=None, admin_gateway=None, ): super().__init__() self.pddTaskPage = PDDTaskPage(self) self.settingsPage = SettingsPage( self, settings_repository=settings_repository, admin_gateway=admin_gateway, live_purchase_adapter_ready=True, ) self.pddTaskPageEvent = PDDTaskPageEvent( self.pddTaskPage, task_repository or TaskRepository(), self, claim_gateway=admin_gateway, settings_repository=settings_repository, purchase_adapter_factory=create_u2_purchase_adapter, live_purchase_adapter_factory=create_u2_live_purchase_adapter, purchase_reconcile_factory=create_u2_purchase_reconcile_adapter, ) self.pddTaskPage.openSettingsRequested.connect( lambda: self.switchTo(self.settingsPage) ) self.settingsPage.eventBinder.androidDeviceConfigurationChanged.connect( self.pddTaskPageEvent.android_device_configuration_changed ) self.settingsPage.eventBinder.adminBaseUrlChanged.connect( self.pddTaskPageEvent.update_admin_base_url ) self.addSubInterface(self.pddTaskPage, FIF.HOME, "pdd") self.addSubInterface( self.settingsPage, FIF.SETTING, "设置", NavigationItemPosition.BOTTOM, ) self.setWindowTitle("采集采购工具") self.setMinimumSize(820, 560) self.resize(1040, 680) self._moveToScreenCenter() self.pddTaskPageEvent.load_initial_tasks() def _moveToScreenCenter(self): screen = QApplication.primaryScreen() if screen is None: return frame = self.frameGeometry() frame.moveCenter(screen.availableGeometry().center()) self.move(frame.topLeft()) def ui_main(): """启动桌面应用。""" QApplication.setAttribute(Qt.AA_EnableHighDpiScaling) QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) app = QApplication(sys.argv) setTheme(Theme.AUTO) window = MainWindow() window.show() try: mark_current_version_healthy() except OSError: # 健康标记失败不能让界面崩溃;Launcher 会保留旧版本并在下次启动恢复。 pass return app.exec_() if __name__ == "__main__": sys.exit(ui_main())