1
1
mirror of https://github.com/KenanZhu/AutoLibrary.git synced 2026-08-02 06:09:36 +08:00

refactor(bulletin): 提取 ALBulletinFetchWorker 到独立文件

This commit is contained in:
2026-06-26 09:16:45 +08:00
parent 92c5fa0dfb
commit 2fe4584129
4 changed files with 134 additions and 105 deletions
+4 -45
View File
@@ -7,14 +7,11 @@ This software is provided "as is", without any warranty of any kind.
You may use, modify, and distribute this file under the terms of the MIT License. You may use, modify, and distribute this file under the terms of the MIT License.
See the LICENSE file for details. See the LICENSE file for details.
""" """
import requests
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any from typing import Any
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, Qt,
QThread,
Signal, Signal,
Slot, Slot,
QTimer QTimer
@@ -32,53 +29,12 @@ from PySide6.QtWidgets import (
QWidget QWidget
) )
from gui.ALBulletinWorker import ALBulletinFetchWorker
from gui.ALStatusLabel import ALStatusLabel from gui.ALStatusLabel import ALStatusLabel
from gui.resources.ui.Ui_ALBulletinDialog import Ui_ALBulletinDialog from gui.resources.ui.Ui_ALBulletinDialog import Ui_ALBulletinDialog
from managers.bulletin.BulletinManager import instance as bulletinInstance from managers.bulletin.BulletinManager import instance as bulletinInstance
class ALBulletinFetchWorker(QThread):
"""
Worker thread for fetching bulletins from the server.
"""
fetchWorkerIsFinished = Signal(dict)
fetchWorkerFinishedWithError = Signal(str)
def __init__(
self,
parent=None,
request_url: str = "",
params: dict = None
):
super().__init__(parent)
self.__request_url = request_url.rstrip("/") if request_url else ""
self.__params = params or {}
def run(
self
):
try:
response = requests.get(
self.__request_url, params=self.__params, timeout=5
)
response.raise_for_status()
r = response.json()
if r.get("code") == 200:
data = r.get("data", {})
self.fetchWorkerIsFinished.emit(data)
else:
raise Exception(
f"服务器返回错误: [{r.get('code', '未知代码')}] {r.get('msg', '未知错误')}"
)
except requests.RequestException as e:
self.fetchWorkerFinishedWithError.emit(f"获取公告数据时发生网络错误: \n{e}")
except Exception as e:
self.fetchWorkerFinishedWithError.emit(f"获取公告数据时发生未知错误: \n{e}")
class ALBulletinItemWidget(QWidget): class ALBulletinItemWidget(QWidget):
""" """
Single bulletin item widget for the bulletin list. Single bulletin item widget for the bulletin list.
@@ -216,6 +172,9 @@ class ALBulletinDialog(QDialog, Ui_ALBulletinDialog):
self, self,
iso_str: str iso_str: str
): ):
"""
Set last sync time to update the UI status.
"""
try: try:
dt = datetime.fromisoformat(iso_str) dt = datetime.fromisoformat(iso_str)
+1 -1
View File
@@ -16,7 +16,7 @@ from PySide6.QtCore import (
Slot Slot
) )
from gui.ALBulletinDialog import ALBulletinFetchWorker from gui.ALBulletinWorker import ALBulletinFetchWorker
from managers.bulletin.BulletinManager import instance as bulletinInstance from managers.bulletin.BulletinManager import instance as bulletinInstance
+57
View File
@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
"""
Copyright (c) 2026 KenanZhu.
All rights reserved.
This software is provided "as is", without any warranty of any kind.
You may use, modify, and distribute this file under the terms of the MIT License.
See the LICENSE file for details.
"""
import requests
from PySide6.QtCore import (
QThread,
Signal
)
class ALBulletinFetchWorker(QThread):
"""
Worker thread for fetching bulletins from the server.
"""
fetchWorkerIsFinished = Signal(dict)
fetchWorkerFinishedWithError = Signal(str)
def __init__(
self,
parent=None,
request_url: str = "",
params: dict = None
):
super().__init__(parent)
self.__request_url = request_url.rstrip("/") if request_url else ""
self.__params = params or {}
def run(
self
):
try:
response = requests.get(
self.__request_url, params=self.__params, timeout=5
)
response.raise_for_status()
r = response.json()
if r.get("code") == 200:
data = r.get("data", {})
self.fetchWorkerIsFinished.emit(data)
else:
raise Exception(
f"服务器返回错误: [{r.get('code', '未知代码')}] {r.get('msg', '未知错误')}"
)
except requests.RequestException as e:
self.fetchWorkerFinishedWithError.emit(f"获取公告数据时发生网络错误: \n{e}")
except Exception as e:
self.fetchWorkerFinishedWithError.emit(f"获取公告数据时发生未知错误: \n{e}")
+72 -59
View File
@@ -41,6 +41,7 @@ from managers.theme.ThemeManager import(
instance as themeInstance instance as themeInstance
) )
from gui.ALBulletinWorker import ALBulletinFetchWorker
from gui.ALWidgetMixin import CenterOnParentMixin from gui.ALWidgetMixin import CenterOnParentMixin
from gui.resources.ui.Ui_ALSettingsWidget import Ui_ALSettingsWidget from gui.resources.ui.Ui_ALSettingsWidget import Ui_ALSettingsWidget
from interfaces.ConfigProvider import ( from interfaces.ConfigProvider import (
@@ -196,6 +197,7 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
self self
): ):
# appearance settings
theme = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.THEME, "system") theme = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.THEME, "system")
style = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.STYLE, "Fusion") style = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.STYLE, "Fusion")
custom_theme = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.CUSTOM_THEME, "") custom_theme = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.CUSTOM_THEME, "")
@@ -218,7 +220,7 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
self.CustomThemeComboBox.setCurrentIndex(idx) self.CustomThemeComboBox.setCurrentIndex(idx)
self.updateCustomThemeInfo() self.updateCustomThemeInfo()
self.updateCustomThemeStatus() self.updateCustomThemeStatus()
# bulletin settings
bulletin_mgr = bulletinInstance() bulletin_mgr = bulletinInstance()
self.__original_bulletin_url = bulletin_mgr.serverUrl() self.__original_bulletin_url = bulletin_mgr.serverUrl()
self.__original_bulletin_auto_fetch = bulletin_mgr.autoFetch() self.__original_bulletin_auto_fetch = bulletin_mgr.autoFetch()
@@ -274,10 +276,17 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
elif need_theme == "dark": elif need_theme == "dark":
self.DarkThemeRadio.setChecked(True) self.DarkThemeRadio.setChecked(True)
def collectSettings( def clearBulletinTestStatus(
self self
): ):
self.BulletinTestStatusLabel.setText("")
self.BulletinTestStatusLabel.setStyleSheet("")
def collectAppearanceSettings(
self
) -> tuple[str, str, str]:
if self.LightThemeRadio.isChecked(): if self.LightThemeRadio.isChecked():
theme = "light" theme = "light"
elif self.DarkThemeRadio.isChecked(): elif self.DarkThemeRadio.isChecked():
@@ -290,41 +299,29 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
custom_theme = "" custom_theme = ""
return theme, style, custom_theme return theme, style, custom_theme
def clearBulletinTestStatus( def collectBulletinSettings(
self self
): ) -> tuple[str, bool, int]:
self.BulletinTestStatusLabel.setText("")
self.BulletinTestStatusLabel.setStyleSheet("")
def saveBulletinSettings(
self
):
url = self.BulletinServerUrlEdit.text().strip() url = self.BulletinServerUrlEdit.text().strip()
auto_fetch = self.BulletinAutoFetchCheck.isChecked() auto_fetch = self.BulletinAutoFetchCheck.isChecked()
sync_interval = self.BulletinSyncIntervalSpin.value() sync_interval = self.BulletinSyncIntervalSpin.value()
if sync_interval < 1: if sync_interval < 1:
sync_interval = 5 sync_interval = 5
self.__cfg_mgr.set(CfgKey.GLOBAL.BULLETIN.SERVER_URL, url) return url, auto_fetch, sync_interval
self.__cfg_mgr.set(CfgKey.GLOBAL.BULLETIN.AUTO_FETCH, auto_fetch)
self.__cfg_mgr.set(CfgKey.GLOBAL.BULLETIN.SYNC_INTERVAL, sync_interval)
self.__original_bulletin_url = url
self.__original_bulletin_auto_fetch = auto_fetch
self.__original_bulletin_sync_interval = sync_interval
def saveAndApply( def saveAppearanceSettings(
self self
): ):
theme, style, custom_theme = self.collectSettings() theme, style, custom_theme = self.collectAppearanceSettings()
self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.STYLE, style) self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.STYLE, style)
self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.CUSTOM_THEME, custom_theme) self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.CUSTOM_THEME, custom_theme)
setActiveStyle(style) setActiveStyle(style)
if not _applyCustomTheme(custom_theme, theme): if not _applyCustomTheme(custom_theme, theme):
self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.CUSTOM_THEME, "") self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.CUSTOM_THEME, "")
self.syncRadioFromNeedTheme(custom_theme) self.syncRadioFromNeedTheme(custom_theme)
theme, _, _ = self.collectSettings() theme, _, _ = self.collectAppearanceSettings()
self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.THEME, theme) self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.THEME, theme)
self.setNavigationIcons() self.setNavigationIcons()
self.updateCustomThemeStatus() self.updateCustomThemeStatus()
@@ -333,7 +330,24 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
self.__original_custom_theme = custom_theme if custom_theme else "" self.__original_custom_theme = custom_theme if custom_theme else ""
self.__original_style = getActiveStyle() self.__original_style = getActiveStyle()
def saveBulletinSettings(
self
):
url, auto_fetch, sync_interval = self.collectBulletinSettings()
self.__cfg_mgr.set(CfgKey.GLOBAL.BULLETIN.SERVER_URL, url)
self.__cfg_mgr.set(CfgKey.GLOBAL.BULLETIN.AUTO_FETCH, auto_fetch)
self.__cfg_mgr.set(CfgKey.GLOBAL.BULLETIN.SYNC_INTERVAL, sync_interval)
self.__original_bulletin_url = url
self.__original_bulletin_auto_fetch = auto_fetch
self.__original_bulletin_sync_interval = sync_interval
def saveSettings(
self
):
self.saveBulletinSettings() self.saveBulletinSettings()
self.saveAppearanceSettings()
def maybeRestart( def maybeRestart(
self self
@@ -351,6 +365,34 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
return True return True
return False return False
@Slot()
def onImportCustomThemeButtonClicked(
self
):
file_path, _ = QFileDialog.getOpenFileName(
self,
"导入主题 - AutoLibrary",
"",
"主题文件 (*.altheme *.qss);;所有文件 (*)"
)
if not file_path:
return
try:
file_id = themeInstance().importTheme(file_path)
self.populateCustomThemes()
idx = self.CustomThemeComboBox.findData(file_id)
if idx >= 0:
self.CustomThemeComboBox.setCurrentIndex(idx)
self.updateCustomThemeStatus()
self.updateCustomThemeInfo()
except Exception as e:
QMessageBox.warning(
self,
"导入失败 - AutoLibrary",
f"无法导入主题文件:{e}"
)
@Slot() @Slot()
def onRemoveCustomThemeButtonClicked( def onRemoveCustomThemeButtonClicked(
self self
@@ -388,34 +430,6 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
f"无法删除主题:{e}" f"无法删除主题:{e}"
) )
@Slot()
def onImportCustomThemeButtonClicked(
self
):
file_path, _ = QFileDialog.getOpenFileName(
self,
"导入主题 - AutoLibrary",
"",
"主题文件 (*.altheme *.qss);;所有文件 (*)"
)
if not file_path:
return
try:
file_id = themeInstance().importTheme(file_path)
self.populateCustomThemes()
idx = self.CustomThemeComboBox.findData(file_id)
if idx >= 0:
self.CustomThemeComboBox.setCurrentIndex(idx)
self.updateCustomThemeStatus()
self.updateCustomThemeInfo()
except Exception as e:
QMessageBox.warning(
self,
"导入失败 - AutoLibrary",
f"无法导入主题文件:{e}"
)
@Slot() @Slot()
def onCustomThemeComboBoxChanged( def onCustomThemeComboBoxChanged(
self, self,
@@ -464,30 +478,29 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
self.BulletinTestStatusLabel.setText("正在测试连接...") self.BulletinTestStatusLabel.setText("正在测试连接...")
self.BulletinTestStatusLabel.setStyleSheet("") self.BulletinTestStatusLabel.setStyleSheet("")
self.__bulletin_test_t0 = time.monotonic() self.__bulletin_test_t0 = time.monotonic()
from gui.ALBulletinDialog import ALBulletinFetchWorker
api_url = url.rstrip("/") + "/bulletins" api_url = url.rstrip("/") + "/bulletins"
self.__bulletin_test_worker = ALBulletinFetchWorker( self.__bulletin_test_worker = ALBulletinFetchWorker(
self, api_url, {"date": "", "time": "", "range_hour": "1"} self, api_url, {"date": "", "time": "", "range_hour": "1"}
) )
self.__bulletin_test_worker.fetchWorkerIsFinished.connect( self.__bulletin_test_worker.fetchWorkerIsFinished.connect(
self.__onBulletinTestFetched self.onBulletinTestFetched
) )
self.__bulletin_test_worker.fetchWorkerFinishedWithError.connect( self.__bulletin_test_worker.fetchWorkerFinishedWithError.connect(
self.__onBulletinTestError self.onBulletinTestError
) )
self.__bulletin_test_worker.start() self.__bulletin_test_worker.start()
@Slot(dict) @Slot(dict)
def __onBulletinTestFetched( def onBulletinTestFetched(
self, self,
data: dict data: dict
): ):
self.__bulletin_test_worker.fetchWorkerIsFinished.disconnect( self.__bulletin_test_worker.fetchWorkerIsFinished.disconnect(
self.__onBulletinTestFetched self.onBulletinTestFetched
) )
self.__bulletin_test_worker.fetchWorkerFinishedWithError.disconnect( self.__bulletin_test_worker.fetchWorkerFinishedWithError.disconnect(
self.__onBulletinTestError self.onBulletinTestError
) )
self.__bulletin_test_worker.deleteLater() self.__bulletin_test_worker.deleteLater()
self.__bulletin_test_worker = None self.__bulletin_test_worker = None
@@ -500,16 +513,16 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
QTimer.singleShot(3000, self, self.clearBulletinTestStatus) QTimer.singleShot(3000, self, self.clearBulletinTestStatus)
@Slot(str) @Slot(str)
def __onBulletinTestError( def onBulletinTestError(
self, self,
error_message: str error_message: str
): ):
self.__bulletin_test_worker.fetchWorkerIsFinished.disconnect( self.__bulletin_test_worker.fetchWorkerIsFinished.disconnect(
self.__onBulletinTestFetched self.onBulletinTestFetched
) )
self.__bulletin_test_worker.fetchWorkerFinishedWithError.disconnect( self.__bulletin_test_worker.fetchWorkerFinishedWithError.disconnect(
self.__onBulletinTestError self.onBulletinTestError
) )
self.__bulletin_test_worker.deleteLater() self.__bulletin_test_worker.deleteLater()
self.__bulletin_test_worker = None self.__bulletin_test_worker = None
@@ -529,9 +542,9 @@ class ALSettingsWidget(CenterOnParentMixin, QWidget, Ui_ALSettingsWidget):
self self
): ):
_, style, _ = self.collectSettings() _, style, _ = self.collectAppearanceSettings()
style_changed = self.__original_style != style style_changed = self.__original_style != style
self.saveAndApply() self.saveSettings()
if style_changed: if style_changed:
self.maybeRestart() self.maybeRestart()