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); } """)