Files
leonapp/pyqt5fluentdesign/leonapp_gui.py
Leonmmcoset 1586822845 feat: 增强应用详情和公告功能并添加下载支持
- 在应用详情窗口添加下载最新版本功能
- 为版本列表添加下载按钮和操作列
- 增强公告列表和详情的数据处理逻辑
- 优化错误处理和用户反馈
- 修改窗口标题为"LeonApp For PC"
2025-09-21 18:17:37 +08:00

1733 lines
65 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.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
LeonApp GUI - 基于PyQt5和Fluent Design的App Store API图形界面工具
"""
import sys
import json
import requests
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout, QHBoxLayout,
QTableWidgetItem
)
from PyQt5.QtCore import Qt, pyqtSignal, QThread
from qfluentwidgets import (
CardWidget, TitleLabel, SubtitleLabel, CaptionLabel, PushButton,
PrimaryPushButton, LineEdit, ComboBox, ProgressBar, TableWidget,
ScrollArea, InfoBar, InfoBarPosition, NavigationInterface, NavigationItemPosition,
FluentWindow, FluentIcon
)
from qfluentwidgets import FluentTranslator
class APIClient:
"""API客户端类处理与API的通信"""
def __init__(self, api_base_url="http://leonmmcoset.jjxmm.win:8010/api.php"):
self.api_base_url = api_base_url
def make_request(self, endpoint_type, params=None):
"""基础API请求函数"""
if params is None:
params = {}
# 添加API类型参数
params['t'] = endpoint_type
try:
response = requests.get(self.api_base_url, params=params, timeout=30)
response.raise_for_status() # 抛出HTTP错误
data = response.json()
if data.get('status') == 'error':
return {'error': data.get('message', '未知错误')}
return {'success': True, 'data': data.get('data')}
except requests.exceptions.RequestException as e:
return {'error': f"请求异常: {str(e)}"}
except json.JSONDecodeError:
return {'error': "无法解析响应"}
class WorkerThread(QThread):
"""工作线程用于在后台执行API请求"""
# 使用object类型以接受任何数据类型dict、list等
finished = pyqtSignal(object)
progress = pyqtSignal(int)
error = pyqtSignal(str)
def __init__(self, api_client, endpoint_type, params=None):
super().__init__()
self.api_client = api_client
self.endpoint_type = endpoint_type
self.params = params or {}
def run(self):
"""线程运行函数"""
try:
self.progress.emit(10)
result = self.api_client.make_request(self.endpoint_type, self.params)
self.progress.emit(100)
if 'error' in result:
self.error.emit(result['error'])
else:
# 确保数据是可序列化的对象
if isinstance(result['data'], (dict, list, str, int, float, bool, type(None))):
self.finished.emit(result['data'])
else:
self.error.emit(f"API返回的数据类型不支持: {type(result['data'])}")
except Exception as e:
self.error.emit(f"执行错误: {str(e)}")
class AppTab(QWidget):
"""应用列表标签页"""
def __init__(self, api_client, parent=None):
super().__init__(parent)
self.api_client = api_client
# 先初始化分页相关变量因为init_ui()内部会调用load_apps()
self.current_page = 1
self.items_per_page = 20
self.total_pages = 1
self.init_ui()
def init_ui(self):
"""初始化界面"""
# 创建主布局
layout = QVBoxLayout(self)
layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel("应用列表")
layout.addWidget(title)
# 创建搜索和过滤器区域
filter_layout = QHBoxLayout()
filter_layout.setContentsMargins(0, 10, 0, 10)
self.search_input = LineEdit()
self.search_input.setPlaceholderText("搜索应用...")
filter_layout.addWidget(self.search_input, 3)
filter_layout.addSpacing(10)
self.page_size_combo = ComboBox()
self.page_size_combo.addItems(["10", "20", "50", "100"])
self.page_size_combo.setCurrentText("20")
self.page_size_combo.currentTextChanged.connect(self.on_page_size_changed)
filter_layout.addWidget(CaptionLabel("每页显示:"))
filter_layout.addWidget(self.page_size_combo)
filter_layout.addSpacing(10)
search_button = PrimaryPushButton("搜索")
search_button.clicked.connect(self.search_apps)
filter_layout.addWidget(search_button)
layout.addLayout(filter_layout)
# 创建表格
self.table = TableWidget()
self.table.setColumnCount(5)
self.table.setHorizontalHeaderLabels(["ID", "应用名称", "版本", "评分", "下载量"])
self.table.horizontalHeader().setSectionResizeMode(1, 3)
self.table.cellDoubleClicked.connect(self.show_app_detail)
layout.addWidget(self.table)
# 创建分页控制
pagination_layout = QHBoxLayout()
pagination_layout.setContentsMargins(0, 10, 0, 0)
self.prev_button = PushButton("上一页")
self.prev_button.clicked.connect(self.prev_page)
pagination_layout.addWidget(self.prev_button)
self.page_label = CaptionLabel("第 1 页,共 1 页")
pagination_layout.addWidget(self.page_label, alignment=Qt.AlignCenter)
self.next_button = PushButton("下一页")
self.next_button.clicked.connect(self.next_page)
pagination_layout.addWidget(self.next_button)
layout.addLayout(pagination_layout)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
layout.addWidget(self.progress_bar)
# 加载初始数据
self.load_apps()
def load_apps(self):
"""加载应用列表"""
self.show_progress()
self.worker = WorkerThread(
self.api_client,
'getallapps',
{'page': self.current_page, 'limit': self.items_per_page}
)
self.worker.finished.connect(self.on_apps_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_apps_loaded(self, data):
"""应用列表加载完成处理"""
self.hide_progress()
if not data or 'apps' not in data or 'pagination' not in data:
self.show_error("数据格式错误")
return
# 清空表格
self.table.setRowCount(0)
# 填充表格
for app in data['apps']:
row_pos = self.table.rowCount()
self.table.insertRow(row_pos)
self.table.setItem(row_pos, 0, QTableWidgetItem(str(app.get('id', ''))))
self.table.setItem(row_pos, 1, QTableWidgetItem(app.get('name', '')))
self.table.setItem(row_pos, 2, QTableWidgetItem(app.get('version', '')))
self.table.setItem(row_pos, 3, QTableWidgetItem(str(app.get('avg_rating', '暂无'))))
self.table.setItem(row_pos, 4, QTableWidgetItem(str(app.get('total_downloads', 0))))
# 更新分页信息
self.total_pages = data['pagination']['totalPages']
self.page_label.setText(f"{self.current_page} 页,共 {self.total_pages}")
# 更新按钮状态
self.prev_button.setEnabled(self.current_page > 1)
self.next_button.setEnabled(self.current_page < self.total_pages)
def search_apps(self):
"""搜索应用"""
search_text = self.search_input.text().strip()
if search_text:
self.current_page = 1
self.show_progress()
self.worker = WorkerThread(
self.api_client,
'getallapps',
{'page': 1, 'limit': self.items_per_page, 'search': search_text}
)
self.worker.finished.connect(self.on_apps_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
else:
self.load_apps()
def prev_page(self):
"""上一页"""
if self.current_page > 1:
self.current_page -= 1
self.load_apps()
def next_page(self):
"""下一页"""
if self.current_page < self.total_pages:
self.current_page += 1
self.load_apps()
def on_page_size_changed(self, value):
"""每页显示数量变化"""
self.items_per_page = int(value)
self.current_page = 1
self.load_apps()
def show_app_detail(self, row, column):
"""显示应用详情"""
app_id = self.table.item(row, 0).text()
# 直接创建应用详情窗口使用文件顶部已导入的AppDetailWindow类
self.app_detail_window = AppDetailWindow(self.api_client, app_id, self)
self.app_detail_window.show()
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
# 使用Sweet Alert风格的弹窗
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class TagTab(QWidget):
"""标签管理标签页"""
def __init__(self, api_client, parent=None):
super().__init__(parent)
self.api_client = api_client
self.init_ui()
def init_ui(self):
"""初始化界面"""
# 创建主布局
layout = QVBoxLayout(self)
layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel("标签管理")
layout.addWidget(title)
# 创建标签列表
self.tag_list = TableWidget()
self.tag_list.setColumnCount(2)
self.tag_list.setHorizontalHeaderLabels(["ID", "标签名称"])
self.tag_list.cellDoubleClicked.connect(self.show_tag_apps)
layout.addWidget(self.tag_list)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
layout.addWidget(self.progress_bar)
# 加载标签数据
self.load_tags()
def load_tags(self):
"""加载标签数据"""
self.show_progress()
self.worker = WorkerThread(self.api_client, 'getalltags')
self.worker.finished.connect(self.on_tags_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_tags_loaded(self, data):
"""标签数据加载完成处理"""
self.hide_progress()
if not data:
self.show_error("数据加载失败")
return
# 清空表格
self.tag_list.setRowCount(0)
# 填充表格
for tag in data:
row_pos = self.tag_list.rowCount()
self.tag_list.insertRow(row_pos)
self.tag_list.setItem(row_pos, 0, QTableWidgetItem(str(tag.get('id', ''))))
self.tag_list.setItem(row_pos, 1, QTableWidgetItem(tag.get('name', '')))
def show_tag_apps(self, row, column):
"""显示标签下的应用"""
tag_id = self.tag_list.item(row, 0).text()
tag_name = self.tag_list.item(row, 1).text()
# 直接创建并显示标签应用窗口而不是调用parent方法
tag_apps_window = TagAppsWindow(self.api_client, tag_id, tag_name, self)
tag_apps_window.show()
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def download_version(self, version_id):
"""下载指定版本"""
import webbrowser
# 查找对应版本的文件路径
file_path = None
for i in range(self.versions_table.rowCount()):
# 这里假设我们在填充表格时存储了版本ID作为item的data
version_item = self.versions_table.item(i, 0)
if version_item and hasattr(version_item, 'version_id') and version_item.version_id == version_id:
# 假设我们在填充表格时存储了文件路径
if hasattr(version_item, 'file_path'):
file_path = version_item.file_path
break
if file_path:
# 构建直接的文件URL
download_url = f"http://leonmmcoset.jjxmm.win:8010/{file_path}"
try:
# 使用系统默认浏览器打开下载链接
webbrowser.open(download_url)
# 显示下载成功提示
InfoBar.success(
title="下载开始",
content=f"下载已开始,请稍候...",
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=3000,
parent=self
)
except Exception as e:
self.show_error(f"下载失败: {str(e)}")
else:
self.show_error("无法获取下载文件路径")
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class DeveloperTab(QWidget):
"""开发者管理标签页"""
def __init__(self, api_client, parent=None):
super().__init__(parent)
self.api_client = api_client
self.init_ui()
def init_ui(self):
"""初始化界面"""
# 创建主布局
layout = QVBoxLayout(self)
layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel("开发者管理")
layout.addWidget(title)
# 创建开发者ID输入框和按钮
input_layout = QHBoxLayout()
input_layout.setContentsMargins(0, 10, 0, 10)
self.developer_id_input = LineEdit()
self.developer_id_input.setPlaceholderText("输入开发者ID...")
input_layout.addWidget(self.developer_id_input, 3)
input_layout.addSpacing(10)
app_list_button = PrimaryPushButton("查看应用列表")
app_list_button.clicked.connect(self.show_developer_apps)
input_layout.addWidget(app_list_button)
input_layout.addSpacing(10)
info_button = PushButton("查看开发者信息")
info_button.clicked.connect(self.show_developer_info)
input_layout.addWidget(info_button)
layout.addLayout(input_layout)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
layout.addWidget(self.progress_bar)
def show_developer_apps(self):
"""查看开发者的应用列表"""
developer_id = self.developer_id_input.text().strip()
if developer_id:
# 直接创建并显示开发者应用窗口而不是调用parent方法
developer_apps_window = DeveloperAppsWindow(self.api_client, developer_id, self)
developer_apps_window.show()
else:
InfoBar.warning(
title="警告",
content="请输入开发者ID",
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=3000,
parent=self
)
def show_developer_info(self):
"""查看开发者信息"""
developer_id = self.developer_id_input.text().strip()
if developer_id:
# 直接创建并显示开发者信息窗口而不是调用parent方法
developer_info_window = DeveloperInfoWindow(self.api_client, developer_id, self)
developer_info_window.show()
else:
InfoBar.warning(
title="警告",
content="请输入开发者ID",
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=3000,
parent=self
)
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class AnnouncementTab(QWidget):
"""公告管理标签页"""
def __init__(self, api_client, parent=None):
super().__init__(parent)
self.api_client = api_client
# 先初始化分页相关变量因为init_ui()内部会调用load_announcements()
self.current_page = 1
self.items_per_page = 20
self.total_pages = 1
self.init_ui()
def init_ui(self):
"""初始化界面"""
# 创建主布局
layout = QVBoxLayout(self)
layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel("公告管理")
layout.addWidget(title)
# 创建分页控制
pagination_layout = QHBoxLayout()
pagination_layout.setContentsMargins(0, 10, 0, 10)
self.prev_button = PushButton("上一页")
self.prev_button.clicked.connect(self.prev_page)
pagination_layout.addWidget(self.prev_button)
self.page_label = CaptionLabel("第 1 页,共 1 页")
pagination_layout.addWidget(self.page_label, alignment=Qt.AlignCenter)
self.next_button = PushButton("下一页")
self.next_button.clicked.connect(self.next_page)
pagination_layout.addWidget(self.next_button)
layout.addLayout(pagination_layout)
# 创建公告列表
self.announcement_list = TableWidget()
self.announcement_list.setColumnCount(4)
self.announcement_list.setHorizontalHeaderLabels(["ID", "标题", "发布时间", "管理员ID"])
self.announcement_list.horizontalHeader().setSectionResizeMode(1, 3)
self.announcement_list.cellDoubleClicked.connect(self.show_announcement_detail)
layout.addWidget(self.announcement_list)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
layout.addWidget(self.progress_bar)
# 加载初始数据
self.load_announcements()
def load_announcements(self):
"""加载公告列表"""
self.show_progress()
self.worker = WorkerThread(
self.api_client,
'getacc',
{'page': self.current_page, 'limit': self.items_per_page}
)
self.worker.finished.connect(self.on_announcements_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_announcements_loaded(self, data):
"""公告列表加载完成处理"""
self.hide_progress()
# 增强的数据格式验证,提供更具体的错误信息
if data is None:
self.show_error("API返回数据为空")
return
# 处理数据 - 如果是列表类型,转换为预期的字典格式
processed_data = {}
if isinstance(data, list):
# API返回了列表我们将其转换为预期的字典结构
processed_data['announcements'] = data
# 构建简单的分页信息
total_items = len(data)
total_pages = (total_items + self.items_per_page - 1) // self.items_per_page
processed_data['pagination'] = {'totalPages': total_pages}
elif isinstance(data, dict):
# 保留原有的字典处理逻辑,但添加更灵活的验证
processed_data = data.copy()
# 验证必要字段是否存在,如果不存在则使用默认值
if 'announcements' not in processed_data:
processed_data['announcements'] = []
elif not isinstance(processed_data['announcements'], list):
# 如果announcements不是列表尝试转换或使用空列表
try:
processed_data['announcements'] = [processed_data['announcements']]
except:
processed_data['announcements'] = []
if 'pagination' not in processed_data:
# 如果没有分页信息,计算简单的分页
total_items = len(processed_data['announcements'])
total_pages = (total_items + self.items_per_page - 1) // self.items_per_page
processed_data['pagination'] = {'totalPages': total_pages}
elif not isinstance(processed_data['pagination'], dict):
# 如果pagination不是字典创建默认分页信息
processed_data['pagination'] = {'totalPages': 1}
# 确保分页信息中有totalPages
if 'totalPages' not in processed_data['pagination']:
processed_data['pagination']['totalPages'] = 1
else:
self.show_error(f"数据格式错误: 期望字典或列表类型,实际为{type(data).__name__}")
return
# 清空表格
self.announcement_list.setRowCount(0)
# 填充表格,添加更健壮的数据处理
for announcement in processed_data['announcements']:
# 确保announcement是字典类型
if not isinstance(announcement, dict):
continue
row_pos = self.announcement_list.rowCount()
self.announcement_list.insertRow(row_pos)
# 安全获取字段值避免KeyError
self.announcement_list.setItem(row_pos, 0, QTableWidgetItem(str(announcement.get('id', '未知ID'))))
self.announcement_list.setItem(row_pos, 1, QTableWidgetItem(announcement.get('title', '无标题')))
self.announcement_list.setItem(row_pos, 2, QTableWidgetItem(announcement.get('created_at', '未知时间')))
self.announcement_list.setItem(row_pos, 3, QTableWidgetItem(str(announcement.get('admin_id', '未知管理员'))))
# 更新分页信息,增加异常处理
try:
self.total_pages = int(processed_data['pagination']['totalPages'])
self.page_label.setText(f"{self.current_page} 页,共 {self.total_pages}")
except (ValueError, TypeError):
self.total_pages = 1
self.page_label.setText(f"{self.current_page} 页,共 {self.total_pages}")
# 更新按钮状态
self.prev_button.setEnabled(self.current_page > 1)
self.next_button.setEnabled(self.current_page < self.total_pages)
def prev_page(self):
"""上一页"""
if self.current_page > 1:
self.current_page -= 1
self.load_announcements()
def next_page(self):
"""下一页"""
if self.current_page < self.total_pages:
self.current_page += 1
self.load_announcements()
def show_announcement_detail(self, row, column):
"""显示公告详情"""
announcement_id = self.announcement_list.item(row, 0).text()
title = self.announcement_list.item(row, 1).text()
created_at = self.announcement_list.item(row, 2).text()
# 查找完整的公告数据
for i in range(self.announcement_list.rowCount()):
if self.announcement_list.item(i, 0).text() == announcement_id:
# 获取完整的公告内容
# 由于表格中没有直接存储content我们需要重新获取
self.show_progress()
self.detail_worker = WorkerThread(
self.api_client,
'getacc',
{'page': 1, 'limit': 100} # 获取足够多的公告以确保找到目标公告
)
self.detail_worker.finished.connect(lambda data, aid=announcement_id, t=title, ca=created_at:
self.on_announcement_detail_loaded(data, aid, t, ca))
self.detail_worker.progress.connect(self.update_progress)
self.detail_worker.error.connect(self.show_error)
self.detail_worker.start()
break
def on_announcement_detail_loaded(self, data, announcement_id, title, created_at):
"""公告详情加载完成处理"""
self.hide_progress()
# 增强的数据格式验证
if data is None:
self.show_error("获取公告详情失败: API返回数据为空")
return
# 处理数据 - 支持字典或列表类型
processed_data = {}
if isinstance(data, list):
# API返回了列表转换为预期的字典结构
processed_data['announcements'] = data
elif isinstance(data, dict):
# 保留字典处理逻辑,但添加更灵活的验证
processed_data = data.copy()
# 验证必要字段是否存在
if 'announcements' not in processed_data:
processed_data['announcements'] = []
elif not isinstance(processed_data['announcements'], list):
# 尝试转换announcements为列表类型
try:
processed_data['announcements'] = [processed_data['announcements']]
except:
processed_data['announcements'] = []
else:
self.show_error(f"获取公告详情失败: 数据格式错误,期望字典或列表类型,实际为{type(data).__name__}")
return
# 查找特定的公告,增加异常处理
content = "无内容"
try:
for announcement in processed_data['announcements']:
if not isinstance(announcement, dict):
continue
if str(announcement.get('id', '')) == announcement_id:
content = announcement.get('content', '无内容')
break
except Exception as e:
self.show_error(f"查找公告详情时发生错误: {str(e)}")
return
# 使用Sweet Alert风格的弹窗显示公告详情
InfoBar.info(
title="公告详情",
content=f"标题: {title}\n\n发布时间: {created_at}\n\n内容:\n{content}",
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=10000, # 增加显示时间以便阅读
parent=self
)
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class StatsTab(QWidget):
"""统计信息标签页"""
def __init__(self, api_client, parent=None):
super().__init__(parent)
self.api_client = api_client
self.init_ui()
def init_ui(self):
"""初始化界面"""
# 创建主布局
layout = QVBoxLayout(self)
layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel("应用商店统计信息")
layout.addWidget(title)
# 创建统计卡片容器
cards_layout = QVBoxLayout()
cards_layout.setSpacing(20)
# 创建统计卡片
self.app_count_card = CardWidget()
self.app_count_card.setMinimumHeight(100)
self.app_count_layout = QVBoxLayout(self.app_count_card)
self.app_count_title = SubtitleLabel("应用总数")
self.app_count_value = TitleLabel("--")
self.app_count_layout.addWidget(self.app_count_title)
self.app_count_layout.addWidget(self.app_count_value, alignment=Qt.AlignCenter)
cards_layout.addWidget(self.app_count_card)
self.developer_count_card = CardWidget()
self.developer_count_card.setMinimumHeight(100)
self.developer_count_layout = QVBoxLayout(self.developer_count_card)
self.developer_count_title = SubtitleLabel("开发者总数")
self.developer_count_value = TitleLabel("--")
self.developer_count_layout.addWidget(self.developer_count_title)
self.developer_count_layout.addWidget(self.developer_count_value, alignment=Qt.AlignCenter)
cards_layout.addWidget(self.developer_count_card)
self.tag_count_card = CardWidget()
self.tag_count_card.setMinimumHeight(100)
self.tag_count_layout = QVBoxLayout(self.tag_count_card)
self.tag_count_title = SubtitleLabel("标签总数")
self.tag_count_value = TitleLabel("--")
self.tag_count_layout.addWidget(self.tag_count_title)
self.tag_count_layout.addWidget(self.tag_count_value, alignment=Qt.AlignCenter)
cards_layout.addWidget(self.tag_count_card)
self.announcement_count_card = CardWidget()
self.announcement_count_card.setMinimumHeight(100)
self.announcement_count_layout = QVBoxLayout(self.announcement_count_card)
self.announcement_count_title = SubtitleLabel("公告总数")
self.announcement_count_value = TitleLabel("--")
self.announcement_count_layout.addWidget(self.announcement_count_title)
self.announcement_count_layout.addWidget(self.announcement_count_value, alignment=Qt.AlignCenter)
cards_layout.addWidget(self.announcement_count_card)
self.download_count_card = CardWidget()
self.download_count_card.setMinimumHeight(100)
self.download_count_layout = QVBoxLayout(self.download_count_card)
self.download_count_title = SubtitleLabel("总下载量")
self.download_count_value = TitleLabel("--")
self.download_count_layout.addWidget(self.download_count_title)
self.download_count_layout.addWidget(self.download_count_value, alignment=Qt.AlignCenter)
cards_layout.addWidget(self.download_count_card)
layout.addLayout(cards_layout)
# 创建刷新按钮
refresh_button = PrimaryPushButton("刷新统计数据")
refresh_button.clicked.connect(self.load_stats)
layout.addWidget(refresh_button, alignment=Qt.AlignCenter)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
layout.addWidget(self.progress_bar)
# 加载初始数据
self.load_stats()
def load_stats(self):
"""加载统计数据"""
self.show_progress()
self.worker = WorkerThread(self.api_client, 'getcount')
self.worker.finished.connect(self.on_stats_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_stats_loaded(self, data):
"""统计数据加载完成处理"""
self.hide_progress()
if not data:
self.show_error("数据加载失败")
return
# 更新统计数据
self.app_count_value.setText(str(data.get('total_apps', '--')))
self.developer_count_value.setText(str(data.get('total_developers', '--')))
self.tag_count_value.setText(str(data.get('total_tags', '--')))
self.announcement_count_value.setText(str(data.get('total_announcements', '--')))
self.download_count_value.setText(str(data.get('total_downloads', '--')))
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class AppDetailWindow(QMainWindow):
"""应用详情窗口"""
def __init__(self, api_client, app_id, parent=None):
super().__init__(parent)
self.api_client = api_client
self.app_id = app_id
self.setWindowTitle("应用详情")
self.resize(800, 600)
self.init_ui()
self.load_app_detail()
def init_ui(self):
"""初始化界面"""
# 创建中心部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 创建主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
self.app_title = TitleLabel("加载中...")
main_layout.addWidget(self.app_title)
# 创建应用信息区域
self.info_card = CardWidget()
self.info_layout = QVBoxLayout(self.info_card)
main_layout.addWidget(self.info_card)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
main_layout.addWidget(self.progress_bar)
def load_app_detail(self):
"""加载应用详情"""
self.show_progress()
self.worker = WorkerThread(self.api_client, 'getappinfo', {'id': self.app_id})
self.worker.finished.connect(self.on_app_detail_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_app_detail_loaded(self, data):
"""应用详情加载完成处理"""
self.hide_progress()
if not data:
self.show_error("应用详情加载失败")
return
# 更新标题
self.app_title.setText(data.get('name', '未知应用'))
# 清空之前的信息
while self.info_layout.count():
item = self.info_layout.takeAt(0)
widget = item.widget()
if widget:
widget.deleteLater()
# 添加应用信息
info_text = f"""
版本: {data.get('version', '未知')}
年龄分级: {data.get('age_rating', '未知')}
评分: {data.get('avg_rating', '暂无')}
下载量: {data.get('total_downloads', 0)}
"""
# 添加描述
description_label = SubtitleLabel("描述")
self.info_layout.addWidget(description_label)
description_text = CaptionLabel(data.get('description', '暂无描述'))
description_text.setWordWrap(True)
self.info_layout.addWidget(description_text)
# 添加标签信息
if 'tags' in data and data['tags']:
tags_label = SubtitleLabel("标签")
self.info_layout.addWidget(tags_label)
tags_text = ', '.join([tag['name'] for tag in data['tags']])
self.info_layout.addWidget(CaptionLabel(tags_text))
# 添加版本信息
if 'versions' in data and data['versions']:
versions_label = SubtitleLabel("版本历史")
self.info_layout.addWidget(versions_label)
versions_text = "\n".join([f"- 版本 {v['version']} ({v['download_count']} 下载)" for v in data['versions'][:3]])
self.info_layout.addWidget(CaptionLabel(versions_text))
# 添加"查看全部版本"按钮
if len(data['versions']) > 3:
self.view_all_versions_button = PushButton("查看全部版本")
self.view_all_versions_button.clicked.connect(lambda: self.view_all_versions())
self.info_layout.addWidget(self.view_all_versions_button)
# 添加下载最新版本按钮
if data['versions']:
# 保存最新版本信息用于下载
self.latest_version = data['versions'][0]
download_layout = QHBoxLayout()
download_layout.addStretch(1)
self.download_button = PushButton("下载最新版本")
self.download_button.setIcon(FluentIcon.DOWNLOAD)
self.download_button.clicked.connect(self.download_latest_version)
download_layout.addWidget(self.download_button)
self.info_layout.addLayout(download_layout)
def view_all_versions(self):
"""查看全部版本"""
versions_window = AppVersionsWindow(self.api_client, self.app_id, self.app_title.text(), self)
versions_window.show()
def download_latest_version(self):
"""下载最新版本"""
if hasattr(self, 'latest_version'):
version_id = self.latest_version.get('id', '')
if version_id:
self.perform_download(version_id)
else:
self.show_error("无法获取版本ID")
else:
self.show_error("没有可下载的版本")
def perform_download(self, version_id):
"""执行下载操作"""
import webbrowser
# 直接使用latest_version中的file_path进行下载
if hasattr(self, 'latest_version') and 'file_path' in self.latest_version:
file_path = self.latest_version['file_path']
# 构建直接的文件URL
download_url = f"http://leonmmcoset.jjxmm.win:8010/{file_path}"
try:
# 使用系统默认浏览器打开下载链接
webbrowser.open(download_url)
# 显示下载成功提示
InfoBar.success(
title="下载开始",
content=f"下载已开始,请稍候...",
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=3000,
parent=self
)
except Exception as e:
self.show_error(f"下载失败: {str(e)}")
else:
self.show_error("无法获取下载文件路径")
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class TagAppsWindow(QMainWindow):
"""标签下的应用列表窗口"""
def __init__(self, api_client, tag_id, tag_name, parent=None):
super().__init__(parent)
self.api_client = api_client
self.tag_id = tag_id
self.tag_name = tag_name
self.setWindowTitle(f"标签 '{tag_name}' 下的应用")
self.resize(800, 600)
self.current_page = 1
self.items_per_page = 20
self.total_pages = 1
self.init_ui()
self.load_tag_apps()
def init_ui(self):
"""初始化界面"""
# 创建中心部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 创建主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel(f"标签 '{self.tag_name}' 下的应用")
main_layout.addWidget(title)
# 创建应用列表
self.app_table = TableWidget()
self.app_table.setColumnCount(5)
self.app_table.setHorizontalHeaderLabels(["ID", "应用名称", "版本", "评分", "下载量"])
self.app_table.horizontalHeader().setSectionResizeMode(1, 3)
self.app_table.cellDoubleClicked.connect(self.show_app_detail)
main_layout.addWidget(self.app_table)
# 创建分页控件
pagination_layout = QHBoxLayout()
self.prev_button = PushButton("上一页")
self.prev_button.clicked.connect(self.prev_page)
self.page_label = CaptionLabel("第 1 页,共 1 页")
self.next_button = PushButton("下一页")
self.next_button.clicked.connect(self.next_page)
pagination_layout.addWidget(self.prev_button)
pagination_layout.addStretch()
pagination_layout.addWidget(self.page_label)
pagination_layout.addStretch()
pagination_layout.addWidget(self.next_button)
main_layout.addLayout(pagination_layout)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
main_layout.addWidget(self.progress_bar)
def load_tag_apps(self):
"""加载标签下的应用"""
self.show_progress()
params = {
'id': self.tag_id,
'page': self.current_page,
'limit': self.items_per_page
}
self.worker = WorkerThread(self.api_client, 'gettagapp', params)
self.worker.finished.connect(self.on_tag_apps_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_tag_apps_loaded(self, data):
"""标签应用加载完成处理"""
self.hide_progress()
if not data or 'apps' not in data:
self.show_error("应用列表加载失败")
return
# 清空表格
self.app_table.setRowCount(0)
# 添加数据
for app in data['apps']:
row_position = self.app_table.rowCount()
self.app_table.insertRow(row_position)
# 添加应用数据到表格
self.app_table.setItem(row_position, 0, QTableWidgetItem(str(app.get('id', '--'))))
self.app_table.setItem(row_position, 1, QTableWidgetItem(app.get('name', '未知应用')))
self.app_table.setItem(row_position, 2, QTableWidgetItem(app.get('version', '未知')))
self.app_table.setItem(row_position, 3, QTableWidgetItem(str(app.get('avg_rating', '暂无'))))
self.app_table.setItem(row_position, 4, QTableWidgetItem(str(app.get('total_downloads', 0))))
# 更新分页信息
self.total_pages = data.get('total_pages', 1)
self.page_label.setText(f"{self.current_page} 页,共 {self.total_pages}")
# 更新按钮状态
self.prev_button.setEnabled(self.current_page > 1)
self.next_button.setEnabled(self.current_page < self.total_pages)
def prev_page(self):
"""上一页"""
if self.current_page > 1:
self.current_page -= 1
self.load_tag_apps()
def next_page(self):
"""下一页"""
if self.current_page < self.total_pages:
self.current_page += 1
self.load_tag_apps()
def show_app_detail(self, row, column):
"""显示应用详情"""
# 获取应用ID
app_id_item = self.app_table.item(row, 0)
if app_id_item:
app_id = int(app_id_item.text())
# 打开应用详情窗口
self.app_detail_window = AppDetailWindow(self.api_client, app_id, self)
self.app_detail_window.show()
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class DeveloperAppsWindow(QMainWindow):
"""开发者的应用列表窗口"""
def __init__(self, api_client, developer_id, parent=None):
super().__init__(parent)
self.api_client = api_client
self.developer_id = developer_id
self.setWindowTitle(f"开发者ID {developer_id} 的应用")
self.resize(800, 600)
self.current_page = 1
self.items_per_page = 20
self.total_pages = 1
self.init_ui()
self.load_developer_apps()
def init_ui(self):
"""初始化界面"""
# 创建中心部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 创建主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel(f"开发者ID {self.developer_id} 的应用")
main_layout.addWidget(title)
# 创建应用列表
self.app_table = TableWidget()
self.app_table.setColumnCount(5)
self.app_table.setHorizontalHeaderLabels(["ID", "应用名称", "版本", "评分", "下载量"])
self.app_table.horizontalHeader().setSectionResizeMode(1, 3)
self.app_table.cellDoubleClicked.connect(self.show_app_detail)
main_layout.addWidget(self.app_table)
# 创建分页控件
pagination_layout = QHBoxLayout()
pagination_layout.setContentsMargins(0, 10, 0, 0)
self.prev_button = PushButton("上一页")
self.prev_button.clicked.connect(self.prev_page)
pagination_layout.addWidget(self.prev_button)
self.page_label = CaptionLabel("第 1 页,共 1 页")
pagination_layout.addWidget(self.page_label, alignment=Qt.AlignCenter)
self.next_button = PushButton("下一页")
self.next_button.clicked.connect(self.next_page)
pagination_layout.addWidget(self.next_button)
main_layout.addLayout(pagination_layout)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
main_layout.addWidget(self.progress_bar)
def load_developer_apps(self):
"""加载开发者的应用"""
self.show_progress()
self.worker = WorkerThread(
self.api_client,
'getdeveloperapp',
{'id': self.developer_id, 'page': self.current_page, 'limit': self.items_per_page}
)
self.worker.finished.connect(self.on_developer_apps_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_developer_apps_loaded(self, data):
"""开发者应用加载完成处理"""
self.hide_progress()
if not data or 'apps' not in data or 'pagination' not in data:
self.show_error("数据格式错误")
return
# 清空表格
self.app_table.setRowCount(0)
# 填充表格
for app in data['apps']:
row_pos = self.app_table.rowCount()
self.app_table.insertRow(row_pos)
self.app_table.setItem(row_pos, 0, QTableWidgetItem(str(app.get('id', ''))))
self.app_table.setItem(row_pos, 1, QTableWidgetItem(app.get('name', '')))
self.app_table.setItem(row_pos, 2, QTableWidgetItem(app.get('version', '')))
self.app_table.setItem(row_pos, 3, QTableWidgetItem(str(app.get('avg_rating', '暂无'))))
self.app_table.setItem(row_pos, 4, QTableWidgetItem(str(app.get('total_downloads', 0))))
# 更新分页信息
self.total_pages = data['pagination']['totalPages']
self.page_label.setText(f"{self.current_page} 页,共 {self.total_pages}")
# 更新按钮状态
self.prev_button.setEnabled(self.current_page > 1)
self.next_button.setEnabled(self.current_page < self.total_pages)
def prev_page(self):
"""上一页"""
if self.current_page > 1:
self.current_page -= 1
self.load_developer_apps()
def next_page(self):
"""下一页"""
if self.current_page < self.total_pages:
self.current_page += 1
self.load_developer_apps()
def show_app_detail(self, row, column):
"""显示应用详情"""
app_id = self.app_table.item(row, 0).text()
detail_window = AppDetailWindow(self.api_client, app_id, self)
detail_window.show()
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class DeveloperInfoWindow(QMainWindow):
"""开发者信息窗口"""
def __init__(self, api_client, developer_id, parent=None):
super().__init__(parent)
self.api_client = api_client
self.developer_id = developer_id
self.setWindowTitle(f"开发者信息")
self.resize(600, 400)
self.init_ui()
self.load_developer_info()
def init_ui(self):
"""初始化界面"""
# 创建中心部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 创建主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel("开发者信息")
main_layout.addWidget(title)
# 创建信息卡片
self.info_card = CardWidget()
self.info_layout = QVBoxLayout(self.info_card)
main_layout.addWidget(self.info_card)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
main_layout.addWidget(self.progress_bar)
def load_developer_info(self):
"""加载开发者信息"""
self.show_progress()
self.worker = WorkerThread(self.api_client, 'getdeveloperinfo', {'id': self.developer_id})
self.worker.finished.connect(self.on_developer_info_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_developer_info_loaded(self, data):
"""开发者信息加载完成处理"""
self.hide_progress()
if not data:
self.show_error("开发者信息加载失败")
return
# 清空之前的信息
while self.info_layout.count():
item = self.info_layout.takeAt(0)
widget = item.widget()
if widget:
widget.deleteLater()
# 添加开发者信息
info_items = [
("ID", data.get('id', '--')),
("用户名", data.get('username', '--')),
("邮箱", data.get('email', '--')),
("注册时间", data.get('created_at', '--')),
("是否验证", "" if data.get('is_verified', False) else ""),
("应用数量", data.get('app_count', 0))
]
for label_text, value_text in info_items:
label = CaptionLabel(f"{label_text}: {value_text}")
self.info_layout.addWidget(label)
# 添加验证时间(如果已验证)
if data.get('is_verified', False) and data.get('verified_at'):
verified_at_label = CaptionLabel(f"验证时间: {data.get('verified_at')}")
self.info_layout.addWidget(verified_at_label)
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class AppVersionsWindow(QMainWindow):
"""应用版本列表窗口"""
def __init__(self, api_client, app_id, app_name, parent=None):
super().__init__(parent)
self.api_client = api_client
self.app_id = app_id
self.app_name = app_name
self.setWindowTitle(f"{app_name} - 版本历史")
self.resize(800, 600)
self.current_page = 1
self.items_per_page = 20
self.total_pages = 1
self.init_ui()
self.load_versions()
def init_ui(self):
"""初始化界面"""
# 创建中心部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 创建主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setContentsMargins(20, 20, 20, 20)
# 创建标题
title = TitleLabel(f"{self.app_name} - 版本历史")
main_layout.addWidget(title)
# 创建版本列表
self.versions_table = TableWidget()
self.versions_table.setColumnCount(6)
self.versions_table.setHorizontalHeaderLabels(["版本号", "发布日期", "操作系统", "文件大小", "下载量", "操作"])
main_layout.addWidget(self.versions_table)
# 创建分页控件
pagination_layout = QHBoxLayout()
self.prev_button = PushButton("上一页")
self.prev_button.clicked.connect(self.prev_page)
self.page_label = CaptionLabel("第 1 页,共 1 页")
self.next_button = PushButton("下一页")
self.next_button.clicked.connect(self.next_page)
pagination_layout.addWidget(self.prev_button)
pagination_layout.addStretch()
pagination_layout.addWidget(self.page_label)
pagination_layout.addStretch()
pagination_layout.addWidget(self.next_button)
main_layout.addLayout(pagination_layout)
# 创建进度条
self.progress_bar = ProgressBar()
self.progress_bar.setVisible(False)
main_layout.addWidget(self.progress_bar)
def load_versions(self):
"""加载版本列表"""
self.show_progress()
self.worker = WorkerThread(self.api_client, 'getappversions',
{'id': self.app_id,
'page': self.current_page,
'limit': self.items_per_page})
self.worker.finished.connect(self.on_versions_loaded)
self.worker.progress.connect(self.update_progress)
self.worker.error.connect(self.show_error)
self.worker.start()
def on_versions_loaded(self, data):
"""版本列表加载完成处理"""
self.hide_progress()
if not data:
self.show_error("版本列表加载失败")
return
# 清空表格
self.versions_table.setRowCount(0)
# 更新分页信息
pagination = data.get('pagination', {})
self.total_pages = pagination.get('totalPages', 1)
self.page_label.setText(f"{self.current_page} 页,共 {self.total_pages}")
# 更新按钮状态
self.prev_button.setEnabled(self.current_page > 1)
self.next_button.setEnabled(self.current_page < self.total_pages)
# 填充表格
versions = data.get('versions', [])
for version in versions:
row_position = self.versions_table.rowCount()
self.versions_table.insertRow(row_position)
# 添加版本数据并存储版本ID和文件路径
version_item = QTableWidgetItem(version.get('version', '未知'))
# 存储版本ID和文件路径信息
version_item.version_id = version.get('id', '')
version_item.file_path = version.get('file_path', '')
self.versions_table.setItem(row_position, 0, version_item)
self.versions_table.setItem(row_position, 1, QTableWidgetItem(version.get('created_at', '未知')))
self.versions_table.setItem(row_position, 2, QTableWidgetItem(version.get('platform', '未知')))
self.versions_table.setItem(row_position, 3, QTableWidgetItem(version.get('file_size', '未知')))
self.versions_table.setItem(row_position, 4, QTableWidgetItem(str(version.get('download_count', 0))))
# 添加下载按钮
download_button = PushButton("下载")
download_button.setIcon(FluentIcon.DOWNLOAD)
# 将版本ID绑定到按钮上
version_id = version.get('id', '')
download_button.clicked.connect(lambda checked, vid=version_id: self.download_version(vid))
# 创建按钮容器并添加按钮
button_container = QWidget()
button_layout = QHBoxLayout(button_container)
button_layout.setContentsMargins(5, 5, 5, 5)
button_layout.addWidget(download_button)
button_container.setLayout(button_layout)
self.versions_table.setCellWidget(row_position, 5, button_container)
# 自动调整列宽
self.versions_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
def prev_page(self):
"""上一页"""
if self.current_page > 1:
self.current_page -= 1
self.load_versions()
def next_page(self):
"""下一页"""
if self.current_page < self.total_pages:
self.current_page += 1
self.load_versions()
def show_progress(self):
"""显示进度条"""
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
def update_progress(self, value):
"""更新进度条"""
self.progress_bar.setValue(value)
def hide_progress(self):
"""隐藏进度条"""
self.progress_bar.setVisible(False)
def show_error(self, message):
"""显示错误消息"""
self.hide_progress()
InfoBar.error(
title="错误",
content=message,
orient=Qt.Horizontal,
isClosable=True,
position=InfoBarPosition.BOTTOM_RIGHT,
duration=5000,
parent=self
)
class LeonAppGUI(FluentWindow):
"""主应用窗口"""
def __init__(self):
super().__init__()
# 初始化API客户端
self.api_client = APIClient()
# 设置窗口标题和大小
self.setWindowTitle("LeonApp For PC")
self.resize(1000, 700)
# 初始化UI
self.init_ui()
def init_ui(self):
"""初始化界面"""
# 创建各个标签页
self.app_tab = AppTab(self.api_client, self)
self.app_tab.setObjectName("app")
self.tag_tab = TagTab(self.api_client, self)
self.tag_tab.setObjectName("tag")
self.developer_tab = DeveloperTab(self.api_client, self)
self.developer_tab.setObjectName("developer")
self.announcement_tab = AnnouncementTab(self.api_client, self)
self.announcement_tab.setObjectName("announcement")
self.stats_tab = StatsTab(self.api_client, self)
self.stats_tab.setObjectName("stats")
# 添加子界面到主窗口
self.addSubInterface(self.app_tab, FluentIcon.APPLICATION, "应用管理")
self.addSubInterface(self.tag_tab, FluentIcon.TAG, "标签管理")
self.addSubInterface(self.developer_tab, FluentIcon.DEVELOPER_TOOLS, "开发者管理")
self.addSubInterface(self.announcement_tab, FluentIcon.MEGAPHONE, "公告管理")
self.addSubInterface(self.stats_tab, FluentIcon.PIE_SINGLE, "统计信息")
# 设置默认选中的标签页
self.navigationInterface.setCurrentItem("app")
# 构建状态栏
# self.init_status_bar()
def show_app_detail(self, app_id):
"""显示应用详情"""
detail_window = AppDetailWindow(self.api_client, app_id, self)
detail_window.show()
def show_tag_apps(self, tag_id, tag_name):
"""显示标签下的应用"""
tag_apps_window = TagAppsWindow(self.api_client, tag_id, tag_name, self)
tag_apps_window.show()
def show_developer_apps(self, developer_id):
"""显示开发者的应用"""
developer_apps_window = DeveloperAppsWindow(self.api_client, developer_id, self)
developer_apps_window.show()
def show_developer_info(self, developer_id):
"""显示开发者信息"""
developer_info_window = DeveloperInfoWindow(self.api_client, developer_id, self)
developer_info_window.show()
def show_app_versions(self, app_id, app_name):
"""显示应用的版本列表"""
versions_window = AppVersionsWindow(self.api_client, app_id, app_name, self)
versions_window.show()
def main():
"""主函数"""
# 创建应用实例
app = QApplication(sys.argv)
# 添加中文支持
translator = FluentTranslator()
app.installTranslator(translator)
# 创建并显示主窗口
window = LeonAppGUI()
window.show()
# 运行应用
sys.exit(app.exec_())
if __name__ == "__main__":
main()