#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 版本检查器 定期检查后端是否有新版本,并通知GUI更新 """ import threading import time import logging from typing import Callable, Optional logger = logging.getLogger(__name__) class VersionChecker: """ 版本检查器 定期向后端发送版本检查请求,如果有新版本则触发更新回调 """ def __init__(self, backend_client, update_callback: Optional[Callable] = None): """ 初始化版本检查器 Args: backend_client: 后端WebSocket客户端实例 update_callback: 发现新版本时的回调函数 callback(latest_version, download_url) """ self.backend_client = backend_client self.update_callback = update_callback self.is_running = False self.check_interval = 600 # 10分钟检查一次 self.thread = None # 从config获取当前版本 try: from config import APP_VERSION self.current_version = APP_VERSION logger.info(f"✅ 版本检查器初始化成功,当前版本: v{self.current_version}") except ImportError: self.current_version = "1.0.0" logger.warning("⚠️ 无法从config读取APP_VERSION,使用默认版本: 1.0.0") def start(self): """启动版本检查线程""" if self.is_running: logger.warning("版本检查器已在运行中") return self.is_running = True self.thread = threading.Thread(target=self._check_loop, daemon=True) self.thread.start() logger.info(f"✅ 版本检查器已启动,每{self.check_interval}秒检查一次更新") def stop(self): """停止版本检查""" self.is_running = False if self.thread: self.thread.join(timeout=2) logger.info("版本检查器已停止") def _check_loop(self): """版本检查循环""" # 等待5秒后首次检查(避免启动时立即检查) time.sleep(5) while self.is_running: try: self._perform_version_check() except Exception as e: logger.error(f"版本检查失败: {e}") # 等待下次检查 time.sleep(self.check_interval) def _perform_version_check(self): """执行版本检查""" try: if not self.backend_client or not self.backend_client.is_connected: logger.debug("后端未连接,跳过版本检查") return # 向后端发送版本检查请求 message = { 'type': 'version_check', 'current_version': self.current_version, 'client_type': 'gui' } logger.debug(f"发送版本检查请求: v{self.current_version}") self.backend_client.send_message(message) except Exception as e: logger.error(f"发送版本检查请求失败: {e}") def handle_version_response(self, response: dict): """ 处理后端返回的版本检查响应 Args: response: 后端响应消息 { "type": "version_response", "has_update": true, "latest_version": "1.5.0", "current_version": "1.4.7", "download_url": "https://example.com/download/v1.5.0", "update_content": "修复了若干Bug" } """ try: has_update = response.get('has_update', None) # 改为 None,便于后续判断 latest_version = response.get('latest_version', '') current_version = response.get('current_version', self.current_version) download_url = response.get('download_url', '') update_content = response.get('update_content', '') logger.info(f"📡 收到版本检查响应: 当前v{current_version}, 最新v{latest_version}") # 如果后端没有返回 has_update 字段,自动通过版本比较判断 if has_update is None and latest_version: # 自动比较版本号 compare_result = self.compare_versions(latest_version, current_version) has_update = compare_result > 0 # latest > current 表示有更新 logger.info(f"🔍 后端未返回has_update字段,通过版本比较判断: {has_update}") if has_update and latest_version: logger.info(f"🔔 发现新版本: v{latest_version}") if update_content: logger.info(f"📝 更新内容: {update_content[:100]}") # 触发更新回调 if self.update_callback: try: self.update_callback(latest_version, download_url) except Exception as e: logger.error(f"执行更新回调失败: {e}") else: logger.debug(f"✅ 当前已是最新版本: v{current_version}") except Exception as e: logger.error(f"处理版本响应失败: {e}") def compare_versions(self, version1: str, version2: str) -> int: """ 比较两个版本号 Args: version1: 版本1 (如 "1.4.7") version2: 版本2 (如 "1.5.0") Returns: 1: version1 > version2 0: version1 == version2 -1: version1 < version2 """ try: v1_parts = [int(x) for x in version1.split('.')] v2_parts = [int(x) for x in version2.split('.')] # 补齐长度 max_len = max(len(v1_parts), len(v2_parts)) v1_parts.extend([0] * (max_len - len(v1_parts))) v2_parts.extend([0] * (max_len - len(v2_parts))) # 逐位比较 for v1, v2 in zip(v1_parts, v2_parts): if v1 > v2: return 1 elif v1 < v2: return -1 return 0 except Exception as e: logger.error(f"版本比较失败: {e}") return 0 # 使用示例 if __name__ == '__main__': # 配置日志 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s [%(levelname)s] %(message)s' ) # 模拟使用 class MockBackendClient: is_connected = True def send_message(self, msg): print(f"发送消息: {msg}") def on_update_available(version, url): print(f"🔔 发现新版本: {version}, 下载地址: {url}") client = MockBackendClient() checker = VersionChecker(client, on_update_available) checker.start() # 模拟接收后端响应 time.sleep(2) response = { "type": "version_response", "has_update": True, "latest_version": "1.5.0", "current_version": "1.4.7", "download_url": "https://example.com/download", "update_content": "修复了若干Bug" } checker.handle_version_response(response) time.sleep(2) checker.stop()