Files
WareShipManifest/core/printing.py
Misaka_Company bf9199189a Add HTTP print API for packing list and sign-off receipt
- core/printing.py: SumatraPDF silent print backend (dry_run, timeout, error capture)
- core/print_document.py: orchestrate generate() + print, per-report paper size, printer fallback
- core/print_api.py: FastAPI POST /api/print + GET /api/health, HTTPBearer auth, English Swagger at /api/docs
- serve.py: uvicorn entrypoint
- config: printers/print/api sections in settings.yaml + core/settings.py
- requirements.txt: add fastapi, uvicorn
- .gitignore: ignore logs/
2026-08-05 16:22:59 +08:00

65 lines
2.0 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.
"""打印后端:把已生成的 PDF 静默送到物理/网络打印机。
MVP 使用 SumatraPDF 命令行打印(轻量、支持 -print-to 指定打印机与纸张,
配合 -silent 适合服务端无人值守打印)。
"""
from __future__ import annotations
import subprocess
from pathlib import Path
def build_command(
sumatrapdf_path: str, printer: str, settings: str, pdf_path: str
) -> list[str]:
"""构造 SumatraPDF 打印命令。"""
return [
sumatrapdf_path,
"-print-to",
printer,
"-print-settings",
settings,
"-silent",
pdf_path,
]
def print_pdf(
pdf_path: str | Path,
printer: str,
settings: str = "paper=A4,orientation=portrait,color=bw",
sumatrapdf_path: str = "C:/Program Files/SumatraPDF/SumatraPDF.exe",
timeout: int = 60,
dry_run: bool = False,
) -> dict:
"""调用 SumatraPDF 把 PDF 静默打印到指定打印机。
返回结构化结果dry_run=True 时只构造命令并上报,不真正执行(用于验证链路)。
"""
pdf_path = str(pdf_path)
cmd = build_command(sumatrapdf_path, printer, settings, pdf_path)
result: dict = {
"printer": printer,
"pdf": pdf_path,
"command": cmd,
"dry_run": dry_run,
}
if dry_run:
result["ok"] = True
result["note"] = "dry_run: command constructed, not executed"
return result
try:
proc = subprocess.run(
cmd, capture_output=True, text=True, timeout=timeout, check=False
)
result["returncode"] = proc.returncode
result["stdout"] = proc.stdout
result["stderr"] = proc.stderr
result["ok"] = proc.returncode == 0
if proc.returncode != 0:
result["error"] = (proc.stderr or proc.stdout or "unknown error").strip()
except subprocess.TimeoutExpired:
result["ok"] = False
result["error"] = f"print timeout after {timeout}s"
return result