添加项目源代码
This commit is contained in:
227
utils/version_manager.py
Normal file
227
utils/version_manager.py
Normal file
@@ -0,0 +1,227 @@
|
||||
"""版本管理模块
|
||||
|
||||
职责:
|
||||
1. 检查软件更新
|
||||
2. 管理版本信息
|
||||
3. 处理更新下载
|
||||
4. 维护更新配置
|
||||
|
||||
设计原则:
|
||||
1. 单一职责
|
||||
2. 配置与逻辑分离
|
||||
3. 异常处理标准化
|
||||
4. 日志完整记录
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
import urllib3
|
||||
from pathlib import Path
|
||||
from typing import Dict, Tuple, Optional
|
||||
from logger import logger
|
||||
from config import config
|
||||
|
||||
class VersionConfig:
|
||||
"""版本配置类"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化版本配置"""
|
||||
self.update_url = f"{config.base_url}/admin/api.version/check"
|
||||
self.config_dir = os.path.join(os.getenv('APPDATA'), 'TingquanAssistant')
|
||||
self.config_file = os.path.join(self.config_dir, 'version.json')
|
||||
|
||||
# 确保配置目录存在
|
||||
os.makedirs(self.config_dir, exist_ok=True)
|
||||
|
||||
# 获取版本号
|
||||
self.current_version = self._get_version()
|
||||
|
||||
def _get_version(self) -> str:
|
||||
"""
|
||||
从version.txt文件获取当前版本号
|
||||
如果是打包后的程序,从打包目录读取
|
||||
如果是开发环境,从根目录读取
|
||||
"""
|
||||
try:
|
||||
# 确定version.txt的路径
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 如果是打包后的程序
|
||||
base_path = Path(sys._MEIPASS)
|
||||
else:
|
||||
# 如果是开发环境,获取根目录路径
|
||||
current_file = Path(__file__)
|
||||
base_path = current_file.parent.parent # utils -> root
|
||||
|
||||
version_file = base_path / "version.txt"
|
||||
|
||||
# 读取版本号
|
||||
if version_file.exists():
|
||||
with open(version_file, "r", encoding="utf-8") as f:
|
||||
version = f.read().strip()
|
||||
logger.get_logger().info(f"当前版本: {version}")
|
||||
return version
|
||||
else:
|
||||
logger.get_logger().error(f"版本文件不存在: {version_file}")
|
||||
return "0.0.0"
|
||||
|
||||
except Exception as e:
|
||||
logger.get_logger().error(f"读取版本号失败: {str(e)}")
|
||||
return "0.0.0"
|
||||
|
||||
class VersionManager:
|
||||
"""版本管理器"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化版本管理器"""
|
||||
self.config = VersionConfig()
|
||||
|
||||
# 禁用SSL警告
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
def _load_config(self) -> Dict:
|
||||
"""加载版本配置"""
|
||||
try:
|
||||
if os.path.exists(self.config.config_file):
|
||||
with open(self.config.config_file, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
return {}
|
||||
except Exception as e:
|
||||
logger.get_logger().error(f"加载版本配置失败: {str(e)}")
|
||||
return {}
|
||||
|
||||
def _save_config(self, config_data: Dict) -> bool:
|
||||
"""保存版本配置"""
|
||||
try:
|
||||
with open(self.config.config_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(config_data, f, indent=2, ensure_ascii=False)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.get_logger().error(f"保存版本配置失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def check_update(self) -> Tuple[bool, str, Optional[Dict]]:
|
||||
"""
|
||||
检查更新
|
||||
|
||||
Returns:
|
||||
Tuple[bool, str, Optional[Dict]]:
|
||||
- bool: 是否有更新
|
||||
- str: 消息
|
||||
- Optional[Dict]: 更新信息
|
||||
"""
|
||||
try:
|
||||
log = logger.get_logger()
|
||||
log.info(f"开始检查更新,当前版本: {self.config.current_version}")
|
||||
|
||||
# 准备请求数据
|
||||
data = {
|
||||
"version": self.config.current_version,
|
||||
"platform": "windows"
|
||||
}
|
||||
|
||||
log.info(f"请求URL: {self.config.update_url}")
|
||||
log.info(f"请求数据: {json.dumps(data, ensure_ascii=False)}")
|
||||
log.info(f"请求头: {json.dumps(config.request_config['headers'], ensure_ascii=False)}")
|
||||
|
||||
# 发送更新检查请求
|
||||
response = requests.post(
|
||||
self.config.update_url,
|
||||
json=data,
|
||||
headers=config.request_config["headers"],
|
||||
timeout=config.request_config["timeout"],
|
||||
verify=config.request_config["verify"]
|
||||
)
|
||||
|
||||
log.info(f"响应状态码: {response.status_code}")
|
||||
log.info(f"响应内容: {response.text}")
|
||||
|
||||
# 解析响应
|
||||
result = response.json()
|
||||
|
||||
# 检查响应码(0或1都是正常响应)
|
||||
if result.get("code") in [0, 1]:
|
||||
update_info = result.get("data", {})
|
||||
|
||||
if update_info.get("has_update"):
|
||||
# 有更新可用
|
||||
version_info = update_info.get("version_info", {})
|
||||
new_version = version_info.get("version")
|
||||
update_msg = version_info.get("update_msg", "")
|
||||
download_url = version_info.get("download_url", "")
|
||||
is_force = update_info.get("is_force", 0)
|
||||
|
||||
log.info(f"发现新版本: {new_version}")
|
||||
log.info(f"更新信息: {json.dumps(version_info, ensure_ascii=False)}")
|
||||
|
||||
update_data = {
|
||||
"version": new_version,
|
||||
"message": update_msg,
|
||||
"download_url": download_url,
|
||||
"is_force": bool(is_force),
|
||||
"check_time": update_info.get("check_time")
|
||||
}
|
||||
|
||||
# 更新配置
|
||||
config_data = self._load_config()
|
||||
config_data["last_check_update"] = update_data
|
||||
self._save_config(config_data)
|
||||
|
||||
return True, f"发现新版本: {new_version}", update_data
|
||||
else:
|
||||
log.info("当前已是最新版本")
|
||||
return False, "当前已是最新版本", None
|
||||
|
||||
else:
|
||||
error_msg = result.get("msg", "检查更新失败")
|
||||
log.error(f"检查更新失败: {error_msg}")
|
||||
log.error(f"错误响应: {json.dumps(result, ensure_ascii=False)}")
|
||||
return False, f"检查更新失败: {error_msg}", None
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
error_msg = f"网络连接失败: {str(e)}"
|
||||
logger.get_logger().error(error_msg)
|
||||
return False, error_msg, None
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
error_msg = f"解析响应失败: {str(e)}"
|
||||
logger.get_logger().error(error_msg)
|
||||
logger.get_logger().error(f"无法解析的响应内容: {response.text}")
|
||||
return False, error_msg, None
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"检查更新异常: {str(e)}"
|
||||
logger.get_logger().error(error_msg)
|
||||
return False, error_msg, None
|
||||
|
||||
def get_last_update_info(self) -> Optional[Dict]:
|
||||
"""获取上次检查的更新信息"""
|
||||
try:
|
||||
config_data = self._load_config()
|
||||
update_info = config_data.get("last_check_update")
|
||||
|
||||
if update_info:
|
||||
logger.get_logger().info(f"获取到未完成的更新信息: {update_info['version']}")
|
||||
|
||||
return update_info
|
||||
|
||||
except Exception as e:
|
||||
logger.get_logger().error(f"获取更新信息失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def clear_update_info(self) -> bool:
|
||||
"""清除更新信息"""
|
||||
try:
|
||||
config_data = self._load_config()
|
||||
if "last_check_update" in config_data:
|
||||
del config_data["last_check_update"]
|
||||
success = self._save_config(config_data)
|
||||
if success:
|
||||
logger.get_logger().info("更新信息已清除")
|
||||
return success
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.get_logger().error(f"清除更新信息失败: {str(e)}")
|
||||
return False
|
||||
Reference in New Issue
Block a user