Files
leonpan-pc/app/view/app_info_interface.py
2025-10-29 22:20:21 +08:00

301 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.jpg", 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重新启动应用但为了安全考虑
# 这里仅退出当前进程,让用户手动重启