471 lines
16 KiB
Python
471 lines
16 KiB
Python
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||
QPushButton, QTableWidget, QTableWidgetItem,
|
||
QHeaderView, QAbstractItemView, QFrame,
|
||
QComboBox, QDateEdit, QLineEdit, QSpacerItem)
|
||
from PyQt5.QtCore import Qt, QDate
|
||
from PyQt5.QtGui import QBrush, QColor, QIcon, QFont
|
||
|
||
|
||
class HistoryPage(QWidget):
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.setObjectName("historyPage")
|
||
self.init_ui()
|
||
|
||
def init_ui(self):
|
||
main_layout = QVBoxLayout()
|
||
main_layout.setContentsMargins(25, 20, 25, 20)
|
||
main_layout.setSpacing(15)
|
||
|
||
# 标题区域
|
||
title_layout = QHBoxLayout()
|
||
|
||
title = QLabel("使用记录")
|
||
title.setObjectName("pageTitle")
|
||
title.setFont(QFont("Segoe UI", 18, QFont.Bold))
|
||
title_layout.addWidget(title)
|
||
|
||
title_layout.addStretch()
|
||
|
||
# 导出按钮
|
||
export_btn = QPushButton("导出记录")
|
||
export_btn.setObjectName("exportBtn")
|
||
export_btn.setIcon(QIcon(":/icons/download.png"))
|
||
export_btn.setCursor(Qt.PointingHandCursor)
|
||
title_layout.addWidget(export_btn)
|
||
|
||
# 刷新按钮
|
||
refresh_btn = QPushButton("刷新")
|
||
refresh_btn.setObjectName("refreshBtn")
|
||
refresh_btn.setIcon(QIcon(":/icons/refresh.png"))
|
||
refresh_btn.setCursor(Qt.PointingHandCursor)
|
||
title_layout.addWidget(refresh_btn)
|
||
|
||
main_layout.addLayout(title_layout)
|
||
|
||
# 筛选控件
|
||
filter_layout = QHBoxLayout()
|
||
filter_layout.setContentsMargins(0, 0, 0, 0)
|
||
filter_layout.setSpacing(10)
|
||
|
||
# 类型选择器
|
||
type_combo = QComboBox()
|
||
type_combo.addItems(["全部操作", "转换", "下载", "上传", "删除"])
|
||
type_combo.setFixedWidth(120)
|
||
type_combo.setObjectName("filterCombo")
|
||
|
||
# 日期范围选择
|
||
date_layout = QHBoxLayout()
|
||
date_layout.setSpacing(5)
|
||
|
||
start_date = QDateEdit()
|
||
start_date.setDate(QDate.currentDate().addMonths(-1))
|
||
start_date.setCalendarPopup(True)
|
||
start_date.setDisplayFormat("yyyy-MM-dd")
|
||
start_date.setFixedWidth(110)
|
||
start_date.setObjectName("dateInput")
|
||
|
||
to_label = QLabel("至")
|
||
|
||
end_date = QDateEdit()
|
||
end_date.setDate(QDate.currentDate())
|
||
end_date.setCalendarPopup(True)
|
||
end_date.setDisplayFormat("yyyy-MM-dd")
|
||
end_date.setFixedWidth(110)
|
||
end_date.setObjectName("dateInput")
|
||
|
||
date_layout.addWidget(start_date)
|
||
date_layout.addWidget(to_label)
|
||
date_layout.addWidget(end_date)
|
||
|
||
# 搜索框
|
||
search_layout = QHBoxLayout()
|
||
search_layout.setSpacing(5)
|
||
search_layout.setContentsMargins(0, 0, 0, 0)
|
||
|
||
search_input = QLineEdit()
|
||
search_input.setPlaceholderText("搜索文件名、操作类型...")
|
||
search_input.setFixedWidth(250)
|
||
search_input.setObjectName("searchInput")
|
||
|
||
search_btn = QPushButton()
|
||
search_btn.setIcon(QIcon(":/icons/search.png"))
|
||
search_btn.setObjectName("searchBtn")
|
||
search_btn.setFixedSize(40, 40)
|
||
search_btn.setCursor(Qt.PointingHandCursor)
|
||
|
||
search_layout.addWidget(search_input)
|
||
search_layout.addWidget(search_btn)
|
||
|
||
# 添加到主筛选布局
|
||
filter_layout.addWidget(type_combo)
|
||
filter_layout.addSpacing(15)
|
||
filter_layout.addWidget(QLabel("时间段:"))
|
||
filter_layout.addLayout(date_layout)
|
||
filter_layout.addSpacing(15)
|
||
filter_layout.addWidget(QLabel("搜索:"))
|
||
filter_layout.addLayout(search_layout)
|
||
filter_layout.addStretch()
|
||
|
||
main_layout.addLayout(filter_layout)
|
||
|
||
# 结果计数
|
||
count_layout = QHBoxLayout()
|
||
count_layout.setContentsMargins(0, 0, 0, 0)
|
||
|
||
result_count = QLabel("共找到 125 条记录")
|
||
result_count.setObjectName("resultCount")
|
||
result_count.setStyleSheet("color: #a0aec0; font-size: 13px;")
|
||
count_layout.addWidget(result_count)
|
||
count_layout.addStretch()
|
||
|
||
main_layout.addLayout(count_layout)
|
||
|
||
# 表格区域
|
||
self.table = QTableWidget(0, 5) # 0行,5列
|
||
self.table.setObjectName("historyTable")
|
||
self.table.setHorizontalHeaderLabels(["日期时间", "操作类型", "文件名称", "状态", ""])
|
||
self.table.setColumnWidth(0, 160)
|
||
self.table.setColumnWidth(1, 100)
|
||
self.table.setColumnWidth(2, 280)
|
||
self.table.setColumnWidth(3, 80)
|
||
self.table.setColumnWidth(4, 100)
|
||
self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
|
||
self.table.verticalHeader().setVisible(False)
|
||
self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||
self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||
self.table.setAlternatingRowColors(True)
|
||
|
||
# 表头样式
|
||
header = self.table.horizontalHeader()
|
||
header.setStyleSheet("""
|
||
QHeaderView::section {
|
||
background-color: #2d3748;
|
||
padding: 12px 15px;
|
||
border: none;
|
||
color: #a0aec0;
|
||
font-weight: 600;
|
||
font-size: 13px;
|
||
}
|
||
""")
|
||
|
||
# 填充示例数据
|
||
self.populate_table()
|
||
|
||
main_layout.addWidget(self.table, 1) # 弹性因子1
|
||
|
||
# 分页控件
|
||
pagination_layout = QHBoxLayout()
|
||
pagination_layout.setContentsMargins(0, 10, 0, 0)
|
||
|
||
# 每页显示选择
|
||
per_page_layout = QHBoxLayout()
|
||
per_page_layout.setSpacing(5)
|
||
per_page_layout.addWidget(QLabel("每页显示:"))
|
||
|
||
per_page_combo = QComboBox()
|
||
per_page_combo.addItems(["10", "25", "50", "100"])
|
||
per_page_combo.setCurrentText("25")
|
||
per_page_combo.setFixedWidth(80)
|
||
per_page_combo.setObjectName("pageCombo")
|
||
per_page_layout.addWidget(per_page_combo)
|
||
|
||
pagination_layout.addLayout(per_page_layout)
|
||
pagination_layout.addStretch()
|
||
|
||
# 分页导航
|
||
prev_btn = QPushButton("上一页")
|
||
prev_btn.setObjectName("paginationBtn")
|
||
prev_btn.setCursor(Qt.PointingHandCursor)
|
||
prev_btn.setFixedWidth(80)
|
||
prev_btn.setEnabled(False)
|
||
|
||
page_label = QLabel("第 1 / 5 页")
|
||
page_label.setObjectName("pageLabel")
|
||
page_label.setFixedWidth(100)
|
||
page_label.setAlignment(Qt.AlignCenter)
|
||
|
||
next_btn = QPushButton("下一页")
|
||
next_btn.setObjectName("paginationBtn")
|
||
next_btn.setCursor(Qt.PointingHandCursor)
|
||
next_btn.setFixedWidth(80)
|
||
|
||
pagination_layout.addWidget(prev_btn)
|
||
pagination_layout.addWidget(page_label)
|
||
pagination_layout.addWidget(next_btn)
|
||
|
||
main_layout.addLayout(pagination_layout)
|
||
|
||
self.setLayout(main_layout)
|
||
|
||
def populate_table(self):
|
||
# 示例数据
|
||
records = [
|
||
{"time": "2023-06-15 14:30:22", "type": "转换", "file": "季度报告.docx", "status": "成功"},
|
||
{"time": "2023-06-14 10:15:45", "type": "下载", "file": "项目文档.pdf", "status": "成功"},
|
||
{"time": "2023-06-13 16:45:10", "type": "转换", "file": "个人简历.docx", "status": "失败",
|
||
"error": "文件格式不支持"},
|
||
{"time": "2023-06-12 09:20:33", "type": "上传", "file": "产品设计图.png", "status": "成功"},
|
||
{"time": "2023-06-11 17:30:18", "type": "删除", "file": "旧项目备份.zip", "status": "成功"},
|
||
{"time": "2023-06-10 08:45:27", "type": "转换", "file": "年度计划.docx", "status": "成功"},
|
||
{"time": "2023-06-09 11:12:03", "type": "下载", "file": "合同范本.pdf", "status": "成功"},
|
||
{"time": "2023-06-08 14:22:55", "type": "转换", "file": "用户手册.docx", "status": "失败",
|
||
"error": "文件已损坏"},
|
||
{"time": "2023-06-07 16:30:41", "type": "上传", "file": "会议记录.txt", "status": "成功"},
|
||
{"time": "2023-06-06 10:45:19", "type": "转换", "file": "财务数据.xlsx", "status": "失败",
|
||
"error": "不支持Excel转换"},
|
||
]
|
||
|
||
self.table.setRowCount(len(records))
|
||
|
||
for row, record in enumerate(records):
|
||
# 时间
|
||
time_item = QTableWidgetItem(record["time"])
|
||
time_item.setFont(QFont("Segoe UI", 10))
|
||
self.table.setItem(row, 0, time_item)
|
||
|
||
# 类型
|
||
type_item = QTableWidgetItem(record["type"])
|
||
type_item.setFont(QFont("Segoe UI", 10, QFont.Medium))
|
||
type_item.setTextAlignment(Qt.AlignCenter)
|
||
|
||
# 设置类型颜色
|
||
type_colors = {
|
||
"转换": "#818cf8", # 紫色
|
||
"下载": "#34d399", # 绿色
|
||
"上传": "#60a5fa", # 蓝色
|
||
"删除": "#f87171", # 红色
|
||
}
|
||
color = type_colors.get(record["type"], "#a0aec0")
|
||
type_item.setForeground(QBrush(QColor(color)))
|
||
self.table.setItem(row, 1, type_item)
|
||
|
||
# 文件名
|
||
file_item = QTableWidgetItem(record["file"])
|
||
file_item.setFont(QFont("Segoe UI", 10))
|
||
self.table.setItem(row, 2, file_item)
|
||
|
||
# 状态
|
||
status_item = QTableWidgetItem(record["status"])
|
||
status_item.setFont(QFont("Segoe UI", 10, QFont.Medium))
|
||
status_item.setTextAlignment(Qt.AlignCenter)
|
||
|
||
# 设置状态颜色
|
||
if record["status"] == "成功":
|
||
status_color = QColor("#10b981") # 绿色
|
||
else:
|
||
status_color = QColor("#ef4444") # 红色
|
||
|
||
status_item.setForeground(QBrush(status_color))
|
||
self.table.setItem(row, 3, status_item)
|
||
|
||
# 操作按钮
|
||
btn_layout = QHBoxLayout()
|
||
btn_layout.setContentsMargins(0, 0, 0, 0)
|
||
btn_layout.setSpacing(5)
|
||
|
||
# 查看按钮
|
||
view_btn = QPushButton("详情")
|
||
view_btn.setObjectName("actionBtn")
|
||
view_btn.setFixedSize(60, 28)
|
||
view_btn.setProperty("row", row)
|
||
|
||
# 如果是失败状态,添加重试按钮
|
||
if record.get("error"):
|
||
retry_btn = QPushButton("重试")
|
||
retry_btn.setObjectName("retryBtn")
|
||
retry_btn.setFixedSize(60, 28)
|
||
retry_btn.setProperty("row", row)
|
||
btn_layout.addWidget(retry_btn)
|
||
|
||
# 删除按钮
|
||
delete_btn = QPushButton("删除")
|
||
delete_btn.setObjectName("deleteBtn")
|
||
delete_btn.setFixedSize(60, 28)
|
||
delete_btn.setProperty("row", row)
|
||
|
||
btn_layout.addWidget(view_btn)
|
||
btn_layout.addWidget(delete_btn)
|
||
|
||
# 添加到表格单元格
|
||
widget = QWidget()
|
||
widget.setLayout(btn_layout)
|
||
self.table.setCellWidget(row, 4, widget)
|
||
|
||
# 设置行高
|
||
for row in range(len(records)):
|
||
self.table.setRowHeight(row, 45)
|
||
|
||
# 设置表格为空时的提示
|
||
if len(records) == 0:
|
||
self.table.setRowCount(1)
|
||
self.table.setSpan(0, 0, 1, self.table.columnCount())
|
||
|
||
empty_label = QLabel("没有找到记录")
|
||
empty_label.setAlignment(Qt.AlignCenter)
|
||
empty_label.setStyleSheet("color: #a0aec0; font-size: 16px;")
|
||
self.table.setCellWidget(0, 0, empty_label)
|
||
self.table.setRowHeight(0, 200)
|
||
|
||
# 统一设置按钮样式
|
||
self.set_styles()
|
||
|
||
def set_styles(self):
|
||
self.setStyleSheet("""
|
||
/* ---------- 页面容器 ---------- */
|
||
QWidget#historyPage {
|
||
background-color: #1a202c;
|
||
}
|
||
|
||
/* ---------- 按钮通用样式 ---------- */
|
||
QPushButton {
|
||
border-radius: 4px;
|
||
padding: 8px 12px;
|
||
font-weight: 500;
|
||
transition: all 0.2s;
|
||
border: none;
|
||
}
|
||
|
||
/* 刷新和导出按钮 */
|
||
QPushButton#refreshBtn,
|
||
QPushButton#exportBtn {
|
||
background-color: #4f46e5;
|
||
color: white;
|
||
min-height: 40px;
|
||
padding: 10px 16px;
|
||
min-width: 120px;
|
||
}
|
||
|
||
QPushButton#refreshBtn:hover,
|
||
QPushButton#exportBtn:hover {
|
||
background-color: #4338ca;
|
||
}
|
||
|
||
/* 筛选控件 */
|
||
QComboBox#filterCombo,
|
||
QComboBox#pageCombo {
|
||
background-color: #2d3748;
|
||
border: 1px solid #4a5568;
|
||
border-radius: 4px;
|
||
padding: 8px 12px;
|
||
color: #e2e8f0;
|
||
min-height: 35px;
|
||
}
|
||
|
||
QComboBox#filterCombo::drop-down,
|
||
QComboBox#pageCombo::drop-down {
|
||
width: 20px;
|
||
border: none;
|
||
}
|
||
|
||
QComboBox#filterCombo QAbstractItemView,
|
||
QComboBox#pageCombo QAbstractItemView {
|
||
background-color: #2d3748;
|
||
border: 1px solid #4a5568;
|
||
color: #e2e8f0;
|
||
selection-background-color: #4f46e5;
|
||
}
|
||
|
||
/* 日期输入 */
|
||
QDateEdit#dateInput {
|
||
background-color: #2d3748;
|
||
border: 1px solid #4a5568;
|
||
border-radius: 4px;
|
||
padding: 8px 12px;
|
||
color: #e2e8f0;
|
||
min-height: 35px;
|
||
}
|
||
|
||
QDateEdit#dateInput::drop-down {
|
||
width: 20px;
|
||
border: none;
|
||
}
|
||
|
||
/* 搜索框 */
|
||
QLineEdit#searchInput {
|
||
background-color: #2d3748;
|
||
border: 1px solid #4a5568;
|
||
border-radius: 4px;
|
||
padding: 8px 12px;
|
||
color: #e2e8f0;
|
||
min-height: 35px;
|
||
}
|
||
|
||
QPushButton#searchBtn {
|
||
background-color: #4f46e5;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
QPushButton#searchBtn:hover {
|
||
background-color: #4338ca;
|
||
}
|
||
|
||
/* 分页按钮 */
|
||
QPushButton#paginationBtn {
|
||
background-color: #2d3748;
|
||
border: 1px solid #4a5568;
|
||
color: #e2e8f0;
|
||
padding: 8px;
|
||
min-height: 35px;
|
||
}
|
||
|
||
QPushButton#paginationBtn:hover {
|
||
background-color: rgba(79, 70, 229, 0.15);
|
||
border-color: #818cf8;
|
||
}
|
||
|
||
/* ---------- 表格样式 ---------- */
|
||
QTableView#historyTable {
|
||
background-color: #1a202c;
|
||
border: none;
|
||
border-radius: 8px;
|
||
gridline-color: #2d3748;
|
||
selection-background-color: rgba(79, 70, 229, 0.15);
|
||
selection-color: white;
|
||
alternate-background-color: #19202c;
|
||
}
|
||
|
||
QTableView#historyTable QTableCornerButton::section {
|
||
background-color: #2d3748;
|
||
border: none;
|
||
}
|
||
|
||
QTableView#historyTable::item {
|
||
padding: 12px 15px;
|
||
border-bottom: 1px solid rgba(74, 85, 104, 0.5);
|
||
color: #e2e8f0;
|
||
}
|
||
|
||
/* 操作按钮 */
|
||
QPushButton#actionBtn {
|
||
background-color: rgba(129, 140, 248, 0.1);
|
||
color: #818cf8;
|
||
border: 1px solid rgba(129, 140, 248, 0.2);
|
||
}
|
||
|
||
QPushButton#actionBtn:hover {
|
||
background-color: rgba(129, 140, 248, 0.2);
|
||
}
|
||
|
||
/* 重试按钮 */
|
||
QPushButton#retryBtn {
|
||
background-color: rgba(251, 113, 133, 0.1);
|
||
color: #fb7185;
|
||
border: 1px solid rgba(251, 113, 133, 0.2);
|
||
}
|
||
|
||
QPushButton#retryBtn:hover {
|
||
background-color: rgba(251, 113, 133, 0.2);
|
||
}
|
||
|
||
/* 删除按钮 */
|
||
QPushButton#deleteBtn {
|
||
background-color: rgba(120, 113, 108, 0.1);
|
||
color: #a8a29e;
|
||
border: 1px solid rgba(120, 113, 108, 0.2);
|
||
}
|
||
|
||
QPushButton#deleteBtn:hover {
|
||
background-color: rgba(120, 113, 108, 0.2);
|
||
}
|
||
""") |