certflow.views.param_supplement_dialog 源代码

"""参数补充对话框

对标 VBA print.vb 中的 InputBox 交互式参数补充逻辑:
- 口径 (DN) 补充 → 对标 确认口径() InputBox
- 压力 (PN) 补充 → 对标 确认压力() InputBox
- 温度补充 → 对标 print.vb 第659-664行
- 介质补充 → 对标 print.vb 第740-748行
- 材质补充 → 对标 print.vb 的 FaTiCaiZhi/FaGanCaiZhi/QiBiJianCaiZhi

v2.0 新增:
    - 完整的 PySide6 对话框替代 VBA InputBox
    - 下拉选项(材质牌号从 SQLite 读取)
    - 自动预填已有值
    - 支持批量跳过(一键全部留空)
"""

from __future__ import annotations

from typing import Any

from PySide6.QtCore import Signal
from PySide6.QtWidgets import (
    QComboBox,
    QDialog,
    QDialogButtonBox,
    QFormLayout,
    QGroupBox,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QPushButton,
    QVBoxLayout,
    QWidget,
)


[文档] class ParamSupplementDialog(QDialog): """参数补充对话框 对标 VBA print.vb 批量打印时的一连串 InputBox 交互: 1. 口径 InputBox(第635/671行) 2. 压力 InputBox(第651/703行) 3. 温度 InputBox(第660/716行) 4. 介质 InputBox(第741行) Attributes: params: 用户填写的参数字典 confirmed: 用户是否点击了"确认" skip_all: 用户是否点击了"跳过全部" """ # 信号:确认补充完成 supplement_confirmed = Signal(dict) def __init__( self, model: str = "", prefill: dict[str, Any] | None = None, material_grades: dict[str, list[str]] | None = None, parent: QWidget | None = None, ) -> None: """初始化参数补充对话框 Args: model: 当前产品型号,用于标题显示 prefill: 预填参数字典,键名: - caliber: 口径 - pressure: 压力 - temperature: 温度 - medium: 介质 - test_standard: 试压标准 - inspector_id: 检验工号 - body_material: 阀体材质 - stem_material: 阀杆材质 - disc_material: 启闭件材质 material_grades: 材质牌号字典 {分类: [牌号列表]} 分类: "body" / "stem" / "disc" / "common" parent: 父窗口 """ super().__init__(parent) self.model = model self.prefill = prefill or {} self.material_grades = material_grades or {} self._confirmed: bool = False self._skip_all: bool = False self.setup_ui() self.load_prefill() @property def confirmed(self) -> bool: """用户是否确认""" return self._confirmed @property def skip_all(self) -> bool: """用户是否跳过全部(留空)""" return self._skip_all @property def params(self) -> dict[str, str]: """获取用户填写的参数""" return { "caliber": self.caliber_input.text().strip(), "pressure": self.pressure_input.text().strip(), "temperature": self.temperature_input.text().strip(), "medium": self.medium_input.text().strip(), "test_standard": self.standard_input.text().strip(), "inspector_id": self.inspector_input.text().strip(), "body_material": self.body_material_combo.currentText().strip(), "stem_material": self.stem_material_combo.currentText().strip(), "disc_material": self.disc_material_combo.currentText().strip(), } # ============================================================ # UI 构建 # ============================================================
[文档] def setup_ui(self) -> None: """构建对话框 UI""" title = f"参数补充 - {self.model}" if self.model else "参数补充" self.setWindowTitle(title) self.setMinimumWidth(480) self.resize(520, 560) main_layout = QVBoxLayout(self) main_layout.setContentsMargins(12, 12, 12, 12) main_layout.setSpacing(10) # 标题提示 title_label = QLabel( f"产品型号:<b>{self.model}</b>\n以下参数缺失或需确认,请补充后继续打印:" ) title_label.setWordWrap(True) title_label.setStyleSheet("font-size: 12px; padding: 4px;") main_layout.addWidget(title_label) # === 基本参数组 === basic_group = QGroupBox("基本参数") basic_layout = QFormLayout(basic_group) basic_layout.setSpacing(6) # 公称通径 (DN) self.caliber_input = QLineEdit() self.caliber_input.setPlaceholderText("如 DN100, 150") basic_layout.addRow("公称通径 (DN):", self.caliber_input) # 公称压力 (PN) self.pressure_input = QLineEdit() self.pressure_input.setPlaceholderText("如 2.5, 150Lb, 2.5MPa") basic_layout.addRow("公称压力 (PN):", self.pressure_input) # 工作温度 self.temperature_input = QLineEdit() self.temperature_input.setPlaceholderText("如 ≤425℃, 常温") basic_layout.addRow("工作温度:", self.temperature_input) # 适用介质 self.medium_input = QLineEdit() self.medium_input.setPlaceholderText("如 水、蒸汽、油品") basic_layout.addRow("适用介质:", self.medium_input) main_layout.addWidget(basic_group) # === 检验参数组 === inspect_group = QGroupBox("检验参数") inspect_layout = QFormLayout(inspect_group) inspect_layout.setSpacing(6) # 试压标准 self.standard_input = QLineEdit() self.standard_input.setPlaceholderText("如 GB/T 13927-2008") inspect_layout.addRow("试压标准:", self.standard_input) # 检验工号 self.inspector_input = QLineEdit() self.inspector_input.setPlaceholderText("检验员工号") inspect_layout.addRow("检验工号:", self.inspector_input) main_layout.addWidget(inspect_group) # === 材质参数组 === material_group = QGroupBox("材质参数") material_layout = QFormLayout(material_group) material_layout.setSpacing(6) # 阀体材质 self.body_material_combo = self._create_material_combo("body") material_layout.addRow("阀体材质:", self.body_material_combo) # 阀杆材质 self.stem_material_combo = self._create_material_combo("stem") material_layout.addRow("阀杆材质:", self.stem_material_combo) # 启闭件材质 self.disc_material_combo = self._create_material_combo("disc") material_layout.addRow("启闭件材质:", self.disc_material_combo) main_layout.addWidget(material_group) # === 按钮区域 === button_layout = QHBoxLayout() button_layout.setSpacing(8) # 跳过全部按钮 self.skip_btn = QPushButton("跳过全部(留空)") self.skip_btn.setToolTip("所有参数留空,继续打印") self.skip_btn.clicked.connect(self._on_skip_all) button_layout.addWidget(self.skip_btn) button_layout.addStretch() # 确认/取消 self.button_box = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel ) self.button_box.button(QDialogButtonBox.StandardButton.Ok).setText("确认并打印") self.button_box.button(QDialogButtonBox.StandardButton.Cancel).setText("取消") self.button_box.accepted.connect(self._on_confirm) self.button_box.rejected.connect(self.reject) button_layout.addWidget(self.button_box) main_layout.addLayout(button_layout)
def _create_material_combo(self, category: str) -> QComboBox: """创建材质下拉框(可编辑) Args: category: 材质分类 (body/stem/disc) Returns: QComboBox: 可编辑下拉框 """ combo = QComboBox() combo.setEditable(True) combo.setInsertPolicy(QComboBox.InsertPolicy.NoInsert) # 从预置数据填充 grades = self.material_grades.get(category, []) # 也添加 common 通用材质 common_grades = self.material_grades.get("common", []) all_grades = sorted(set(grades + common_grades)) combo.addItem("") # 空选项 for grade in all_grades: combo.addItem(grade) return combo # ============================================================ # 预填数据 # ============================================================
[文档] def load_prefill(self) -> None: """加载预填数据""" prefill = self.prefill # 基本参数 self._set_text_if(self.caliber_input, prefill.get("caliber")) self._set_text_if(self.pressure_input, prefill.get("pressure")) self._set_text_if(self.temperature_input, prefill.get("temperature")) self._set_text_if(self.medium_input, prefill.get("medium")) # 检验参数 self._set_text_if(self.standard_input, prefill.get("test_standard")) self._set_text_if(self.inspector_input, prefill.get("inspector_id")) # 材质(可编辑下拉框) self._set_combo(self.body_material_combo, prefill.get("body_material")) self._set_combo(self.stem_material_combo, prefill.get("stem_material")) self._set_combo(self.disc_material_combo, prefill.get("disc_material")) # 自动聚焦第一个空字段 self._focus_first_empty()
@staticmethod def _set_text_if(widget: QLineEdit, value: Any) -> None: if value: widget.setText(str(value)) @staticmethod def _set_combo(combo: QComboBox, value: Any) -> None: if value: idx = combo.findText(str(value)) if idx >= 0: combo.setCurrentIndex(idx) else: combo.setEditText(str(value)) def _focus_first_empty(self) -> None: if not self.caliber_input.text(): self.caliber_input.setFocus() elif not self.pressure_input.text(): self.pressure_input.setFocus() else: self.caliber_input.setFocus() # ============================================================ # 事件处理 # ============================================================ def _on_confirm(self) -> None: """确认按钮点击""" self._confirmed = True self.accept() def _on_skip_all(self) -> None: """跳过全部(留空)""" self._skip_all = True self._confirmed = True # 也算确认(只是参数为空) self.accept() # ============================================================ # 静态工厂方法 # ============================================================
[文档] @staticmethod def get_parameters( model: str = "", prefill: dict[str, Any] | None = None, material_grades: dict[str, list[str]] | None = None, parent: QWidget | None = None, ) -> tuple[bool, bool, dict[str, str]]: """弹出参数补充对话框并返回结果 对标 VBA 的 InputBox 调用模式,提供便捷的静态方法。 Args: model: 产品型号 prefill: 预填参数 material_grades: 材质牌号选项 parent: 父窗口 Returns: (confirmed, skip_all, params) 元组 - confirmed: 用户是否确认(含跳过) - skip_all: 是否跳过全部留空 - params: 填写的参数字典 """ dialog = ParamSupplementDialog( model=model, prefill=prefill, material_grades=material_grades, parent=parent, ) dialog.exec() return dialog.confirmed, dialog.skip_all, dialog.params