diff --git a/.gitignore b/.gitignore index 8bd4447..3526b0e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ logs/ /pyqt5fluentdesign/output/ /pyqt5fluentdesign/logs/ +/pyqt5fluentdesign/install/ # 忽略Windows系统文件 Thumbs.db diff --git a/pyqt5fluentdesign/__pycache__/app_detail_window.cpython-312.pyc b/pyqt5fluentdesign/__pycache__/app_detail_window.cpython-312.pyc index 6ec0a12..f55be0f 100644 Binary files a/pyqt5fluentdesign/__pycache__/app_detail_window.cpython-312.pyc and b/pyqt5fluentdesign/__pycache__/app_detail_window.cpython-312.pyc differ diff --git a/pyqt5fluentdesign/__pycache__/leonapp_gui.cpython-312.pyc b/pyqt5fluentdesign/__pycache__/leonapp_gui.cpython-312.pyc new file mode 100644 index 0000000..cb201d4 Binary files /dev/null and b/pyqt5fluentdesign/__pycache__/leonapp_gui.cpython-312.pyc differ diff --git a/pyqt5fluentdesign/app_detail_window.py b/pyqt5fluentdesign/app_detail_window.py index f384ea2..e6b7317 100644 --- a/pyqt5fluentdesign/app_detail_window.py +++ b/pyqt5fluentdesign/app_detail_window.py @@ -1,6 +1,6 @@ # 这破代码有人能修复吗 from PyQt5.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, - QPushButton, QFrame, QLabel, QGridLayout) + QPushButton, QFrame, QLabel, QGridLayout, QMessageBox) from PyQt5.QtCore import Qt, QSize, pyqtSignal, QThread from PyQt5.QtGui import QPixmap, QFont from qfluentwidgets import (InfoBar, InfoBarPosition, TitleLabel, SubtitleLabel, @@ -14,6 +14,25 @@ import tempfile import subprocess import platform +def show_error_dialog(title, message): + """显示错误弹窗,模拟Sweet Alert风格""" + # 创建错误消息框 + msg_box = QMessageBox() + msg_box.setIcon(QMessageBox.Critical) + msg_box.setWindowTitle(title) + + # 设置字体大小 + font = QFont() + font.setPointSize(10) + msg_box.setFont(font) + + # 设置消息内容 + msg_box.setText(message) + msg_box.setStandardButtons(QMessageBox.Ok) + + # 显示弹窗 + msg_box.exec_() + class DownloadThread(QThread): """下载线程,用于在后台下载文件""" progress = pyqtSignal(int) @@ -652,34 +671,44 @@ class AppDetailWindow(QMainWindow): # 检查是否有应用数据 if not hasattr(self, 'app_data'): - InfoBar.error( - title="错误", - content="应用数据未加载,请刷新页面后重试。", - orient=Qt.Horizontal, - isClosable=True, - position=InfoBarPosition.TOP, - parent=self - ) + show_error_dialog("错误", "应用数据未加载,请刷新页面后重试。") return - # 创建确认对话框 - reply = QMessageBox.question(self, - "确认安装", - f"您确定要安装{self.app_data.get('name', '未知应用')}吗?\n\n点击'确定'开始安装。", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No) + # 创建Sweet Alert风格的确认对话框 + confirm_box = QMessageBox() + confirm_box.setWindowTitle("确认安装") + confirm_box.setIcon(QMessageBox.Question) + confirm_box.setText(f"您确定要安装{self.app_data.get('name', '未知应用')}吗?\n\n点击'确定'开始安装。") + + # 设置字体大小 + font = QFont() + font.setPointSize(10) + confirm_box.setFont(font) + + # 添加按钮 + confirm_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + confirm_box.setDefaultButton(QMessageBox.No) + + # 显示对话框 + reply = confirm_box.exec_() if reply == QMessageBox.Yes: - # 显示开始安装的提示 - InfoBar.success( - title="安装开始", - content=f"{self.app_data.get('name', '未知应用')}安装已开始,请稍候...", - orient=Qt.Horizontal, - isClosable=True, - position=InfoBarPosition.TOP, - duration=3000, - parent=self - ) + # 创建Sweet Alert风格的成功提示 + success_box = QMessageBox() + success_box.setWindowTitle("安装开始") + success_box.setIcon(QMessageBox.Information) + success_box.setText(f"{self.app_data.get('name', '未知应用')}安装已开始,请稍候...") + + # 设置字体大小 + font = QFont() + font.setPointSize(10) + success_box.setFont(font) + + # 添加按钮 + success_box.setStandardButtons(QMessageBox.Ok) + + # 显示对话框 + success_box.exec_() # 1. 首先尝试从应用数据中获取直接下载链接 download_url = self.app_data.get('direct_download_url') @@ -688,30 +717,75 @@ class AppDetailWindow(QMainWindow): if not download_url: download_url = self.app_data.get('download_url') - # 3. 如果仍然没有下载链接,尝试通过API获取下载链接 + # 3. 根据新API格式,从versions数组中获取最新版本的file_path + if not download_url and 'versions' in self.app_data and isinstance(self.app_data['versions'], list) and self.app_data['versions']: + # 假设versions数组中第一个版本是最新的 + latest_version = self.app_data['versions'][0] + if isinstance(latest_version, dict) and 'file_path' in latest_version: + download_url = latest_version['file_path'] + + # 4. 如果仍然没有下载链接,尝试通过API获取下载链接 if not download_url: try: # 使用app_id通过API获取下载链接 app_id = self.app_data.get('id') if app_id: download_result = self.api_client.make_request('getdownloadlink', {'id': app_id}) - if isinstance(download_result, dict) and 'success' in download_result and download_result['success']: - download_url = download_result.get('data') + if isinstance(download_result, dict): + # 检查是否是新API格式的响应 + if 'data' in download_result: + if isinstance(download_result['data'], dict) and 'versions' in download_result['data'] and download_result['data']['versions']: + latest_version = download_result['data']['versions'][0] + if isinstance(latest_version, dict) and 'file_path' in latest_version: + download_url = latest_version['file_path'] + # 兼容旧API格式 + elif 'success' in download_result and download_result['success']: + download_url = download_result.get('data') except Exception as e: print(f"获取下载链接API调用失败: {str(e)}") # 4. 如果仍然没有下载链接,显示错误信息 if not download_url: - InfoBar.error( - title="错误", - content="无法获取应用的下载链接,请稍后重试。\n可能原因:API返回数据中缺少下载链接字段。", - orient=Qt.Horizontal, - isClosable=True, - position=InfoBarPosition.TOP, - parent=self - ) + show_error_dialog("错误", "无法获取应用的下载链接,请稍后重试。\n可能原因:API返回数据中缺少下载链接字段。") return + # 5. 更健壮的URL处理逻辑 + from urllib.parse import urlparse, quote + import os + + # 检查是否看起来像一个文件名(包含扩展名) + is_filename = False + if '.' in download_url: + # 获取最后一个点后的部分作为扩展名 + extension = download_url.split('.')[-1].lower() + # 常见的应用安装包扩展名 + common_extensions = ['exe', 'apk', 'dmg', 'pkg', 'msi', 'appx', 'deb', 'rpm'] + if extension in common_extensions and len(extension) <= 5: + is_filename = True + + # 如果是文件名或不包含协议,处理为完整URL + if is_filename or not download_url.startswith(('http://', 'https://')): + # 使用基础域名 + base_domain = 'leonmmcoset.jjxmm.win:8010' + + # 对于所有情况,统一使用直链形式,不再使用download.php + # 对文件名/路径进行URL编码,处理空格和特殊字符 + if not download_url.startswith(('http://', 'https://')): + # 使用http协议和基础域名,直接拼接文件名或路径 + encoded_path = quote(download_url) + download_url = f'http://leonmmcoset.jjxmm.win:8010/{encoded_path.lstrip("/")}' + + # 额外检查:确保主机名有效(包含点) + parsed_url = urlparse(download_url) + if '.' not in parsed_url.netloc: + # 如果主机名仍然无效,完全重建URL + base_domain = 'leonmmcoset.jjxmm.win:8010' + path = parsed_url.path or parsed_url.netloc + # 对路径进行URL编码 + encoded_path = quote(path) + # 使用http协议 + download_url = f'http://leonmmcoset.jjxmm.win:8010/{encoded_path.lstrip("/")}' + # 创建进度对话框 self.progress_dialog = QProgressDialog( f"正在下载{self.app_data.get('name', '未知应用')}...", @@ -723,11 +797,31 @@ class AppDetailWindow(QMainWindow): self.progress_dialog.setWindowTitle("正在安装") self.progress_dialog.setMinimumDuration(0) - # 创建临时保存路径 + # 创建保存路径 - 使用代码文件夹所在的install目录 file_extension = ".exe" # 假设是Windows可执行文件 app_name = self.app_data.get('name', '未知应用').replace(' ', '_') - temp_dir = tempfile.gettempdir() - save_path = os.path.join(temp_dir, f"{app_name}_installer{file_extension}") + + # 获取当前脚本所在目录 + import os + current_dir = os.path.dirname(os.path.abspath(__file__)) + # 创建install目录路径 + install_dir = os.path.join(current_dir, 'install') + + # 确保install目录存在 + if not os.path.exists(install_dir): + try: + os.makedirs(install_dir) + except Exception as e: + # 如果创建目录失败,回退到临时目录 + show_error_dialog("创建目录失败", f"无法创建安装目录: {str(e)}\n将使用临时目录") + temp_dir = tempfile.gettempdir() + save_path = os.path.join(temp_dir, f"{app_name}_installer{file_extension}") + else: + # 使用install目录 + save_path = os.path.join(install_dir, f"{app_name}_installer{file_extension}") + else: + # 目录已存在,直接使用 + save_path = os.path.join(install_dir, f"{app_name}_installer{file_extension}") # 创建下载线程 self.download_thread = DownloadThread(download_url, save_path) @@ -749,49 +843,75 @@ class AppDetailWindow(QMainWindow): # 在Windows上,直接运行可执行文件 subprocess.Popen([file_path], shell=True) - # 显示安装成功提示 - InfoBar.success( - title="下载完成", - content=f"安装程序已启动,请按照向导完成安装。\n文件位置:{file_path}", - orient=Qt.Horizontal, - isClosable=True, - position=InfoBarPosition.TOP, - duration=5000, - parent=self - ) + # 创建Sweet Alert风格的下载完成提示 + success_box = QMessageBox() + success_box.setWindowTitle("下载完成") + success_box.setIcon(QMessageBox.Information) + success_box.setText(f"安装程序已启动,请按照向导完成安装。\n文件位置:{file_path}") + + # 设置字体大小 + font = QFont() + font.setPointSize(10) + success_box.setFont(font) + + # 添加按钮 + success_box.setStandardButtons(QMessageBox.Ok) + + # 显示对话框 + success_box.exec_() + + # 打开下载文件夹并选中文件 + subprocess.Popen(f'explorer /select,"{file_path}"') except Exception as e: - InfoBar.error( - title="启动安装程序失败", - content=f"无法启动安装程序: {str(e)}\n您可以手动运行文件: {file_path}", - orient=Qt.Horizontal, - isClosable=True, - position=InfoBarPosition.TOP, - parent=self - ) + show_error_dialog("启动安装程序失败", f"无法启动安装程序: {str(e)}\n您可以手动运行文件: {file_path}") + + # 即使启动安装程序失败,也尝试打开下载文件夹 + try: + subprocess.Popen(f'explorer /select,"{file_path}"') + except Exception as ex: + show_error_dialog("打开文件夹失败", f"无法打开下载文件夹: {str(ex)}") else: # 其他操作系统 - InfoBar.information( - title="下载完成", - content=f"文件已下载完成。\n\n文件位置:{file_path}\n\n请手动运行安装程序。", - orient=Qt.Horizontal, - isClosable=True, - position=InfoBarPosition.TOP, - duration=5000, - parent=self - ) + info_box = QMessageBox() + info_box.setWindowTitle("下载完成") + info_box.setIcon(QMessageBox.Information) + info_box.setText(f"文件已下载完成。\n\n文件位置:{file_path}\n\n请手动运行安装程序。") + + # 设置字体大小 + font = QFont() + font.setPointSize(10) + info_box.setFont(font) + + # 添加按钮 + info_box.setStandardButtons(QMessageBox.Ok) + + # 显示对话框 + info_box.exec_() + + # 打开下载文件夹 + try: + import os + import subprocess + # 获取文件所在目录 + folder_path = os.path.dirname(file_path) + if platform.system() == 'Windows': + # Windows下使用explorer打开文件夹并选中文件 + subprocess.Popen(f'explorer /select,"{file_path}"') + elif platform.system() == 'Darwin': + # macOS下使用open命令打开文件夹 + subprocess.Popen(['open', folder_path]) + else: + # Linux下使用xdg-open打开文件夹 + subprocess.Popen(['xdg-open', folder_path]) + except Exception as e: + show_error_dialog("打开文件夹失败", f"无法打开下载文件夹: {str(e)}") def on_download_error(self, error_msg): """下载错误处理""" self.progress_dialog.reject() - InfoBar.error( - title="安装失败", - content=error_msg, - orient=Qt.Horizontal, - isClosable=True, - position=InfoBarPosition.TOP, - parent=self - ) + # 使用Sweet Alert风格弹窗显示错误 + show_error_dialog("安装失败", error_msg) def share_app(self): """分享应用""" @@ -802,7 +922,7 @@ class AppDetailWindow(QMainWindow): # 创建分享链接 app_share_url = f"leonapp://app/{self.app_id}" - web_share_url = f"http://leonmcoset.jjxmm.win:8010/app?id={self.app_id}" + web_share_url = f"http://leonmmcoset.jjxmm.win:8010/app?id={self.app_id}" # 创建自定义对话框 dialog = QMessageBox(self)