这次增加了测试结果导出到EXCEL、项目阶段需要安装定义的表格中的name PN来处理

This commit is contained in:
2025-12-14 18:19:29 +08:00
parent 872b181703
commit 5e94d17212
10 changed files with 434 additions and 17 deletions

View File

@@ -7,10 +7,15 @@
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QPushButton, QTableWidget, QTableWidgetItem,
QHeaderView, QLineEdit, QComboBox, QDateTimeEdit, QMessageBox, QGridLayout)
QHeaderView, QLineEdit, QComboBox, QDateTimeEdit, QMessageBox, QGridLayout,
QFileDialog, QProgressDialog, QApplication)
from PyQt5.QtCore import Qt, QDateTime, QSize
import requests
from config import HTTP_API_BASE_URL
import datetime
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
class TestResultView(QWidget):
@@ -235,10 +240,61 @@ class TestResultView(QWidget):
self.page_size_combo.currentTextChanged.connect(self.on_page_size_changed)
pager_layout.addWidget(self.page_size_combo)
# 上一页按钮
self.prev_btn = QPushButton("上一页")
self.prev_btn.clicked.connect(self.go_prev_page)
pager_layout.addWidget(self.prev_btn)
# 页码跳转
goto_label = QLabel("跳转至")
pager_layout.addWidget(goto_label)
self.page_input = QLineEdit()
self.page_input.setFixedWidth(60)
self.page_input.setPlaceholderText("页码")
self.page_input.setAlignment(Qt.AlignCenter)
self.page_input.setStyleSheet("""
QLineEdit {
padding: 4px;
border: 1px solid #ddd;
border-radius: 3px;
}
QLineEdit:focus {
border: 1px solid #3A84FF;
}
""")
# 按回车键跳转
self.page_input.returnPressed.connect(self.go_to_page)
pager_layout.addWidget(self.page_input)
goto_page_label = QLabel("")
pager_layout.addWidget(goto_page_label)
# 跳转按钮
self.goto_btn = QPushButton("跳转")
self.goto_btn.setFixedWidth(60)
self.goto_btn.clicked.connect(self.go_to_page)
self.goto_btn.setStyleSheet("""
QPushButton {
background-color: #3A84FF;
color: white;
border: none;
border-radius: 3px;
padding: 4px 8px;
}
QPushButton:hover {
background-color: #2B6FE6;
}
QPushButton:pressed {
background-color: #1F5BD1;
}
QPushButton:disabled {
background-color: #cccccc;
}
""")
pager_layout.addWidget(self.goto_btn)
# 下一页按钮
self.next_btn = QPushButton("下一页")
self.next_btn.clicked.connect(self.go_next_page)
pager_layout.addWidget(self.next_btn)
@@ -444,7 +500,261 @@ class TestResultView(QWidget):
if self.current_page < total_pages:
self.current_page += 1
self.load_data()
def go_to_page(self):
"""跳转到指定页码"""
try:
# 获取输入的页码
page_text = self.page_input.text().strip()
if not page_text:
QMessageBox.warning(self, "提示", "请输入页码")
return
# 尝试转换为整数
try:
target_page = int(page_text)
except ValueError:
QMessageBox.warning(self, "错误", "页码必须是整数")
self.page_input.clear()
return
# 计算总页数
total_pages = max(1, (self.total_count + self.page_size - 1) // self.page_size)
# 检查页码有效性
if target_page < 1:
QMessageBox.warning(self, "错误", f"页码不能小于 1")
self.page_input.clear()
return
if target_page > total_pages:
QMessageBox.warning(
self,
"错误",
f"页码不能大于总页数 {total_pages}"
)
self.page_input.clear()
return
# 如果已经在当前页,不需要重复加载
if target_page == self.current_page:
QMessageBox.information(self, "提示", f"当前已在第 {target_page}")
self.page_input.clear()
return
# 跳转到目标页
self.current_page = target_page
self.page_input.clear()
self.load_data()
except Exception as e:
print(f"页码跳转失败: {e}")
QMessageBox.critical(self, "错误", f"跳转失败:{str(e)}")
self.page_input.clear()
def on_export(self):
"""导出结果"""
QMessageBox.information(self, "导出", "导出功能开发中...")
"""导出结果到Excel"""
try:
# 获取满足筛选条件的总数
total_count = self.total_count
if total_count == 0:
QMessageBox.information(self, "提示", "没有数据可以导出")
return
# 生成默认文件名testResult+日期
default_filename = f"testResult_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
# 显示另存为对话框
file_path, _ = QFileDialog.getSaveFileName(
self,
"导出测试结果",
default_filename,
"Excel Files (*.xlsx);;All Files (*)"
)
if not file_path:
return # 用户取消
# 确保文件后缀名
if not file_path.endswith('.xlsx'):
file_path += '.xlsx'
# 显示进度对话框
progress = QProgressDialog("正在导出数据...", "取消", 0, 100, self)
progress.setWindowModality(Qt.WindowModal)
progress.setWindowTitle("导出进度")
progress.setMinimumDuration(0)
progress.setValue(0)
QApplication.processEvents()
# 分批获取策略每次最多获取500条数据
batch_size = 500
total_batches = (total_count + batch_size - 1) // batch_size
# 创建Excel工作簿
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "测试结果"
# 设置表头
headers = [
"序号", "样品编号", "项目代码", "项目阶段", "项目方案", "测试周次",
"工单名称", "产品序列号", "测试设备", "测试通道", "跌落方向",
"跌落高度(mm)", "跌落速度(次/Min)", "样品跌落次数", "方向当前次数",
"木板累计跌落次数", "试验开始时间", "试验结束时间"
]
ws.append(headers)
# 设置表头样式
header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
header_font = Font(bold=True, color="FFFFFF", size=11)
header_alignment = Alignment(horizontal="center", vertical="center")
for col_num, header in enumerate(headers, 1):
cell = ws.cell(row=1, column=col_num)
cell.fill = header_fill
cell.font = header_font
cell.alignment = header_alignment
# 分批获取并写入数据
all_data = []
for batch_num in range(total_batches):
if progress.wasCanceled():
QMessageBox.information(self, "提示", "导出已取消")
return
# 更新进度
progress_value = int((batch_num / total_batches) * 80) # 0-80%用于数据获取
progress.setValue(progress_value)
progress.setLabelText(f"正在获取数据... ({batch_num + 1}/{total_batches})")
QApplication.processEvents()
# 获取当前批次数据
batch_data = self._fetch_batch_data(batch_num + 1, batch_size)
if batch_data:
all_data.extend(batch_data)
# 应用前端筛选(测试人员)
progress.setValue(85)
progress.setLabelText("正在筛选数据...")
QApplication.processEvents()
filtered_data = self._filter_data_by_inspector(all_data)
# 写入数据到Excel
progress.setValue(90)
progress.setLabelText(f"正在写入Excel... 共{len(filtered_data)}条数据")
QApplication.processEvents()
for idx, item in enumerate(filtered_data):
row_data = [
self._format_cell_value(item.get('mysequence', idx + 1)),
self._format_cell_value(item.get('SN')),
self._format_cell_value(item.get('dutProject')),
self._format_cell_value(item.get('dutPhase')),
self._format_cell_value(item.get('dutProjectType')),
self._format_cell_value(item.get('dutWeeks')),
self._format_cell_value(item.get('dutWorkOrder')),
self._format_cell_value(item.get('SN')),
self._format_cell_value(item.get('machine_sn')),
self._format_cell_value(item.get('station_no')),
self._format_cell_value(item.get('dropDirection')),
self._format_cell_value(item.get('dropHeight_int')),
self._format_cell_value(item.get('dropSpeed')),
self._format_cell_value(item.get('dropCycles')),
self._format_cell_value(item.get('itemCurrentCycles')),
self._format_cell_value(item.get('stationDropCycles')),
self._format_cell_value(item.get('startTime')),
self._format_cell_value(item.get('endTime'))
]
ws.append(row_data)
# 每100行更新一次进度
if (idx + 1) % 100 == 0:
progress_value = 90 + int((idx + 1) / len(filtered_data) * 8) # 90-98%
progress.setValue(progress_value)
QApplication.processEvents()
# 设置列宽
for col_num in range(1, len(headers) + 1):
column_letter = get_column_letter(col_num)
ws.column_dimensions[column_letter].width = 15
# 保存文件
progress.setValue(99)
progress.setLabelText("正在保存文件...")
QApplication.processEvents()
wb.save(file_path)
progress.setValue(100)
progress.close()
QMessageBox.information(
self,
"成功",
f"导出成功!\n共导出 {len(filtered_data)} 条数据\n文件保存在:{file_path}"
)
except Exception as e:
print(f"导出失败: {e}")
import traceback
traceback.print_exc()
QMessageBox.critical(self, "错误", f"导出失败:{str(e)}")
def _fetch_batch_data(self, page, page_size):
"""获取指定页的数据"""
try:
url = f"{self.api_base_url}/dbTableAccess"
# 构建请求参数(与当前筛选条件一致)
params = {
'table': 'testReqResult',
'pageSize': page_size,
'currentPage': page,
}
# 添加时间筛选
start_dt = self.start_datetime_edit.dateTime().toString("yyyy/MM/dd HH:mm:ss")
end_dt = self.end_datetime_edit.dateTime().toString("yyyy/MM/dd HH:mm:ss")
params['date1'] = start_dt
params['date2'] = end_dt
# 添加样品编号筛选
sn_filter = self.sn_input.text().strip()
if sn_filter:
params['SN'] = sn_filter
# 添加工单筛选
workorder_filter = self.workorder_input.text().strip()
if workorder_filter:
params['dutWorkOrder'] = workorder_filter
# 调用后端API
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
result = response.json()
if 'data' in result:
return result['data']
return []
except Exception as e:
print(f"获取第{page}页数据失败: {e}")
return []
def _filter_data_by_inspector(self, data):
"""根据测试人员筛选数据(前端筛选)"""
inspector_filter = self.inspector_input.text().strip().lower()
if not inspector_filter:
return data
filtered = []
for item in data:
inspector = str(item.get('tester', '')).lower()
if inspector_filter in inspector:
filtered.append(item)
return filtered