#!/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() # 直接创建应用详情窗口,而不是通过父对象调用方法 from app_detail_window import AppDetailWindow 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() # 使用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 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 not data or 'announcements' not in data or 'pagination' not in data: self.show_error("数据格式错误") return # 清空表格 self.announcement_list.setRowCount(0) # 填充表格 for announcement in data['announcements']: row_pos = self.announcement_list.rowCount() self.announcement_list.insertRow(row_pos) self.announcement_list.setItem(row_pos, 0, QTableWidgetItem(str(announcement.get('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', '')))) # 更新分页信息 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_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() # 查找完整的公告数据 for i in range(self.announcement_list.rowCount()): if self.announcement_list.item(i, 0).text() == announcement_id: # 这里可以添加获取公告详情的逻辑 InfoBar.info( title="公告详情", content=f"标题: {title}\nID: {announcement_id}", orient=Qt.Horizontal, isClosable=True, position=InfoBarPosition.BOTTOM_RIGHT, duration=5000, parent=self ) break 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) def view_all_versions(self): """查看全部版本""" versions_window = AppVersionsWindow(self.api_client, self.app_id, self.app_title.text(), self) versions_window.show() # 添加图片数量信息 if 'images' in data and data['images']: images_label = SubtitleLabel("图片") self.info_layout.addWidget(images_label) self.info_layout.addWidget(CaptionLabel(f"共 {len(data['images'])} 张图片")) 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(5) 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) # 添加版本数据 self.versions_table.setItem(row_position, 0, QTableWidgetItem(version.get('version', '未知'))) 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)))) # 自动调整列宽 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 GUI") 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()