Files
dtm-py-all/UI/views/dut_form_dialog.py

254 lines
9.6 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.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
DUT表单对话框全局复用
- 新建/编辑公用一个对话框,根据模式禁用部分字段
- 数据以 dict(dut_form) 形式在模块间传递
- 设备分配为二级选择:机台 -> 通道
"""
from PyQt5.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QFormLayout, QLineEdit, QComboBox,
QTextEdit, QPushButton, QLabel, QWidget
)
from PyQt5.QtCore import Qt
class DUTFormDialog(QDialog):
def __init__(self, mode="create", dut_form=None, lock_fields=None, system_model=None, parent=None):
super().__init__(parent)
self.mode = mode # "create" | "edit"
self.dut_form = dut_form or {}
self.lock_fields = set(lock_fields or [])
self.system_model = system_model # 用于加载机台数据
self.setWindowTitle("编辑试验样品详情" if self.mode == "edit" else "新建试验样品")
self.setModal(True)
self.resize(800, 480)
# 机台数据缓存
self.machines = []
self.current_machine = None
self._build_ui()
self._load_machines() # 加载机台数据
self._fill_form(self.dut_form)
self._apply_lock()
def _build_ui(self):
layout = QVBoxLayout(self)
layout.setContentsMargins(20, 20, 20, 20)
layout.setSpacing(12)
#title = QLabel("编辑试验样品详情" if self.mode == "edit" else "新建试验样品详情")
#title.setObjectName("title")
#title.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
#layout.addWidget(title)
form = QFormLayout()
form.setLabelAlignment(Qt.AlignRight)
form.setFormAlignment(Qt.AlignTop)
form.setHorizontalSpacing(16)
form.setVerticalSpacing(12)
# 左右两列容器
row = QHBoxLayout()
left = QVBoxLayout()
right = QVBoxLayout()
# 左列控件
self.input_SN = QLineEdit()
self.input_project = QLineEdit()
self.input_testReq = QLineEdit()
self.input_phase = QComboBox()
self.input_phase.setEditable(True)
self.input_phase.addItems(["A Sample", "B Sample", "C Sample", "Work Sample", "阶段1", "阶段2"]) # 示例项
# 右列控件 - 设备分配(二级选择)
self.input_dtMachine = QComboBox() # 机台选择
self.input_dtMachine.setEditable(False)
self.input_dtMachine.addItem("", None) # 空选项
self.input_dtMachine.currentIndexChanged.connect(self._on_machine_changed)
self.input_station = QComboBox() # 通道选择
self.input_station.setEditable(False)
self.input_station.addItem("", None) # 空选项
self.input_weeks = QLineEdit()
self.input_workOrder = QLineEdit()
self.input_inspector = QLineEdit()
# 说明
self.input_description = QTextEdit()
self.input_description.setPlaceholderText("请输入内容")
# 左列布局
left_form = QFormLayout()
left_form.setLabelAlignment(Qt.AlignRight)
left_form.addRow("* 产品序列号", self.input_SN)
left_form.addRow("项目代码", self.input_project)
left_form.addRow("项目方案", self.input_testReq)
left_form.addRow("项目阶段", self.input_phase)
left.addLayout(left_form)
# 右列布局
right_form = QFormLayout()
right_form.setLabelAlignment(Qt.AlignRight)
right_form.addRow("机台选择", self.input_dtMachine)
right_form.addRow("通道选择", self.input_station)
right_form.addRow("测试周次", self.input_weeks)
right_form.addRow("工单名称", self.input_workOrder)
right_form.addRow("测试人员", self.input_inspector)
right.addLayout(right_form)
row.addLayout(left, 1)
row.addLayout(right, 1)
layout.addLayout(row)
# 说明一行单独处理
desc_form = QFormLayout()
desc_form.setLabelAlignment(Qt.AlignRight)
desc_form.addRow("说明", self.input_description)
layout.addLayout(desc_form)
# 底部按钮
btn_row = QHBoxLayout()
btn_row.addStretch()
self.btn_submit = QPushButton("修改" if self.mode == "edit" else "保存")
self.btn_close = QPushButton("关闭")
btn_row.addWidget(self.btn_submit)
btn_row.addWidget(self.btn_close)
layout.addLayout(btn_row)
self.btn_submit.clicked.connect(self.accept)
self.btn_close.clicked.connect(self.reject)
def _load_machines(self):
"""加载机台数据"""
if not self.system_model:
return
try:
self.machines = self.system_model.load_machines()
# 填充机台下拉框
self.input_dtMachine.clear()
self.input_dtMachine.addItem("", None) # 空选项
for machine in self.machines:
sn = machine.get("SN", "")
label = machine.get("label", "")
display = f"{sn} - {label}" if label else sn
self.input_dtMachine.addItem(display, machine)
except Exception as e:
print(f"加载机台数据失败: {e}")
def _on_machine_changed(self, index):
"""机台选择变化时更新通道列表"""
self.input_station.clear()
self.input_station.addItem("", None) # 空选项
machine = self.input_dtMachine.currentData()
if not machine:
return
self.current_machine = machine
# 添加有效的通道station1-4
for i in range(1, 5):
station_key = f"station{i}"
status_key = f"status{i}"
try:
# 安全获取通道名称处理None和空值
station_name = machine.get(station_key)
if station_name is None:
continue
station_name = str(station_name).strip()
station_status = machine.get(status_key, "")
# 过滤掉空值和 NA/N/A 的通道
if station_name and station_name.upper() not in ['NA', 'N/A']:
display = f"{i:02d} - {station_name}"
if station_status:
display += f" ({station_status})"
self.input_station.addItem(display, f"{i:02d}")
except Exception as e:
print(f"加载通道数据失败: {e}")
def _fill_form(self, f):
# 将已有数据填充到控件
self.input_SN.setText(str(f.get("SN", "")))
self.input_project.setText(str(f.get("project", "")))
self.input_testReq.setText(str(f.get("testReq", "")))
phase_val = str(f.get("phase", ""))
if phase_val:
idx = self.input_phase.findText(phase_val)
if idx >= 0:
self.input_phase.setCurrentIndex(idx)
else:
self.input_phase.setEditText(phase_val)
# 设备分配:使用 Model 解析后的 dtMachine 和 station 字段
dtm = f.get("dtMachine", "").strip()
station = f.get("station", "").strip()
# 选中机台
if dtm:
for i in range(self.input_dtMachine.count()):
machine = self.input_dtMachine.itemData(i)
if machine and machine.get("SN") == dtm:
self.input_dtMachine.setCurrentIndex(i)
break
# 选中通道(需要在机台选中后)
if station:
for i in range(self.input_station.count()):
station_num = self.input_station.itemData(i)
if station_num == station:
self.input_station.setCurrentIndex(i)
break
self.input_weeks.setText(str(f.get("weeks", "")))
self.input_workOrder.setText(str(f.get("workOrder", "")))
self.input_inspector.setText(str(f.get("inspector", "")))
self.input_description.setPlainText(str(f.get("description", "")))
def _apply_lock(self):
# 根据锁定字段禁用编辑(默认在编辑模式锁定 SN
defaults = {"SN"} if self.mode == "edit" else set()
locked = defaults | self.lock_fields
if "SN" in locked:
self.input_SN.setDisabled(True)
# 注意:设备分配在编辑模式下是可以更改的
def get_form_dict(self):
# 以 dut_form 的结构返回数据
dut_form = {
"SN": self.input_SN.text().strip(),
"project": self.input_project.text().strip(),
"testReq": self.input_testReq.text().strip(),
"phase": self.input_phase.currentText().strip(),
"weeks": int(self.input_weeks.text() or 0),
"workOrder": self.input_workOrder.text().strip(),
"inspector": self.input_inspector.text().strip(),
"description": self.input_description.toPlainText().strip(),
}
# 设备分配:从二级选择中获取 dtMachine 和 station
# Model 会自动将这两个字段合成为 JSON 字符串存入 stationAssigned
machine = self.input_dtMachine.currentData()
station_num = self.input_station.currentData()
if machine and station_num:
dut_form["dtMachine"] = machine.get("SN", "")
dut_form["station"] = station_num
else:
dut_form["dtMachine"] = ""
dut_form["station"] = ""
# 保留可能存在的 id 等字段
if "id" in self.dut_form:
dut_form["id"] = self.dut_form["id"]
return dut_form