Files
nl-utils/v1/views/history.py
2025-06-07 15:54:17 +08:00

471 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
""")