certflow.views.print_dialog 源代码

"""打印预览对话框

提供合格证打印前的预览和确认打印功能。使用 QPainter 绘制预览位图
(C2 去 Chromium),支持图片导出。

从 certificate_printer v2.0 移植,整合到 CertFlow 架构中。
"""

from __future__ import annotations

from typing import Any

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QDialog,
    QHBoxLayout,
    QLabel,
    QPushButton,
    QSpinBox,
    QVBoxLayout,
)

from certflow.utils.logger import logger


[文档] class PrintPreviewDialog(QDialog): """打印预览对话框 显示合格证预览位图,支持打印、图片导出和关闭操作。 Attributes: data: 打印数据字典 serial_number: 当前预览的产品编号 copies: 打印份数 """ def __init__( self, data: dict[str, Any], serial_number: str = "预览编号", template_key: str = "full_chinese_3", parent: QDialog | None = None, ) -> None: """初始化PrintPreviewDialog。 Args: data: 数据 serial_number: serial_number 参数 template_key: TemplateManager 模板键(决定坐标与语言族) parent: 父控件(可选) Returns: None """ super().__init__(parent) self.data = data self.serial_number = serial_number self.template_key = template_key self.copies = 1 self._result: bool = False # 用户是否点击了打印 self.setup_ui() self.load_preview() @property def result(self) -> bool: """用户是否确认打印""" return self._result
[文档] def setup_ui(self) -> None: """构建 UI""" self.setWindowTitle("打印预览 - 合格证打印管理系统") self.setMinimumSize(500, 700) self.resize(550, 800) layout = QVBoxLayout(self) layout.setContentsMargins(8, 8, 8, 8) layout.setSpacing(6) # 标题 title_label = QLabel(f"产品编号: {self.serial_number}") title_label.setAlignment(Qt.AlignmentFlag.AlignCenter) title_label.setStyleSheet("font-size: 14px; font-weight: bold; padding: 4px;") layout.addWidget(title_label) # 预览区域(单一 QLabel,由 QPainter 绘制,C2 去 Chromium) self.preview_label = QLabel() self.preview_label.setMinimumHeight(500) self.preview_label.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft) layout.addWidget(self.preview_label, stretch=1) # 按钮区域 button_layout = QHBoxLayout() button_layout.setSpacing(8) # 份数选择 copies_label = QLabel("份数:") button_layout.addWidget(copies_label) self.copies_spin = QSpinBox() self.copies_spin.setMinimum(1) self.copies_spin.setMaximum(99) self.copies_spin.setValue(1) self.copies_spin.valueChanged.connect(self._on_copies_changed) button_layout.addWidget(self.copies_spin) button_layout.addStretch() self.image_btn = QPushButton("导出图片") self.image_btn.clicked.connect(self._export_image) button_layout.addWidget(self.image_btn) self.print_btn = QPushButton("打印") self.print_btn.setStyleSheet( "QPushButton { background-color: #0078d4; color: white; " "padding: 6px 20px; font-weight: bold; }" "QPushButton:hover { background-color: #106ebe; }" ) self.print_btn.clicked.connect(self._do_print) button_layout.addWidget(self.print_btn) self.close_btn = QPushButton("关闭") self.close_btn.clicked.connect(self.reject) button_layout.addWidget(self.close_btn) layout.addLayout(button_layout)
[文档] def load_preview(self) -> None: """用 QPainter 绘制预览(替代 Chromium HTML 渲染)""" from certflow.views.certificate_preview_painter import render_certificate_pixmap pixmap = render_certificate_pixmap( self.data, self.serial_number, self.template_key, show_labels=True, paper_w_mm=60.0, paper_h_mm=100.0, preview_w_px=400, label_x_mm=8.0, bg_show=None, ) self.preview_label.setPixmap(pixmap) self.preview_label.setFixedSize(pixmap.size())
def _on_copies_changed(self, value: int) -> None: """份数变化""" self.copies = value def _do_print(self) -> None: """确认打印""" self._result = True self.accept() def _export_image(self) -> None: """导出预览图片(PNG,替代 Chromium PDF 导出)""" from PySide6.QtWidgets import QFileDialog pix = self.preview_label.pixmap() if not pix: return file_path, _ = QFileDialog.getSaveFileName( self, "导出图片", f"合格证_{self.serial_number}.png", "PNG 图片 (*.png)", ) if file_path: try: pix.save(file_path, "PNG") logger.info(f"图片已导出: {file_path}") except Exception as e: logger.error(f"图片导出失败: {e}")