301 lines
12 KiB
Python
301 lines
12 KiB
Python
# coding: utf-8
|
||
import os
|
||
import sys
|
||
|
||
import requests
|
||
from PyQt6.QtCore import Qt, QThread, pyqtSignal
|
||
from PyQt6.QtWidgets import (
|
||
QLabel,
|
||
QMessageBox,
|
||
QSizePolicy,
|
||
QSpacerItem,
|
||
QVBoxLayout,
|
||
QWidget,
|
||
)
|
||
from qfluentwidgets import (ComboBoxSettingCard, FluentIcon, ImageLabel, MessageBox, PrimaryPushSettingCard,
|
||
SettingCardGroup, SwitchSettingCard)
|
||
|
||
from app.core import cfg, lang, qconfig, signalBus
|
||
from app.core.utils.version import version
|
||
|
||
|
||
class AppInfoInterface(QWidget):
|
||
"""
|
||
APP信息页面
|
||
包含语言切换功能
|
||
"""
|
||
|
||
def __init__(self, parent=None):
|
||
super().__init__(parent)
|
||
self.setObjectName("appInfoInterface")
|
||
self.initUI()
|
||
self.connectSignalToSlot()
|
||
# 移除初始化时的自动检查,改为由登录成功信号触发
|
||
|
||
def initUI(self):
|
||
# 创建主布局
|
||
mainLayout = QVBoxLayout(self)
|
||
mainLayout.setContentsMargins(30, 30, 30, 30)
|
||
mainLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
|
||
|
||
self.titleImageLabel = ImageLabel(":app/images/title.png", self)
|
||
self.titleImageLabel.scaledToHeight(130)
|
||
mainLayout.addWidget(self.titleImageLabel, 0, Qt.AlignmentFlag.AlignHCenter)
|
||
|
||
# 添加标题
|
||
self.titleLabel = QLabel(lang("应用信息"))
|
||
self.titleLabel.setStyleSheet("QLabel { font-size: 24px; font-weight: bold; }")
|
||
mainLayout.addWidget(self.titleLabel)
|
||
|
||
# 创建设置卡组
|
||
self.languageGroup = SettingCardGroup(lang("语言设置"), self)
|
||
|
||
# 语言选择设置卡
|
||
self.languageCard = ComboBoxSettingCard(
|
||
title=lang("语言设置"),
|
||
icon=FluentIcon.LANGUAGE,
|
||
texts=["中文", "English"],
|
||
configItem=cfg.language,
|
||
parent=self.languageGroup,
|
||
)
|
||
|
||
# 将设置卡添加到组
|
||
self.languageGroup.addSettingCard(self.languageCard)
|
||
|
||
# 将设置卡组添加到主布局
|
||
mainLayout.addWidget(self.languageGroup)
|
||
|
||
# 创建更新设置卡组
|
||
self.updateGroup = SettingCardGroup(lang("更新设置"), self)
|
||
|
||
# 自动更新设置开关
|
||
self.autoUpdateSwitch = SwitchSettingCard(
|
||
title=lang("开启自动更新"),
|
||
icon=FluentIcon.UPDATE,
|
||
configItem=cfg.checkUpdateAtStartUp,
|
||
parent=self.updateGroup,
|
||
)
|
||
|
||
# 手动检查更新设置卡
|
||
self.checkUpdateCard = PrimaryPushSettingCard(
|
||
title=lang("检查更新"),
|
||
text=lang("检查是否有新版本可用"),
|
||
icon=FluentIcon.UPDATE,
|
||
parent=self.updateGroup,
|
||
)
|
||
|
||
# 当前版本信息
|
||
self.versionLabel = QLabel(f"{lang('当前版本')}: {version}")
|
||
self.versionLabel.setStyleSheet(
|
||
"QLabel { font-size: 14px; color: #666; margin-top: 10px; margin-left: 10px; }"
|
||
)
|
||
|
||
# 将设置卡添加到组
|
||
self.updateGroup.addSettingCard(self.autoUpdateSwitch)
|
||
self.updateGroup.addSettingCard(self.checkUpdateCard)
|
||
self.updateGroup.layout().addWidget(self.versionLabel)
|
||
|
||
# 将更新设置卡组添加到主布局
|
||
mainLayout.addWidget(self.updateGroup)
|
||
|
||
# 添加空白占位符
|
||
spacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
|
||
mainLayout.addItem(spacer)
|
||
|
||
# 底部空间
|
||
bottomSpacer = QSpacerItem(20, 100, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
|
||
mainLayout.addItem(bottomSpacer)
|
||
|
||
def connectSignalToSlot(self):
|
||
# 连接语言变更信号
|
||
signalBus.languageChanged.connect(self.updateUI)
|
||
# 连接ComboBox的当前文本变更信号
|
||
self.languageCard.comboBox.currentTextChanged.connect(self.onLanguageChanged)
|
||
# 连接检查更新按钮信号
|
||
self.checkUpdateCard.clicked.connect(self.manualCheckUpdate)
|
||
# 自动更新开关的信号已通过configItem自动连接,无需额外处理
|
||
# 连接登录成功信号,在用户登录后执行自动检查更新
|
||
signalBus.loginSuccessSignal.connect(self.onLoginSuccess)
|
||
|
||
def checkUpdate(self):
|
||
"""检查应用更新"""
|
||
try:
|
||
# 发送请求获取应用信息
|
||
url = "https://leon.miaostars.com/api.php?t=getappinfo&id=23"
|
||
response = requests.get(url, timeout=10)
|
||
response.raise_for_status()
|
||
|
||
# 解析JSON响应
|
||
data = response.json()
|
||
|
||
if data.get("status") == "success":
|
||
app_data = data.get("data", {})
|
||
versions = app_data.get("versions", [])
|
||
|
||
if versions:
|
||
# 获取最新版本
|
||
latest_version = versions[0].get("version", "")
|
||
|
||
# 比较版本号 - 只要版本不同就提示更新
|
||
if latest_version and latest_version != version:
|
||
# 有新版本
|
||
changelog = versions[0].get("changelog", "")
|
||
api_file_path = versions[0].get("file_path", "")
|
||
# 确保使用完整的URL,如果路径不包含协议,则添加域名前缀
|
||
if api_file_path:
|
||
# 检查是否是完整的URL
|
||
if not (
|
||
api_file_path.startswith("http://")
|
||
or api_file_path.startswith("https://")
|
||
):
|
||
# 添加域名前缀,确保链接完整
|
||
file_path = (
|
||
f"https://leon.miaostars.com/{api_file_path}"
|
||
)
|
||
else:
|
||
file_path = api_file_path
|
||
else:
|
||
# 使用默认下载链接
|
||
file_path = "https://leon.miaostars.com/app.php?id=23"
|
||
|
||
# 使用QFluentWidgets的MessageBox提示用户更新
|
||
msg_box = MessageBox(
|
||
lang("发现新版本"),
|
||
f"{lang('当前版本')}: {version}\n{lang('最新版本')}: {latest_version}\n\n{lang('更新内容')}:\n{changelog}",
|
||
self,
|
||
)
|
||
msg_box.yesButton.setText(lang("立即更新"))
|
||
msg_box.cancelButton.setText(lang("稍后更新"))
|
||
|
||
# QFluentWidgets的MessageBox.exec()返回True表示用户点击了确认按钮
|
||
if msg_box.exec():
|
||
# 添加下载更新的逻辑
|
||
# 例如:打开浏览器访问下载链接
|
||
if file_path:
|
||
import webbrowser
|
||
|
||
webbrowser.open(file_path)
|
||
return True
|
||
|
||
# 没有新版本或请求失败
|
||
return False
|
||
except Exception as e:
|
||
print(f"检查更新失败: {e}")
|
||
# 如果是手动检查更新,则显示错误提示
|
||
if hasattr(self, "is_manual_check") and self.is_manual_check:
|
||
error_box = MessageBox(
|
||
lang("检查更新失败"),
|
||
f"{lang('无法连接到更新服务器,请稍后再试。')}\n{str(e)}",
|
||
self,
|
||
)
|
||
error_box.cancelButton.setVisible(False)
|
||
error_box.exec()
|
||
return False
|
||
|
||
def manualCheckUpdate(self):
|
||
"""手动检查更新"""
|
||
self.is_manual_check = True
|
||
has_update = self.checkUpdate()
|
||
if not has_update and self.is_manual_check:
|
||
# 如果是手动检查且没有更新
|
||
no_update_box = MessageBox(
|
||
lang("已是最新版本"),
|
||
f"{lang('当前版本')} {version} {lang('已是最新版本。')}",
|
||
self,
|
||
)
|
||
no_update_box.cancelButton.setVisible(False)
|
||
no_update_box.exec()
|
||
self.is_manual_check = False
|
||
|
||
def autoCheckUpdate(self):
|
||
"""自动检查更新"""
|
||
print(f"自动检查更新已触发,配置状态: {cfg.checkUpdateAtStartUp.value}")
|
||
|
||
# 在单独的线程中执行,避免阻塞UI
|
||
class UpdateCheckThread(QThread):
|
||
update_available = pyqtSignal(bool)
|
||
|
||
def run(self):
|
||
try:
|
||
print("开始检查更新...")
|
||
url = "https://leon.miaostars.com/api.php?t=getappinfo&id=23"
|
||
response = requests.get(url, timeout=10)
|
||
response.raise_for_status()
|
||
data = response.json()
|
||
|
||
if data.get("status") == "success":
|
||
app_data = data.get("data", {})
|
||
versions = app_data.get("versions", [])
|
||
|
||
if versions:
|
||
latest_version = versions[0].get("version", "")
|
||
print(f"当前版本: {version}, 最新版本: {latest_version}")
|
||
if latest_version and latest_version != version:
|
||
print("发现新版本,准备显示更新提示")
|
||
self.update_available.emit(True)
|
||
return
|
||
except Exception as e:
|
||
print(f"自动检查更新出错: {e}")
|
||
|
||
self.update_available.emit(False)
|
||
|
||
# 创建并启动线程
|
||
self.update_thread = UpdateCheckThread()
|
||
self.update_thread.update_available.connect(self.onAutoUpdateAvailable)
|
||
self.update_thread.start()
|
||
|
||
def onAutoUpdateAvailable(self, available):
|
||
"""自动检查更新结果处理"""
|
||
print(f"自动检查更新结果: {'有更新' if available else '无更新'}")
|
||
if available:
|
||
# 自动检查到更新时,再次调用checkUpdate显示提示
|
||
self.is_manual_check = False
|
||
self.checkUpdate()
|
||
|
||
def onLoginSuccess(self):
|
||
"""用户登录成功后的处理"""
|
||
print(f"用户登录成功,检查是否开启自动更新: {cfg.checkUpdateAtStartUp.value}")
|
||
# 在用户登录成功后,根据配置决定是否自动检查更新
|
||
if cfg.checkUpdateAtStartUp.value:
|
||
self.autoCheckUpdate()
|
||
|
||
def onLanguageChanged(self, text):
|
||
# 语言变更处理
|
||
# 从选项映射获取对应的语言代码
|
||
lang_map = {"中文": "zh", "English": "en"}
|
||
lang_code = lang_map.get(text, "zh")
|
||
|
||
# 保存到配置
|
||
qconfig.set(cfg.language, lang_code)
|
||
|
||
# 显示重启提示
|
||
reply = QMessageBox.question(
|
||
self,
|
||
lang("语言变更"),
|
||
lang("语言已变更,是否立即重启应用以应用新语言?"),
|
||
QMessageBox.Yes | QMessageBox.No,
|
||
QMessageBox.Yes,
|
||
)
|
||
|
||
if reply == QMessageBox.Yes:
|
||
# 重启应用
|
||
self.restartApplication()
|
||
|
||
def updateUI(self):
|
||
# 更新UI文本
|
||
self.titleLabel.setText(lang("应用信息"))
|
||
self.hintLabel.setText(lang("此页面正在建设中..."))
|
||
# 注意:SettingCardGroup可能没有setTitle方法,需要根据实际API调整
|
||
|
||
def restartApplication(self):
|
||
"""重启应用程序"""
|
||
# 保存配置
|
||
qconfig.save()
|
||
# 获取当前Python解释器路径和脚本路径
|
||
python = sys.executable
|
||
script = os.path.abspath(sys.argv[0])
|
||
# 退出当前进程
|
||
sys.exit()
|
||
# 注意:在实际应用中,这里应该使用subprocess重新启动应用,但为了安全考虑,
|
||
# 这里仅退出当前进程,让用户手动重启
|