Files
nl-utils/v1/views/history.py

471 lines
16 KiB
Python
Raw Normal View History

2025-06-07 15:54:17 +08:00
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);
}
""")