[patch] 优化版本管理显示 与 更新提示(修改表名信息)
This commit is contained in:
@@ -167,7 +167,7 @@ class DatabaseVersionManager:
|
|||||||
try:
|
try:
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT version FROM web_versionhistory
|
SELECT version FROM web_version_history
|
||||||
WHERE type = '水滴智能通讯插件' AND is_delete = FALSE
|
WHERE type = '水滴智能通讯插件' AND is_delete = FALSE
|
||||||
ORDER BY release_time DESC LIMIT 1
|
ORDER BY release_time DESC LIMIT 1
|
||||||
""")
|
""")
|
||||||
@@ -211,7 +211,7 @@ class DatabaseVersionManager:
|
|||||||
try:
|
try:
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT version FROM web_versionhistory
|
SELECT version FROM web_version_history
|
||||||
WHERE content LIKE %s AND type = '水滴智能通讯插件'
|
WHERE content LIKE %s AND type = '水滴智能通讯插件'
|
||||||
ORDER BY release_time DESC LIMIT 1
|
ORDER BY release_time DESC LIMIT 1
|
||||||
""", (f'%{commit_id}%',))
|
""", (f'%{commit_id}%',))
|
||||||
@@ -241,7 +241,7 @@ class DatabaseVersionManager:
|
|||||||
|
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
INSERT INTO web_versionhistory
|
INSERT INTO web_version_history
|
||||||
(id, version, type, content, download_url, release_time, is_delete)
|
(id, version, type, content, download_url, release_time, is_delete)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
||||||
""", (
|
""", (
|
||||||
|
|||||||
@@ -8,29 +8,29 @@ jobs:
|
|||||||
gui-version-release:
|
gui-version-release:
|
||||||
runs-on: windows
|
runs-on: windows
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: E:\shuidrop_gui
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# Step 1: Clone repository manually
|
# Step 1: Checkout repository (使用 Gitea 自动检出,适配所有路径)
|
||||||
- name: Clone repository
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.ref_name }} # 动态分支(master 或 develop)
|
||||||
|
fetch-depth: 0 # 获取完整历史(用于版本号计算)
|
||||||
|
|
||||||
|
# Step 1.5: Verify checkout
|
||||||
|
- name: Verify checkout
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
Write-Host "Cloning repository..."
|
Write-Host "=========================================="
|
||||||
|
Write-Host "Repository Information"
|
||||||
# Change to workspace directory
|
Write-Host "=========================================="
|
||||||
cd E:\shuidrop_gui
|
|
||||||
|
|
||||||
Write-Host "Current directory: $(Get-Location)"
|
Write-Host "Current directory: $(Get-Location)"
|
||||||
|
Write-Host "Branch: ${{ github.ref_name }}"
|
||||||
|
Write-Host "Commit: ${{ github.sha }}"
|
||||||
|
Write-Host "Author: ${{ github.actor }}"
|
||||||
|
Write-Host ""
|
||||||
Write-Host "Git status:"
|
Write-Host "Git status:"
|
||||||
git status
|
git status
|
||||||
|
Write-Host "=========================================="
|
||||||
Write-Host "Fetching latest changes..."
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/master
|
|
||||||
|
|
||||||
Write-Host "Repository ready"
|
|
||||||
|
|
||||||
# Step 2: Check Python environment
|
# Step 2: Check Python environment
|
||||||
- name: Check Python environment
|
- name: Check Python environment
|
||||||
@@ -137,21 +137,27 @@ jobs:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
git config user.name "Gitea Actions"
|
# 配置 Git 用户(自动化提交)
|
||||||
git config user.email "actions@gitea.local"
|
git config user.name "Gitea Actions Bot"
|
||||||
|
git config user.email "bot@gitea.local"
|
||||||
|
|
||||||
|
# 添加修改的文件
|
||||||
git add config.py
|
git add config.py
|
||||||
git add version_history.json
|
git add version_history.json
|
||||||
|
|
||||||
|
# 检查是否有变更
|
||||||
$hasChanges = git diff --staged --quiet
|
$hasChanges = git diff --staged --quiet
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
# 动态获取当前分支名 (用于测试使用)
|
# 动态获取当前分支名(兼容 master 和 develop)
|
||||||
$BRANCH = git rev-parse --abbrev-ref HEAD
|
$BRANCH = "${{ github.ref_name }}"
|
||||||
git commit -m "[skip ci] Update version to $VERSION"
|
Write-Host "Committing to branch: $BRANCH"
|
||||||
|
|
||||||
|
git commit -m "[skip ci] 🤖 自动更新版本到 v$VERSION"
|
||||||
git push origin $BRANCH
|
git push origin $BRANCH
|
||||||
Write-Host "Version changes committed and pushed to $BRANCH"
|
|
||||||
|
Write-Host "✅ Version changes committed and pushed to $BRANCH"
|
||||||
} else {
|
} else {
|
||||||
Write-Host "No changes to commit"
|
Write-Host "ℹ️ No changes to commit"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Step 6: Display summary
|
# Step 6: Display summary
|
||||||
|
|||||||
22
main.py
22
main.py
@@ -718,6 +718,23 @@ class LoginWindow(QMainWindow):
|
|||||||
def show_update_notification(self, latest_version, download_url):
|
def show_update_notification(self, latest_version, download_url):
|
||||||
"""显示版本更新通知"""
|
"""显示版本更新通知"""
|
||||||
try:
|
try:
|
||||||
|
self.add_log(f"🔔 准备显示更新通知: v{latest_version}", "INFO")
|
||||||
|
self.add_log(f" 下载地址: {download_url if download_url else '(空)'}", "INFO")
|
||||||
|
|
||||||
|
# 检查下载地址
|
||||||
|
if not download_url or download_url.strip() == "":
|
||||||
|
# 下载地址为空,只显示通知,不提供下载
|
||||||
|
QMessageBox.information(
|
||||||
|
self,
|
||||||
|
"版本更新",
|
||||||
|
f"发现新版本 {latest_version}!\n\n"
|
||||||
|
f"下载地址暂未配置,请稍后再试或联系管理员。",
|
||||||
|
QMessageBox.Ok
|
||||||
|
)
|
||||||
|
self.add_log(f"⚠️ 新版本 {latest_version} 的下载地址为空,已通知用户", "WARNING")
|
||||||
|
return # 安全返回,不崩溃
|
||||||
|
|
||||||
|
# 下载地址有效,显示更新对话框
|
||||||
reply = QMessageBox.question(
|
reply = QMessageBox.question(
|
||||||
self,
|
self,
|
||||||
"版本更新",
|
"版本更新",
|
||||||
@@ -727,7 +744,12 @@ class LoginWindow(QMainWindow):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if reply == QMessageBox.Yes:
|
if reply == QMessageBox.Yes:
|
||||||
|
self.add_log("用户选择立即更新", "INFO")
|
||||||
self.trigger_update(download_url, latest_version)
|
self.trigger_update(download_url, latest_version)
|
||||||
|
else:
|
||||||
|
self.add_log("用户选择稍后更新", "INFO")
|
||||||
|
# 用户点击"否",不做任何操作,程序继续运行
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.add_log(f"❌ 显示更新通知失败: {e}", "ERROR")
|
self.add_log(f"❌ 显示更新通知失败: {e}", "ERROR")
|
||||||
import traceback
|
import traceback
|
||||||
|
|||||||
216
version_checker.py
Normal file
216
version_checker.py
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
#!/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()
|
||||||
|
|
||||||
18
version_history.json
Normal file
18
version_history.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"version": "1.4.7",
|
||||||
|
"update_type": "patch",
|
||||||
|
"content": "当前版本 - 多平台客服智能助手",
|
||||||
|
"author": "开发团队",
|
||||||
|
"commit_hash": "",
|
||||||
|
"commit_short_hash": "",
|
||||||
|
"branch": "develop",
|
||||||
|
"release_time": "2025-10-10 00:00:00",
|
||||||
|
"stats": {
|
||||||
|
"files_changed": 0,
|
||||||
|
"lines_added": 0,
|
||||||
|
"lines_deleted": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
Reference in New Issue
Block a user