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}")