You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
10 KiB
Python

4 months ago
import sys
import os
from PyQt5.QtCore import Qt, QTimer, QAbstractTableModel, QModelIndex, QPoint, QSize, pyqtSignal, QFile, QTextStream
from PyQt5.QtGui import QBrush, QColor, QFont, QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableView,
QPushButton, QVBoxLayout, QWidget, QHBoxLayout,
QLabel, QCheckBox, QSpinBox, QMenu, QFileDialog,
QTabWidget, QTabBar, QListWidget, QListWidgetItem, QDialog,
QLineEdit, QFormLayout, QDialogButtonBox, QMessageBox,
QHeaderView, QToolBar, QAction, QStatusBar, QComboBox, QSplitter, QAbstractItemView)
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
import qtawesome as qta
from datetime import datetime
# 导入其他模块
from model.ProcedureModel.ProcedureProcessor import ExcelParser, StepTableModel
from utils.DBModels.ProcedureModel import DatabaseManager
from UI.ProcedureManager.StepExecutor import StepExecutor # 修改导入路径
class HistoryViewerWidget(QDialog):
def __init__(self, dbManager, parent=None):
super().__init__(parent)
self.dbManager = dbManager
self.setWindowTitle("历史记录查看器")
self.setGeometry(200, 200, 1000, 800)
self.initUi()
self.loadHistory()
def initUi(self):
layout = QVBoxLayout()
# 搜索栏
searchLayout = QHBoxLayout()
self.searchEdit = QLineEdit()
self.searchEdit.setPlaceholderText("搜索规程...")
self.searchEdit.textChanged.connect(self.loadHistory)
searchLayout.addWidget(QLabel("搜索:"))
searchLayout.addWidget(self.searchEdit)
# 将搜索栏布局添加到主布局
layout.addLayout(searchLayout) # 修复:在此处添加搜索栏
# 历史记录表格
self.table = QTableView()
self.table.setEditTriggers(QTableView.NoEditTriggers)
self.model = QStandardItemModel()
self.model.setHorizontalHeaderLabels(["ID", "规程全名", "类型", "执行时间", "报告路径"])
self.table.setModel(self.model)
self.table.doubleClicked.connect(self.openReportOrDetails)
self.table.setSelectionBehavior(QTableView.SelectRows)
# 新增:设置表格的右键菜单策略
self.table.setContextMenuPolicy(Qt.CustomContextMenu)
self.table.customContextMenuRequested.connect(self.showHistoryContextMenu)
# 新增:设置表格列宽自适应内容
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
# 步骤详情表格
self.stepTable = QTableView()
self.stepTable.setEditTriggers(QTableView.NoEditTriggers) # 新增:禁用编辑
self.stepModel = QStandardItemModel()
self.stepModel.setHorizontalHeaderLabels(["步骤ID", "步骤描述", "执行时间", "执行结果"])
self.stepTable.setModel(self.stepModel)
# 新增:设置表格列宽自适应内容
self.stepTable.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
# 分割窗口
splitter = QSplitter(Qt.Vertical)
splitter.addWidget(self.table)
splitter.addWidget(self.stepTable)
splitter.setSizes([400, 400]) # 初始分配高度
layout.addWidget(splitter)
# 新增:操作按钮布局
button_layout = QHBoxLayout()
self.deleteButton = QPushButton("删除历史记录")
self.deleteButton.setIcon(qta.icon('fa5s.trash', color='red'))
self.deleteButton.clicked.connect(self.deleteSelectedHistory)
button_layout.addWidget(self.deleteButton)
# 新增:导出报告按钮
self.exportButton = QPushButton("导出报告")
self.exportButton.setIcon(qta.icon('fa5s.file-export', color='green'))
self.exportButton.clicked.connect(self.exportReport)
button_layout.addWidget(self.exportButton)
button_layout.addStretch()
layout.addLayout(button_layout)
# 按钮
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
buttonBox.accepted.connect(self.accept)
layout.addWidget(buttonBox)
self.setLayout(layout)
def loadHistory(self):
self.model.removeRows(0, self.model.rowCount())
filterText = self.searchEdit.text().strip()
history = self.dbManager.getExecutionHistory(filterText)
for record in history:
# 修改使用正确的列索引0-4
row = [
QStandardItem(str(record[0])), # ID
QStandardItem(record[1]), # 规程全名(名称+编号)
QStandardItem(record[2]), # 类型
QStandardItem(record[3]), # 执行时间
QStandardItem(record[4]) # 报告路径
]
self.model.appendRow(row)
self.table.resizeColumnsToContents()
def openReportOrDetails(self, index):
# 修改:将 get_step_results 改为 getStepResults
execution_id = self.model.item(index.row(), 0).text()
step_results = self.dbManager.getStepResults(execution_id) # 修正方法名
self.showStepDetails(step_results)
# 保存操作历史
self.saveOperationHistory(execution_id, "查看步骤详情", "")
def saveOperationHistory(self, executionId, operationType, operationDetail):
"""保存操作历史记录"""
self.dbManager.saveOperationHistory(
executionId,
operationType,
operationDetail,
datetime.now().strftime("%Y-%m-%d %H:%M:%S")
)
def showStepDetails(self, stepResults):
"""显示步骤详情"""
self.stepModel.removeRows(0, self.stepModel.rowCount())
if not stepResults:
return
for step in stepResults:
row = [
QStandardItem(step['step_id']),
QStandardItem(step['step_description']),
QStandardItem(step['execution_time']),
QStandardItem('成功' if step['result'] else '失败')
]
self.stepModel.appendRow(row)
# 新增删除历史记录的方法
def deleteSelectedHistory(self):
"""删除选中的历史记录"""
selected_indexes = self.table.selectionModel().selectedRows()
if not selected_indexes:
QMessageBox.warning(self, "未选择", "请先选择要删除的历史记录")
return
# 获取选中的执行ID
execution_ids = []
for index in selected_indexes:
execution_id = self.model.item(index.row(), 0).text()
execution_ids.append(execution_id)
# 确认删除
reply = QMessageBox.question(
self,
"确认删除",
f"确定要删除选中的 {len(execution_ids)} 条历史记录吗?\n此操作不可恢复!",
QMessageBox.Yes | QMessageBox.No
)
if reply == QMessageBox.Yes:
# 修改:将 delete_execution_history 改为 deleteExecutionHistory
success = self.dbManager.deleteExecutionHistory(execution_ids) # 修正方法名
if success:
QMessageBox.information(self, "删除成功", "已成功删除选中的历史记录")
self.loadHistory() # 重新加载历史记录
else:
QMessageBox.warning(self, "删除失败", "删除历史记录时发生错误")
def exportReport(self):
"""导出选中历史记录的报告"""
selected_indexes = self.table.selectionModel().selectedRows()
if not selected_indexes:
QMessageBox.warning(self, "未选择", "请先选择要导出的历史记录")
return
if len(selected_indexes) > 1:
QMessageBox.warning(self, "选择过多", "一次只能导出一个历史记录的报告")
return
index = selected_indexes[0]
execution_id = self.model.item(index.row(), 0).text()
# 修改报告路径现在是第5列索引4
reportPath = self.model.item(index.row(), 4).text()
# 获取执行详情数据
# 修改:将 get_execution_details 改为 getExecutionDetails
execution_data = self.dbManager.getExecutionDetails(execution_id) # 修正方法名
if not execution_data:
QMessageBox.warning(self, "数据错误", "无法获取执行详情数据")
return
# 生成报告
try:
# 创建临时StepExecutor实例用于生成报告
executor = StepExecutor(execution_data['procedure_content'],
execution_data['procedure_id'],
self.dbManager)
executor.stepResults = execution_data['step_results']
# 设置步骤数据
for step in executor.tableModel.stepData:
step_result = next((s for s in execution_data['step_results']
if s['step_id'] == step['stepId']), None)
if step_result:
step['executed'] = True
step['result'] = step_result['result']
step['time'] = datetime.strptime(step_result['execution_time'], "%Y-%m-%d %H:%M:%S")
# 生成报告文件
default_name = f"{execution_data['procedure_name']}_历史报告_{execution_id}.docx"
# file_path, _ = QFileDialog.getSaveFileName(
# self, "保存报告", default_name, "Word文档 (*.docx)"
# )
# if file_path:
res = executor.generateReport()
# QMessageBox.information(self, "导出成功", f"报告已保存到:\n{res}")
except Exception as e:
QMessageBox.critical(self, "导出错误", f"生成报告时出错:\n{str(e)}")
# 新增:历史记录表格的右键菜单
def showHistoryContextMenu(self, pos):
"""显示历史记录的右键菜单"""
index = self.table.indexAt(pos)
if index.isValid():
menu = QMenu()
deleteAction = menu.addAction("删除历史记录")
deleteAction.triggered.connect(self.deleteSelectedHistory)
menu.exec_(self.table.viewport().mapToGlobal(pos))