This commit is contained in:
2025-10-29 22:20:21 +08:00
commit 32b3b7b29a
111 changed files with 344425 additions and 0 deletions

View File

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