gwdoc/tools/pdf_generator.py

183 lines
5.1 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 生成工具模块
使用 Pandoc 将 Markdown 文本转换为 PDF 文件
"""
import os
import base64
import subprocess
import tempfile
from datetime import datetime
class PDFGenerator:
"""PDF 生成器类Pandoc 版)"""
def __init__(self, main_font: str = "Noto Serif CJK SC"):
"""
初始化 PDF 生成器
Args:
main_font: Pandoc / XeLaTeX 使用的中文字体名
"""
self.main_font = main_font
def generate_pdf_from_text(
self,
text_content: str,
output_path: str = None,
title: str = "维修报告",
return_base64: bool = True
) -> dict:
"""
将 Markdown 文本内容生成 PDF 文件(方法名不变)
Args:
text_content: Markdown 文本内容
output_path: PDF 输出路径(可选)
title: PDF 标题
return_base64: 是否返回 base64 编码内容
"""
try:
# 输出路径
if output_path is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_path = f"temp_report_{timestamp}.pdf"
# 生成临时 Markdown 文件
with tempfile.NamedTemporaryFile(
mode="w",
suffix=".md",
delete=False,
encoding="utf-8"
) as md_file:
md_path = md_file.name
# 写入标题 + 内容Pandoc 标准)
if title:
md_file.write(f"# {title}\n\n")
md_file.write(text_content.strip())
# Pandoc 命令
cmd = [
"pandoc",
md_path,
"--pdf-engine=xelatex",
"-V", f"mainfont={self.main_font}",
"-o", output_path
]
# 执行转换
subprocess.run(
cmd,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
result = {
"success": True,
"file_path": output_path
}
# 返回 base64
if return_base64:
with open(output_path, "rb") as f:
result["base64_content"] = base64.b64encode(
f.read()
).decode("utf-8")
return result
except subprocess.CalledProcessError as e:
return {
"success": False,
"error": e.stderr.decode("utf-8")
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
finally:
# 清理临时 md 文件
if "md_path" in locals() and os.path.exists(md_path):
os.remove(md_path)
def generate_report_pdf(
report_content: str,
device_name: str = "未知设备",
output_dir: str = None
) -> dict:
"""
生成维修报告 PDF方法名不变
"""
generator = PDFGenerator()
# 文件名规则不变
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
safe_device_name = device_name.replace(" ", "_").replace("/", "_")
file_name = f"{safe_device_name}_维修报告_{timestamp}.pdf"
if output_dir:
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, file_name)
else:
output_path = file_name
result = generator.generate_pdf_from_text(
text_content=report_content,
output_path=output_path,
title="设备维修报告",
return_base64=True
)
if result.get("success"):
result["file_name"] = file_name
return result
# 测试代码
if __name__ == "__main__":
test_md = """
爱因斯坦质能方程:
$$E = mc^2$$
该公式揭示了质量与能量的等价性。在核反应中,微小的质量亏损 $\Delta m$ 会释放巨大能量:
$$\Delta E = \Delta m \cdot c^2$$
其中 $c = 3 \times 10^8 \, \text{m/s}$ 为真空光速。
## 实验数据对比
下表展示了不同材料在相同条件下的能量释放效率:
| 材料类型 | 质量亏损 (kg) | 释放能量 (J) | 能量密度 (J/kg) |
|------------|----------------|---------------------|----------------------|
| 铀-235 | $1.0 \times 10^{-3}$ | $9.0 \times 10^{13}$ | $9.0 \times 10^{16}$ |
| 氘氚聚变 | $3.1 \times 10^{-3}$ | $2.8 \times 10^{14}$ | $9.0 \times 10^{16}$ |
| 化学燃烧 | $1.0 \times 10^{-3}$ | $3.0 \times 10^{4}$ | $3.0 \times 10^{7}$ |
## 结论
- 核反应的能量密度远高于化学反应(约 $10^9$ 倍)。
- 公式 $a^2 + b^2 = c^2$ 虽为几何关系,但在相对论四维时空中有深刻类比。
"""
result = generate_report_pdf(
test_md,
device_name="测试设备"
)
if result["success"]:
print(f"✓ PDF 生成成功:{result['file_name']}")
print(f"✓ 文件路径:{result['file_path']}")
print(f"✓ Base64 长度:{len(result['base64_content'])}")
else:
print(f"✗ PDF 生成失败:{result['error']}")