feat: 增强应用详情和公告功能并添加下载支持
- 在应用详情窗口添加下载最新版本功能 - 为版本列表添加下载按钮和操作列 - 增强公告列表和详情的数据处理逻辑 - 优化错误处理和用户反馈 - 修改窗口标题为"LeonApp For PC"
This commit is contained in:
BIN
APP Store.zip
BIN
APP Store.zip
Binary file not shown.
Binary file not shown.
@@ -240,10 +240,9 @@ class AppTab(QWidget):
|
||||
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()
|
||||
# 直接创建应用详情窗口,使用文件顶部已导入的AppDetailWindow类
|
||||
self.app_detail_window = AppDetailWindow(self.api_client, app_id, self)
|
||||
self.app_detail_window.show()
|
||||
|
||||
def show_progress(self):
|
||||
"""显示进度条"""
|
||||
@@ -353,6 +352,44 @@ class TagTab(QWidget):
|
||||
"""隐藏进度条"""
|
||||
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()
|
||||
@@ -543,27 +580,76 @@ class AnnouncementTab(QWidget):
|
||||
"""公告列表加载完成处理"""
|
||||
self.hide_progress()
|
||||
|
||||
if not data or 'announcements' not in data or 'pagination' not in data:
|
||||
self.show_error("数据格式错误")
|
||||
# 增强的数据格式验证,提供更具体的错误信息
|
||||
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 data['announcements']:
|
||||
# 填充表格,添加更健壮的数据处理
|
||||
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)
|
||||
|
||||
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} 页")
|
||||
# 安全获取字段值,避免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)
|
||||
@@ -584,20 +670,81 @@ class AnnouncementTab(QWidget):
|
||||
"""显示公告详情"""
|
||||
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:
|
||||
# 这里可以添加获取公告详情的逻辑
|
||||
InfoBar.info(
|
||||
title="公告详情",
|
||||
content=f"标题: {title}\nID: {announcement_id}",
|
||||
orient=Qt.Horizontal,
|
||||
isClosable=True,
|
||||
position=InfoBarPosition.BOTTOM_RIGHT,
|
||||
duration=5000,
|
||||
parent=self
|
||||
# 获取完整的公告内容
|
||||
# 由于表格中没有直接存储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):
|
||||
"""显示进度条"""
|
||||
@@ -856,17 +1003,65 @@ class AppDetailWindow(QMainWindow):
|
||||
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()
|
||||
|
||||
# 添加图片数量信息
|
||||
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 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):
|
||||
"""显示进度条"""
|
||||
@@ -1323,8 +1518,8 @@ class AppVersionsWindow(QMainWindow):
|
||||
|
||||
# 创建版本列表
|
||||
self.versions_table = TableWidget()
|
||||
self.versions_table.setColumnCount(5)
|
||||
self.versions_table.setHorizontalHeaderLabels(["版本号", "发布日期", "操作系统", "文件大小", "下载量"])
|
||||
self.versions_table.setColumnCount(6)
|
||||
self.versions_table.setHorizontalHeaderLabels(["版本号", "发布日期", "操作系统", "文件大小", "下载量", "操作"])
|
||||
main_layout.addWidget(self.versions_table)
|
||||
|
||||
# 创建分页控件
|
||||
@@ -1385,12 +1580,33 @@ class AppVersionsWindow(QMainWindow):
|
||||
row_position = self.versions_table.rowCount()
|
||||
self.versions_table.insertRow(row_position)
|
||||
|
||||
# 添加版本数据
|
||||
self.versions_table.setItem(row_position, 0, QTableWidgetItem(version.get('version', '未知')))
|
||||
# 添加版本数据并存储版本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)
|
||||
@@ -1440,7 +1656,7 @@ class LeonAppGUI(FluentWindow):
|
||||
# 初始化API客户端
|
||||
self.api_client = APIClient()
|
||||
# 设置窗口标题和大小
|
||||
self.setWindowTitle("LeonApp GUI")
|
||||
self.setWindowTitle("LeonApp For PC")
|
||||
self.resize(1000, 700)
|
||||
# 初始化UI
|
||||
self.init_ui()
|
||||
|
||||
Reference in New Issue
Block a user