From 7d71ffe099553c4e1a12715d54dcf34f6de41ce8 Mon Sep 17 00:00:00 2001 From: hyb-oyqq <1512383570@qq.com> Date: Mon, 11 Aug 2025 17:54:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(core):=20=E5=A2=9E=E5=BC=BA=E5=8D=B8?= =?UTF-8?q?=E8=BD=BD=E5=A4=84=E7=90=86=E7=A8=8B=E5=BA=8F=E7=9A=84UI?= =?UTF-8?q?=E5=8F=8D=E9=A6=88=E5=92=8C=E5=BC=82=E5=B8=B8=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在卸载处理程序中使用UI管理器显示和隐藏加载对话框,提升用户体验。 - 增加异常钩子,确保未捕获的异常能够记录到日志文件中,增强系统的稳定性和可追溯性。 --- source/Main.py | 35 ++++++++++++++++++++++- source/core/handlers/uninstall_handler.py | 12 ++++++-- source/utils/logger.py | 29 +++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/source/Main.py b/source/Main.py index f33ef5c..168f186 100644 --- a/source/Main.py +++ b/source/Main.py @@ -1,18 +1,50 @@ import sys import os import datetime +import traceback from PySide6.QtWidgets import QApplication, QMessageBox from main_window import MainWindow from core.managers.privacy_manager import PrivacyManager -from utils.logger import setup_logger, cleanup_old_logs +from utils.logger import setup_logger, cleanup_old_logs, log_uncaught_exceptions from config.config import LOG_FILE, APP_NAME, LOG_RETENTION_DAYS from utils import load_config +def excepthook(exc_type, exc_value, exc_traceback): + """全局异常处理钩子,将未捕获的异常记录到日志并显示错误对话框""" + # 记录异常到日志 + if hasattr(sys, '_excepthook'): + sys._excepthook(exc_type, exc_value, exc_traceback) + else: + log_uncaught_exceptions(exc_type, exc_value, exc_traceback) + + # 将异常格式化为易读的形式 + exception_text = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback)) + + # 创建错误对话框 + msg = f"程序遇到未处理的异常:\n\n{str(exc_value)}\n\n详细错误已记录到日志文件。" + try: + # 尝试使用QMessageBox显示错误 + app = QApplication.instance() + if app: + QMessageBox.critical(None, f"错误 - {APP_NAME}", msg) + except Exception: + # 如果QMessageBox失败,则使用标准输出 + print(f"严重错误: {msg}") + print(f"详细错误: {exception_text}") + if __name__ == "__main__": # 设置主日志 logger = setup_logger("main") logger.info("应用启动") + # 设置全局异常处理钩子 + sys._excepthook = sys.excepthook + sys.excepthook = excepthook + + # 记录程序启动信息 + logger.info(f"Python版本: {sys.version}") + logger.info(f"运行平台: {sys.platform}") + # 检查配置中是否启用了调试模式 config = load_config() debug_mode = config.get("debug_mode", False) @@ -48,6 +80,7 @@ if __name__ == "__main__": privacy_manager = PrivacyManager() except Exception as e: logger.error(f"初始化隐私协议管理器失败: {e}") + logger.error(f"错误详情: {traceback.format_exc()}") QMessageBox.critical( None, "隐私协议加载错误", diff --git a/source/core/handlers/uninstall_handler.py b/source/core/handlers/uninstall_handler.py index 7171c96..5989211 100644 --- a/source/core/handlers/uninstall_handler.py +++ b/source/core/handlers/uninstall_handler.py @@ -75,7 +75,11 @@ class UninstallHandler(QObject): if debug_mode: logger.debug(f"DEBUG: 卸载功能 - 用户选择了目录: {selected_folder}") - self.main_window.show_loading_dialog("正在识别游戏目录...") + # 使用UI管理器显示加载对话框 + if hasattr(self.main_window, 'ui_manager'): + self.main_window.ui_manager.show_loading_dialog("正在识别游戏目录...") + else: + logger.warning("无法访问UI管理器,无法显示加载对话框") self.uninstall_thread = UninstallThread(self, selected_folder) self.uninstall_thread.finished.connect(self.on_game_detection_finished) @@ -83,7 +87,11 @@ class UninstallHandler(QObject): def on_game_detection_finished(self, game_dirs): """游戏识别完成后的回调""" - self.main_window.hide_loading_dialog() + # 使用UI管理器隐藏加载对话框 + if hasattr(self.main_window, 'ui_manager'): + self.main_window.ui_manager.hide_loading_dialog() + else: + logger.warning("无法访问UI管理器,无法隐藏加载对话框") if not game_dirs: QMessageBox.information( diff --git a/source/utils/logger.py b/source/utils/logger.py index b7d059f..5cb779c 100644 --- a/source/utils/logger.py +++ b/source/utils/logger.py @@ -4,6 +4,7 @@ import datetime import sys import glob import time +import traceback from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler from config.config import LOG_DIR, LOG_FILE, LOG_LEVEL, LOG_MAX_SIZE, LOG_BACKUP_COUNT, LOG_RETENTION_DAYS @@ -68,6 +69,30 @@ class Logger: except Exception: pass +# 增加异常钩子,确保未捕获的异常也会记录到日志文件中 +def log_uncaught_exceptions(exc_type, exc_value, exc_traceback): + """处理未捕获的异常,记录到日志中""" + if issubclass(exc_type, KeyboardInterrupt): + # 对于键盘中断,使用默认处理 + sys.__excepthook__(exc_type, exc_value, exc_traceback) + return + + # 获取主日志记录器 + logger = logging.getLogger('main') + + # 格式化异常信息 + lines = traceback.format_exception(exc_type, exc_value, exc_traceback) + error_message = '未捕获的异常:\n' + ''.join(lines) + + # 记录到日志中 + logger.critical(error_message) + + # 同时也显示在控制台 + sys.__excepthook__(exc_type, exc_value, exc_traceback) + +# 设置全局异常处理器 +sys.excepthook = log_uncaught_exceptions + def cleanup_old_logs(retention_days=7): """清理超过指定天数的旧日志文件 @@ -147,6 +172,7 @@ def setup_logger(name): # 创建更详细的格式器,包括模块名、文件名和行号 formatter = URLCensorFormatter('%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s') + # 设置处理器的格式化器 console_handler.setFormatter(formatter) if main_file_handler: main_file_handler.setFormatter(formatter) @@ -156,4 +182,7 @@ def setup_logger(name): if main_file_handler: logger.addHandler(main_file_handler) + # 确保异常可以被正确记录 + logger.propagate = True + return logger \ No newline at end of file