添加项目源代码

This commit is contained in:
huangzhenpc
2025-02-20 20:20:19 +08:00
parent 7c63d8a390
commit 268a32f78f
76 changed files with 3344 additions and 0 deletions

227
utils/version_manager.py Normal file
View 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