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