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.

686 lines
30 KiB
Python

4 months ago
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
规程编辑器
支持编辑规程内容并保存到数据库
"""
import json
from datetime import datetime
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QLineEdit, QTextEdit, QPushButton, QTableWidget,
QTableWidgetItem, QHeaderView, QMessageBox,
QDialog, QFormLayout, QSpinBox, QComboBox,
QDialogButtonBox, QAbstractItemView, QMenu)
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QFont, QBrush, QColor
import qtawesome as qta
class NoClearDelegate(QAbstractItemView):
"""自定义委托,防止双击时清除内容"""
def createEditor(self, parent, option, index):
editor = super().createEditor(parent, option, index)
if hasattr(editor, 'setText'):
# 保持原有内容
current_text = index.data()
if current_text:
editor.setText(current_text)
return editor
class StepEditDialog(QDialog):
"""步骤编辑对话框"""
def __init__(self, step_data=None, parent=None):
super().__init__(parent)
self.setWindowTitle("编辑步骤")
self.setModal(True)
self.setMinimumWidth(500)
self.step_data = step_data or {}
self.initUI()
def initUI(self):
layout = QVBoxLayout()
self.setLayout(layout)
# 表单布局
form_layout = QFormLayout()
# 步骤ID
self.stepIdEdit = QLineEdit()
self.stepIdEdit.setText(self.step_data.get('stepId', ''))
form_layout.addRow("步骤ID:", self.stepIdEdit)
# 操作(合并关键词和步骤描述)
self.operationEdit = QTextEdit()
self.operationEdit.setMaximumHeight(80)
self.operationEdit.setPlainText(self.step_data.get('operation', ''))
form_layout.addRow("操作:", self.operationEdit)
# 操作类型(直接输入)
self.typeEdit = QLineEdit()
self.typeEdit.setText(self.step_data.get('type', 'SET'))
form_layout.addRow("操作类型:", self.typeEdit)
# 预期值
self.expectedValueEdit = QLineEdit()
self.expectedValueEdit.setText(str(self.step_data.get('expectedValue', '')))
form_layout.addRow("预期值:", self.expectedValueEdit)
# 备注
self.remarkEdit = QTextEdit()
self.remarkEdit.setMaximumHeight(60)
self.remarkEdit.setPlainText(self.step_data.get('remark', ''))
form_layout.addRow("备注:", self.remarkEdit)
# 序号
self.orderSpin = QSpinBox()
self.orderSpin.setRange(1, 999)
self.orderSpin.setValue(self.step_data.get('order', 1))
form_layout.addRow("序号:", self.orderSpin)
layout.addLayout(form_layout)
# 按钮
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
layout.addWidget(button_box)
def getStepData(self):
"""获取步骤数据"""
return {
'stepId': self.stepIdEdit.text(),
'operation': self.operationEdit.toPlainText(),
'type': self.typeEdit.text(),
'expectedValue': self.expectedValueEdit.text(),
'remark': self.remarkEdit.toPlainText(),
'order': self.orderSpin.value()
}
class ProcedureEditor(QWidget):
"""规程编辑器"""
procedureSaved = pyqtSignal(int) # 规程保存信号
def __init__(self, procedureData, procedureId, dbManager, parent=None):
super().__init__(parent)
self.procedureData = procedureData
self.procedureId = procedureId
self.dbManager = dbManager
self.parent = parent
self.initUI()
self.loadProcedureData()
def initUI(self):
"""初始化界面"""
layout = QVBoxLayout()
self.setLayout(layout)
# 标题
title_label = QLabel("规程编辑器")
title_label.setObjectName("procedureEditorTitle") # 设置对象名称以便QSS选择器使用
layout.addWidget(title_label)
# 基本信息区域
self.createBasicInfoSection(layout)
# 步骤表格区域
self.createStepsSection(layout)
# 按钮区域
self.createButtonSection(layout)
def createBasicInfoSection(self, layout):
"""创建基本信息区域"""
info_group = QWidget()
info_group.setObjectName("basicInfoGroup") # 设置对象名称以便QSS选择器使用
layout.addWidget(info_group)
# 标题
info_title = QLabel("基本信息")
info_layout = QVBoxLayout()
info_group.setLayout(info_layout)
info_layout.addWidget(info_title)
# 表单布局
form_layout = QFormLayout()
self.nameEdit = QLineEdit()
self.nameEdit.setPlaceholderText("输入规程名称")
self.nameEdit.setObjectName("procedureNameEdit") # 设置对象名称以便QSS选择器使用
form_layout.addRow("规程名称:", self.nameEdit)
self.numberEdit = QLineEdit()
self.numberEdit.setPlaceholderText("输入规程编号")
self.numberEdit.setObjectName("procedureNumberEdit") # 设置对象名称以便QSS选择器使用
form_layout.addRow("规程编号:", self.numberEdit)
self.typeEdit = QLineEdit()
self.typeEdit.setPlaceholderText("输入规程类型")
self.typeEdit.setObjectName("procedureTypeEdit") # 设置对象名称以便QSS选择器使用
form_layout.addRow("规程类型:", self.typeEdit)
self.descriptionEdit = QTextEdit()
self.descriptionEdit.setMaximumHeight(80)
self.descriptionEdit.setPlaceholderText("输入规程描述")
self.descriptionEdit.setObjectName("procedureDescriptionEdit") # 设置对象名称以便QSS选择器使用
form_layout.addRow("规程描述:", self.descriptionEdit)
info_layout.addLayout(form_layout)
def createStepsSection(self, layout):
"""创建步骤表格区域"""
steps_group = QWidget()
steps_group.setObjectName("stepsGroup") # 设置对象名称以便QSS选择器使用
layout.addWidget(steps_group)
# 标题和按钮
header_layout = QHBoxLayout()
steps_title = QLabel("步骤列表")
header_layout.addWidget(steps_title)
# 添加步骤按钮
add_step_btn = QPushButton("添加步骤")
add_step_btn.setIcon(qta.icon('fa5s.plus', color='white'))
add_step_btn.clicked.connect(self.addStep)
header_layout.addWidget(add_step_btn)
# 删除步骤按钮
delete_step_btn = QPushButton("删除步骤")
delete_step_btn.setIcon(qta.icon('fa5s.trash', color='white'))
delete_step_btn.clicked.connect(self.deleteStep)
header_layout.addWidget(delete_step_btn)
header_layout.addStretch()
steps_layout = QVBoxLayout()
steps_group.setLayout(steps_layout)
steps_layout.addLayout(header_layout)
# 步骤表格
self.stepsTable = QTableWidget()
self.stepsTable.setObjectName("stepsTable") # 设置对象名称以便QSS选择器使用
self.stepsTable.setColumnCount(6)
self.stepsTable.setHorizontalHeaderLabels(['序号', '步骤ID', '操作', '类型', '预期值', '备注'])
# 设置表格属性
self.stepsTable.setSelectionBehavior(QAbstractItemView.SelectRows)
self.stepsTable.setEditTriggers(QAbstractItemView.AllEditTriggers) # 允许所有方式编辑
self.stepsTable.setAlternatingRowColors(True)
# 设置列宽
header = self.stepsTable.horizontalHeader()
if header:
header.setSectionResizeMode(0, QHeaderView.ResizeToContents) # 序号
header.setSectionResizeMode(1, QHeaderView.ResizeToContents) # 步骤ID
header.setSectionResizeMode(2, QHeaderView.Stretch) # 操作
header.setSectionResizeMode(3, QHeaderView.ResizeToContents) # 类型
header.setSectionResizeMode(4, QHeaderView.ResizeToContents) # 预期值
header.setSectionResizeMode(5, QHeaderView.ResizeToContents) # 备注
# 设置最小列宽,确保表头显示完整
self.stepsTable.setColumnWidth(0, 60) # 序号
self.stepsTable.setColumnWidth(1, 120) # 步骤ID
self.stepsTable.setColumnWidth(3, 80) # 类型
self.stepsTable.setColumnWidth(4, 100) # 预期值
self.stepsTable.setColumnWidth(5, 120) # 备注
# 移除双击弹窗
# self.stepsTable.cellDoubleClicked.connect(self.editStep)
# 添加右键菜单
self.stepsTable.setContextMenuPolicy(Qt.CustomContextMenu)
self.stepsTable.customContextMenuRequested.connect(self.showContextMenu)
steps_layout.addWidget(self.stepsTable)
def createButtonSection(self, layout):
"""创建按钮区域"""
button_layout = QHBoxLayout()
# 保存按钮
save_btn = QPushButton("保存规程")
save_btn.setIcon(qta.icon('fa5s.save', color='white'))
save_btn.setObjectName("saveProcedureButton") # 设置对象名称以便QSS选择器使用
save_btn.clicked.connect(self.saveProcedure)
button_layout.addWidget(save_btn)
# 取消按钮
cancel_btn = QPushButton("取消")
cancel_btn.setIcon(qta.icon('fa5s.times', color='red'))
cancel_btn.setObjectName("cancelEditButton") # 设置对象名称以便QSS选择器使用
cancel_btn.clicked.connect(self.cancelEdit)
button_layout.addWidget(cancel_btn)
button_layout.addStretch()
layout.addLayout(button_layout)
def loadProcedureData(self):
"""加载规程数据"""
if not self.procedureData:
print("警告:规程数据为空")
return
print(f"加载规程数据: {self.procedureData.keys()}")
# 加载基本信息
procedure_info = self.procedureData.get('规程信息', {})
self.nameEdit.setText(procedure_info.get('规程名称', ''))
self.numberEdit.setText(procedure_info.get('规程编号', ''))
self.typeEdit.setText(procedure_info.get('规程类型', ''))
# 加载描述(可能在不同位置)
description = self.procedureData.get('description', '')
if not description:
# 尝试从测试用例信息中获取描述
test_case_info = self.procedureData.get('测试用例信息', {})
description = test_case_info.get('工况描述', '')
self.descriptionEdit.setPlainText(description)
# 加载步骤数据
self.loadStepsData()
def loadStepsData(self):
"""加载步骤数据到表格(主子步骤都显示,字段驼峰)"""
steps = []
# 兼容老数据
if 'testSteps' in self.procedureData:
steps = self.procedureData['testSteps']
elif '测试步骤' in self.procedureData:
steps = self.procedureData['测试步骤']
if not steps:
self.stepsTable.setRowCount(0)
return
# 计算总行数
totalRows = 0
for step in steps:
totalRows += 1
totalRows += len(step.get('subSteps', []) or step.get('子步骤', []))
self.stepsTable.setRowCount(totalRows)
currentRow = 0
for mainStepIndex, mainStep in enumerate(steps):
# 主步骤
orderItem = QTableWidgetItem(str(mainStepIndex + 1))
orderItem.setFlags(orderItem.flags() & ~Qt.ItemIsEditable)
self.stepsTable.setItem(currentRow, 0, orderItem)
stepId = mainStep.get('stepId') or mainStep.get('步骤ID', '') or ''
self.stepsTable.setItem(currentRow, 1, QTableWidgetItem(stepId))
operation = mainStep.get('operation') or mainStep.get('步骤描述', '') or ''
self.stepsTable.setItem(currentRow, 2, QTableWidgetItem(operation))
stepType = mainStep.get('stepType') or mainStep.get('操作类型', '') or ''
self.stepsTable.setItem(currentRow, 3, QTableWidgetItem(stepType))
expectedValue = mainStep.get('expectedValue') or mainStep.get('预期结果', '') or ''
self.stepsTable.setItem(currentRow, 4, QTableWidgetItem(str(expectedValue)))
remark = mainStep.get('remark') or mainStep.get('备注', '') or ''
self.stepsTable.setItem(currentRow, 5, QTableWidgetItem(remark))
# 主步骤样式
for col in range(6):
item = self.stepsTable.item(currentRow, col)
if item:
item.setBackground(QBrush(QColor(220, 220, 220)))
font = item.font()
font.setBold(True)
item.setFont(font)
currentRow += 1
# 子步骤
subSteps = mainStep.get('subSteps') or mainStep.get('子步骤', [])
for subIndex, subStep in enumerate(subSteps):
orderItem = QTableWidgetItem(str(subStep.get('order', subStep.get('序号', subIndex + 1))))
orderItem.setFlags(orderItem.flags() & ~Qt.ItemIsEditable)
self.stepsTable.setItem(currentRow, 0, orderItem)
subStepId = subStep.get('stepId') or f"{stepId}{subStep.get('order', subStep.get('序号', subIndex + 1))}" or ''
self.stepsTable.setItem(currentRow, 1, QTableWidgetItem(subStepId))
subOperation = subStep.get('operation') or subStep.get('操作', '') or ''
self.stepsTable.setItem(currentRow, 2, QTableWidgetItem(subOperation))
subType = subStep.get('stepType') or subStep.get('操作类型', '') or ''
self.stepsTable.setItem(currentRow, 3, QTableWidgetItem(subType))
subExpected = subStep.get('expectedValue') or subStep.get('预期结果', '') or ''
self.stepsTable.setItem(currentRow, 4, QTableWidgetItem(str(subExpected)))
subRemark = subStep.get('remark') or subStep.get('备注', '') or ''
self.stepsTable.setItem(currentRow, 5, QTableWidgetItem(subRemark))
currentRow += 1
self.stepsTable.resizeRowsToContents()
def addStep(self):
"""添加步骤(默认为子步骤)"""
dialog = StepEditDialog(parent=self)
if dialog.exec_() == QDialog.Accepted:
step_data = dialog.getStepData()
# 添加到表格
row = self.stepsTable.rowCount()
self.stepsTable.insertRow(row)
# 设置序号
order_item = QTableWidgetItem(str(row + 1))
order_item.setFlags(order_item.flags() & ~Qt.ItemIsEditable)
self.stepsTable.setItem(row, 0, order_item)
# 设置其他字段
self.stepsTable.setItem(row, 1, QTableWidgetItem(step_data['stepId']))
self.stepsTable.setItem(row, 2, QTableWidgetItem(step_data['operation']))
self.stepsTable.setItem(row, 3, QTableWidgetItem(step_data['type']))
self.stepsTable.setItem(row, 4, QTableWidgetItem(step_data['expectedValue']))
self.stepsTable.setItem(row, 5, QTableWidgetItem(step_data['remark']))
# 不设置主步骤样式,默认为子步骤
def deleteStep(self):
"""删除选中的步骤"""
current_row = self.stepsTable.currentRow()
if current_row < 0:
QMessageBox.warning(self, "未选择步骤", "请先选择要删除的步骤")
return
# 检查是否是最后一个步骤
total_rows = self.stepsTable.rowCount()
is_last_step = (total_rows == 1)
if is_last_step:
reply = QMessageBox.question(
self, "确认删除",
"这是最后一个步骤,删除后规程将为空。确定要删除吗?",
QMessageBox.Yes | QMessageBox.No
)
else:
reply = QMessageBox.question(
self, "确认删除",
f"确定要删除第 {current_row + 1} 个步骤吗?",
QMessageBox.Yes | QMessageBox.No
)
if reply == QMessageBox.Yes:
self.stepsTable.removeRow(current_row)
# 重新编号
self.renumberSteps()
# 如果删除后没有步骤了,给出提示
if self.stepsTable.rowCount() == 0:
QMessageBox.information(
self, "步骤已清空",
"所有步骤已删除,规程现在为空。您可以添加新步骤或保存空规程。"
)
def editStep(self, row, column):
"""编辑步骤"""
# 获取当前步骤数据
stepIdItem = self.stepsTable.item(row, 1)
operationItem = self.stepsTable.item(row, 2)
typeItem = self.stepsTable.item(row, 3)
expectedValueItem = self.stepsTable.item(row, 4)
remarkItem = self.stepsTable.item(row, 5)
step_data = {
'stepId': stepIdItem.text() if stepIdItem else '',
'operation': operationItem.text() if operationItem else '',
'type': typeItem.text() if typeItem else 'SET',
'expectedValue': expectedValueItem.text() if expectedValueItem else '',
'remark': remarkItem.text() if remarkItem else '',
'order': row + 1
}
dialog = StepEditDialog(step_data, self)
if dialog.exec_() == QDialog.Accepted:
updated_data = dialog.getStepData()
# 更新表格
self.stepsTable.setItem(row, 1, QTableWidgetItem(updated_data['stepId']))
self.stepsTable.setItem(row, 2, QTableWidgetItem(updated_data['operation']))
self.stepsTable.setItem(row, 3, QTableWidgetItem(updated_data['type']))
self.stepsTable.setItem(row, 4, QTableWidgetItem(updated_data['expectedValue']))
self.stepsTable.setItem(row, 5, QTableWidgetItem(updated_data['remark']))
def renumberSteps(self):
"""重新编号步骤"""
for row in range(self.stepsTable.rowCount()):
order_item = QTableWidgetItem(str(row + 1))
order_item.setFlags(order_item.flags() & ~Qt.ItemIsEditable)
# 检查这一行是否原本是主步骤(通过检查其他列的背景色)
is_main_step = False
for col in range(1, 6): # 检查步骤ID、操作、类型、预期值、备注列
item = self.stepsTable.item(row, col)
if item and hasattr(item, 'background') and item.background().color() == QColor(220, 220, 220):
is_main_step = True
break
# 如果是主步骤,设置背景色和字体
if is_main_step:
order_item.setBackground(QBrush(QColor(220, 220, 220)))
font = order_item.font()
font.setBold(True)
order_item.setFont(font)
self.stepsTable.setItem(row, 0, order_item)
def getStepsData(self):
"""获取表格中的步骤数据"""
steps = []
for row in range(self.stepsTable.rowCount()):
stepIdItem = self.stepsTable.item(row, 1)
operationItem = self.stepsTable.item(row, 2)
typeItem = self.stepsTable.item(row, 3)
expectedValueItem = self.stepsTable.item(row, 4)
remarkItem = self.stepsTable.item(row, 5)
step = {
'order': row + 1,
'stepId': stepIdItem.text() if stepIdItem else '',
'operation': operationItem.text() if operationItem else '',
'type': typeItem.text() if typeItem else 'SET',
'expectedValue': expectedValueItem.text() if expectedValueItem else '',
'remark': remarkItem.text() if remarkItem else ''
}
steps.append(step)
return steps
def saveProcedure(self):
"""保存规程到数据库(字段驼峰,主子步骤分组)"""
try:
procedureInfo = {
'procedureName': self.nameEdit.text().strip(),
'procedureNumber': self.numberEdit.text().strip(),
'procedureType': self.typeEdit.text().strip()
}
# 数据验证和默认值处理
if not procedureInfo['procedureName']:
QMessageBox.warning(self, "验证失败", "规程名称不能为空")
return
if not procedureInfo['procedureNumber']:
QMessageBox.warning(self, "验证失败", "规程编号不能为空")
return
# 如果规程类型为空,设置默认值
if not procedureInfo['procedureType']:
procedureInfo['procedureType'] = '标准规程'
testSteps = []
currentMainStep = None
print(f"开始处理步骤,总行数: {self.stepsTable.rowCount()}")
for row in range(self.stepsTable.rowCount()):
try:
stepIdItem = self.stepsTable.item(row, 1)
operationItem = self.stepsTable.item(row, 2)
stepTypeItem = self.stepsTable.item(row, 3)
expectedValueItem = self.stepsTable.item(row, 4)
remarkItem = self.stepsTable.item(row, 5)
stepId = stepIdItem.text() if stepIdItem else ''
operation = operationItem.text() if operationItem else ''
stepType = stepTypeItem.text() if stepTypeItem else ''
expectedValue = expectedValueItem.text() if expectedValueItem else ''
remark = remarkItem.text() if remarkItem else ''
print(f"处理第{row+1}行: stepId='{stepId}', operation='{operation}', stepType='{stepType}', expectedValue='{expectedValue}', remark='{remark}'")
# 简化验证只要步骤ID或操作描述不为空就认为是有效步骤
if not (stepId.strip() or operation.strip()):
print(f" 跳过第{row+1}步骤ID和操作描述都为空")
continue
# 判断是否为主步骤(通过背景色判断)
isMainStep = False
item = self.stepsTable.item(row, 0)
if item and hasattr(item, 'background') and item.background().color() == QColor(220, 220, 220):
isMainStep = True
print(f"{row+1}行是主步骤: {isMainStep}")
if isMainStep:
# 如果有前一个主步骤,先添加到结果中
if currentMainStep is not None:
testSteps.append(currentMainStep)
print(f" 添加主步骤到testSteps当前testSteps长度: {len(testSteps)}")
# 创建新的主步骤
currentMainStep = {
'步骤ID': stepId,
'步骤描述': operation,
'操作类型': stepType,
'预期结果': expectedValue,
'备注': remark,
'子步骤': []
}
print(f" 创建新主步骤: {stepId}")
else:
# 子步骤
if currentMainStep is not None:
orderItem = self.stepsTable.item(row, 0)
orderText = orderItem.text() if orderItem else '1'
try:
orderNum = int(orderText)
except ValueError:
orderNum = 1
subStep = {
'序号': orderNum,
'操作': operation,
'操作类型': stepType,
'预期结果': expectedValue,
'实际结果': '',
'一致性': '',
'测试时间': '',
'备注': remark
}
currentMainStep['子步骤'].append(subStep)
print(f" 添加子步骤到当前主步骤,子步骤数量: {len(currentMainStep['子步骤'])}")
except Exception as rowError:
print(f"处理第 {row + 1} 行时出错: {str(rowError)}")
continue
# 添加最后一个主步骤
if currentMainStep is not None:
testSteps.append(currentMainStep)
print(f"添加最后一个主步骤最终testSteps长度: {len(testSteps)}")
else:
print("没有找到任何主步骤")
# 修改验证逻辑:允许保存空规程,但给出提示
if not testSteps:
reply = QMessageBox.question(
self, "确认保存",
"当前规程没有步骤,确定要保存空规程吗?",
QMessageBox.Yes | QMessageBox.No
)
if reply == QMessageBox.No:
return
updatedProcedure = {
'规程信息': {
'规程名称': procedureInfo['procedureName'],
'规程编号': procedureInfo['procedureNumber'],
'规程类型': procedureInfo['procedureType']
},
'测试用例信息': {
'测试用例': procedureInfo['procedureName'],
'用例编号': procedureInfo['procedureNumber'],
'工况描述': self.descriptionEdit.toPlainText()
},
'测试步骤': testSteps,
'updatedAt': datetime.now().isoformat()
}
print(f"准备保存规程: {procedureInfo['procedureName']}")
print(f"步骤数量: {len(testSteps)}")
success = self.dbManager.updateProcedure(self.procedureId, updatedProcedure)
if success:
QMessageBox.information(self, "保存成功", "规程已成功保存到数据库")
self.procedureSaved.emit(self.procedureId)
if self.parent:
currentIndex = self.parent.tabs.currentIndex()
if currentIndex > 0:
self.parent.tabs.removeTab(currentIndex)
else:
QMessageBox.critical(self, "保存失败", "保存规程到数据库时发生错误")
except Exception as e:
print(f"保存规程时发生错误: {str(e)}")
import traceback
traceback.print_exc()
QMessageBox.critical(self, "保存失败", f"保存规程时发生错误:{str(e)}")
def cancelEdit(self):
"""取消编辑"""
reply = QMessageBox.question(
self, "确认取消",
"确定要取消编辑吗?未保存的更改将丢失。",
QMessageBox.Yes | QMessageBox.No
)
if reply == QMessageBox.Yes:
# 关闭编辑器标签页
if self.parent:
current_index = self.parent.tabs.currentIndex()
if current_index > 0: # 不是规程管理标签页
self.parent.tabs.removeTab(current_index)
def showContextMenu(self, pos):
"""显示右键菜单"""
menu = QMenu(self)
# 获取当前行
current_row = self.stepsTable.rowAt(pos.y())
# 添加步骤
add_action = menu.addAction("添加步骤")
add_action.triggered.connect(self.addStep)
# 插入步骤(在选中行之前)
if current_row >= 0:
insert_action = menu.addAction(f"在此行前插入步骤")
insert_action.triggered.connect(lambda: self.insertStep(current_row))
# 编辑步骤
if current_row >= 0:
edit_action = menu.addAction("编辑步骤")
edit_action.triggered.connect(lambda: self.editStep(current_row, 0))
# 删除步骤
if current_row >= 0:
delete_action = menu.addAction("删除步骤")
delete_action.triggered.connect(self.deleteStep)
# 显示菜单
menu.exec_(self.stepsTable.mapToGlobal(pos))
def insertStep(self, position):
"""在指定位置插入新步骤(默认为子步骤)"""
dialog = StepEditDialog(parent=self)
if dialog.exec_() == QDialog.Accepted:
step_data = dialog.getStepData()
# 在指定位置插入行
self.stepsTable.insertRow(position)
# 设置序号
order_item = QTableWidgetItem(str(position + 1))
order_item.setFlags(order_item.flags() & ~Qt.ItemIsEditable)
self.stepsTable.setItem(position, 0, order_item)
# 设置其他字段
self.stepsTable.setItem(position, 1, QTableWidgetItem(step_data['stepId']))
self.stepsTable.setItem(position, 2, QTableWidgetItem(step_data['operation']))
self.stepsTable.setItem(position, 3, QTableWidgetItem(step_data['type']))
self.stepsTable.setItem(position, 4, QTableWidgetItem(step_data['expectedValue']))
self.stepsTable.setItem(position, 5, QTableWidgetItem(step_data['remark']))
# 不设置主步骤样式,默认为子步骤
# 重新编号所有步骤
self.renumberSteps()