320 lines
12 KiB
Python
320 lines
12 KiB
Python
from loguru import logger
|
||
from PyQt6.QtCore import Qt, QThread, pyqtSignal
|
||
from PyQt6.QtWidgets import QVBoxLayout, QWidget, QTableWidget, QTableWidgetItem, QHeaderView, QAbstractItemView, QMenu, QLabel, QFrame, QHBoxLayout
|
||
from PyQt6.QtGui import QAction
|
||
from qfluentwidgets import (CardWidget, ToolButton,
|
||
LineEdit, PrimaryPushButton, InfoBar, InfoBarPosition,
|
||
Dialog)
|
||
|
||
from app.core.api import miaoStarsBasicApi as basicApi
|
||
from app.core import lang
|
||
|
||
|
||
class ShareThread(QThread):
|
||
"""获取分享列表的线程"""
|
||
successSignal = pyqtSignal(dict)
|
||
errorSignal = pyqtSignal(str)
|
||
|
||
def __init__(self, page=1, pageSize=10, nextToken=None):
|
||
super().__init__()
|
||
self.page = page
|
||
self.pageSize = pageSize
|
||
self.nextToken = nextToken
|
||
|
||
def run(self):
|
||
try:
|
||
api = basicApi
|
||
# 注意:getMyShares方法当前只支持page和pageSize参数
|
||
# 未来如果API支持next_token参数,这里需要更新调用方式
|
||
result = api.getMyShares(self.page, self.pageSize)
|
||
if result['code'] == 0:
|
||
self.successSignal.emit(result)
|
||
else:
|
||
self.errorSignal.emit(result['msg'])
|
||
except Exception as e:
|
||
logger.error(f"获取分享列表失败: {e}")
|
||
self.errorSignal.emit(str(e))
|
||
|
||
|
||
class DeleteShareThread(QThread):
|
||
"""删除分享的线程"""
|
||
successSignal = pyqtSignal(str)
|
||
errorSignal = pyqtSignal(str)
|
||
|
||
def __init__(self, shareId):
|
||
super().__init__()
|
||
self.shareId = shareId
|
||
|
||
def run(self):
|
||
try:
|
||
api = basicApi
|
||
result = api.deleteShare(self.shareId)
|
||
if result['code'] == 0:
|
||
self.successSignal.emit(self.shareId)
|
||
else:
|
||
self.errorSignal.emit(result['msg'])
|
||
except Exception as e:
|
||
logger.error(f"删除分享失败: {e}")
|
||
self.errorSignal.emit(str(e))
|
||
|
||
|
||
class ShareWidget(QWidget):
|
||
"""分享页面组件"""
|
||
|
||
def __init__(self, parent=None):
|
||
super().__init__(parent)
|
||
self.page = 1
|
||
self.pageSize = 10
|
||
self.total = 0
|
||
self.nextToken = None
|
||
|
||
self.setupUi()
|
||
self.connectSignals()
|
||
self.loadShares()
|
||
|
||
def setupUi(self):
|
||
"""初始化UI"""
|
||
self.mainLayout = QVBoxLayout(self)
|
||
self.mainLayout.setSpacing(20)
|
||
|
||
# 标题
|
||
titleCard = CardWidget(self)
|
||
titleLayout = QVBoxLayout(titleCard)
|
||
self.titleLabel = QLabel(lang("我的分享"), parent=titleCard)
|
||
font = self.titleLabel.font()
|
||
font.setBold(True)
|
||
self.titleLabel.setFont(font)
|
||
self.titleLabel.setStyleSheet("font-size: 20px;")
|
||
titleLayout.addWidget(self.titleLabel, alignment=Qt.AlignmentFlag.AlignLeft)
|
||
self.mainLayout.addWidget(titleCard)
|
||
|
||
# 表格
|
||
self.tableWidget = QTableWidget(self)
|
||
self.tableWidget.setColumnCount(5)
|
||
self.tableWidget.setHorizontalHeaderLabels([
|
||
lang("分享名称"),
|
||
lang("分享链接"),
|
||
lang("创建时间"),
|
||
lang("访问次数"),
|
||
lang("操作")
|
||
])
|
||
|
||
# 设置表格属性
|
||
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
|
||
self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
|
||
self.tableWidget.horizontalHeader().setSectionResizeMode(4, QHeaderView.ResizeMode.Fixed)
|
||
self.tableWidget.setColumnWidth(4, 100)
|
||
self.tableWidget.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
|
||
self.tableWidget.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||
self.mainLayout.addWidget(self.tableWidget)
|
||
|
||
# 空状态
|
||
self.emptyWidget = QFrame(self)
|
||
self.emptyWidget.setFixedSize(400, 250)
|
||
self.emptyWidget.setStyleSheet("background-color: transparent;")
|
||
emptyLayout = QVBoxLayout(self.emptyWidget)
|
||
|
||
# 图标标签(使用占位文本代替图标)
|
||
self.iconLabel = QLabel("☁️", self.emptyWidget)
|
||
self.iconLabel.setStyleSheet("font-size: 48px;")
|
||
self.iconLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
|
||
# 标题
|
||
self.emptyTitleLabel = QLabel(lang("暂无分享"), self.emptyWidget)
|
||
self.emptyTitleLabel.setStyleSheet("font-size: 18px; font-weight: bold;")
|
||
self.emptyTitleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
|
||
# 描述
|
||
self.emptyDescLabel = QLabel(lang("你还没有任何分享,分享文件可以让他人便捷地获取你的资料"), self.emptyWidget)
|
||
self.emptyDescLabel.setStyleSheet("font-size: 14px; color: #666;")
|
||
self.emptyDescLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
self.emptyDescLabel.setWordWrap(True)
|
||
|
||
emptyLayout.addWidget(self.iconLabel)
|
||
emptyLayout.addWidget(self.emptyTitleLabel, 0, Qt.AlignmentFlag.AlignCenter)
|
||
emptyLayout.addWidget(self.emptyDescLabel, 0, Qt.AlignmentFlag.AlignCenter)
|
||
|
||
self.emptyWidget.setVisible(False)
|
||
self.mainLayout.addWidget(self.emptyWidget, 1, Qt.AlignmentFlag.AlignCenter)
|
||
|
||
# 自定义分页组件
|
||
self.paginationWidget = QWidget(self)
|
||
paginationLayout = QHBoxLayout(self.paginationWidget)
|
||
paginationLayout.setContentsMargins(0, 0, 0, 0)
|
||
|
||
# 页码显示
|
||
self.currentPage = 1
|
||
self.totalPages = 1
|
||
self.pageLabel = QLabel("1/1", self.paginationWidget)
|
||
paginationLayout.addWidget(self.pageLabel)
|
||
|
||
self.mainLayout.addWidget(self.paginationWidget, alignment=Qt.AlignmentFlag.AlignRight)
|
||
|
||
def connectSignals(self):
|
||
"""连接信号与槽"""
|
||
self.tableWidget.customContextMenuRequested.connect(self.showContextMenu)
|
||
|
||
def loadShares(self):
|
||
"""加载分享列表"""
|
||
self.tableWidget.setRowCount(0)
|
||
self.emptyWidget.setVisible(False)
|
||
|
||
self.shareThread = ShareThread(self.page, self.pageSize, self.nextToken)
|
||
self.shareThread.successSignal.connect(self.onSharesLoaded)
|
||
self.shareThread.errorSignal.connect(self.onSharesLoadError)
|
||
self.shareThread.start()
|
||
|
||
def onSharesLoaded(self, result):
|
||
"""处理分享列表加载成功"""
|
||
data = result.get('data', {})
|
||
shares = data.get('shares', [])
|
||
pagination = data.get('pagination', {})
|
||
|
||
# 更新表格
|
||
self.tableWidget.setRowCount(len(shares))
|
||
|
||
for row, share in enumerate(shares):
|
||
# 分享名称
|
||
nameItem = QTableWidgetItem(share.get('name', '-'))
|
||
nameItem.setData(Qt.ItemDataRole.UserRole, share)
|
||
nameItem.setTextAlignment(Qt.AlignmentFlag.AlignVCenter)
|
||
self.tableWidget.setItem(row, 0, nameItem)
|
||
|
||
# 分享链接
|
||
shareUrl = share.get('url', '')
|
||
urlItem = QTableWidgetItem(shareUrl)
|
||
urlItem.setTextAlignment(Qt.AlignmentFlag.AlignVCenter)
|
||
self.tableWidget.setItem(row, 1, urlItem)
|
||
|
||
# 创建时间
|
||
createTime = share.get('created_at', '-')
|
||
timeItem = QTableWidgetItem(createTime)
|
||
timeItem.setTextAlignment(Qt.AlignmentFlag.AlignVCenter)
|
||
self.tableWidget.setItem(row, 2, timeItem)
|
||
|
||
# 访问次数
|
||
visits = share.get('visited', 0)
|
||
visitItem = QTableWidgetItem(str(visits))
|
||
visitItem.setTextAlignment(Qt.AlignmentFlag.AlignVCenter)
|
||
self.tableWidget.setItem(row, 3, visitItem)
|
||
|
||
# 操作按钮
|
||
actionWidget = QWidget()
|
||
actionLayout = QVBoxLayout(actionWidget)
|
||
actionLayout.setContentsMargins(0, 0, 0, 0)
|
||
|
||
deleteButton = ToolButton()
|
||
deleteButton.setText(lang("删除"))
|
||
deleteButton.setProperty("shareId", share.get('id'))
|
||
deleteButton.clicked.connect(lambda checked, shareId=share.get('id'): self.deleteShare(shareId))
|
||
|
||
actionLayout.addWidget(deleteButton, alignment=Qt.AlignmentFlag.AlignCenter)
|
||
actionWidget.setLayout(actionLayout)
|
||
self.tableWidget.setCellWidget(row, 4, actionWidget)
|
||
|
||
# 更新分页显示
|
||
self.nextToken = pagination.get('next_token')
|
||
# 对于基于token的分页,我们仍然显示页码信息以保持UI一致性
|
||
pageSize = pagination.get('page_size', self.pageSize)
|
||
# 估算总页数(基于当前获取的数量和每页大小)
|
||
estimatedTotalPages = (len(shares) + pageSize - 1) // pageSize
|
||
self.totalPages = max(1, estimatedTotalPages)
|
||
self.pageLabel.setText(f"{self.currentPage}/{self.totalPages}")
|
||
|
||
# 显示空状态
|
||
if not shares:
|
||
self.emptyWidget.setVisible(True)
|
||
|
||
def onSharesLoadError(self, errorMsg):
|
||
"""处理分享列表加载失败"""
|
||
logger.error(f"加载分享列表失败: {errorMsg}")
|
||
InfoBar.error(
|
||
lang("失败"),
|
||
f"{lang('加载分享列表失败')}: {errorMsg}",
|
||
parent=self.window()
|
||
)
|
||
self.emptyWidget.setVisible(True)
|
||
|
||
def showContextMenu(self, pos):
|
||
"""显示右键菜单"""
|
||
item = self.tableWidget.itemAt(pos)
|
||
if not item:
|
||
return
|
||
|
||
share = item.data(Qt.ItemDataRole.UserRole)
|
||
if not share:
|
||
return
|
||
|
||
menu = QMenu(self)
|
||
|
||
deleteAction = QAction(lang("删除"), self)
|
||
deleteAction.triggered.connect(lambda: self.deleteShare(share.get('id')))
|
||
|
||
menu.addAction(deleteAction)
|
||
menu.exec(self.tableWidget.mapToGlobal(pos))
|
||
|
||
def deleteShare(self, shareId):
|
||
"""删除分享"""
|
||
# 确认对话框
|
||
from qfluentwidgets import FluentIcon as FIF
|
||
from qfluentwidgets import MessageBox
|
||
|
||
dialog = MessageBox(
|
||
lang("确认删除"),
|
||
lang("确定要删除这个分享链接吗?删除后将无法恢复。"),
|
||
self.window()
|
||
)
|
||
|
||
if dialog.exec() == MessageBox.DialogCode.Accepted:
|
||
self.deleteShareThread = DeleteShareThread(shareId)
|
||
self.deleteShareThread.successSignal.connect(self.onShareDeleted)
|
||
self.deleteShareThread.errorSignal.connect(self.onShareDeleteError)
|
||
self.deleteShareThread.start()
|
||
|
||
def onShareDeleted(self, shareId):
|
||
"""处理分享删除成功"""
|
||
logger.success(f"分享删除成功: {shareId}")
|
||
InfoBar.success(
|
||
lang("成功"),
|
||
lang("分享删除成功"),
|
||
parent=self.window()
|
||
)
|
||
|
||
# 重新加载当前页
|
||
self.loadShares()
|
||
|
||
def onShareDeleteError(self, errorMsg):
|
||
"""处理分享删除失败"""
|
||
logger.error(f"删除分享失败: {errorMsg}")
|
||
InfoBar.error(
|
||
lang("失败"),
|
||
f"{lang('删除分享失败')}: {errorMsg}",
|
||
parent=self.window()
|
||
)
|
||
|
||
def onPageChanged(self, page):
|
||
"""处理页码变化"""
|
||
self.page = page
|
||
self.loadShares()
|
||
|
||
|
||
class ShareInterface(QWidget):
|
||
"""分享页面接口"""
|
||
|
||
def __init__(self, parent=None):
|
||
super().__init__(parent)
|
||
self.setObjectName("shareInterface")
|
||
self.setupUi()
|
||
|
||
def setupUi(self):
|
||
"""初始化UI"""
|
||
self.mainLayout = QVBoxLayout(self)
|
||
self.mainLayout.setContentsMargins(30, 30, 30, 30)
|
||
|
||
self.shareWidget = ShareWidget(self)
|
||
self.mainLayout.addWidget(self.shareWidget)
|
||
|
||
def refresh(self):
|
||
"""刷新页面"""
|
||
if hasattr(self, 'shareWidget'):
|
||
self.shareWidget.loadShares() |