Files
visual-vue-v1/generate_pdf.py
2026-07-26 19:46:02 +08:00

180 lines
4.9 KiB
Python

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, PageBreak
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.colors import HexColor
import os
import json
import re
# 注册中文字体
try:
pdfmetrics.registerFont(TTFont('SimSun', '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc', subfontIndex=0))
pdfmetrics.registerFont(TTFont('SimHei', '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc', subfontIndex=0))
print("Chinese fonts loaded successfully")
except Exception as e:
print(f"Warning: Could not load Chinese font: {e}")
SimSun = 'Helvetica'
SimHei = 'Helvetica-Bold'
# 创建样式
styles = getSampleStyleSheet()
# 标题样式
title_style = ParagraphStyle(
'CustomTitle',
parent=styles['Heading1'],
fontName='Helvetica-Bold',
fontSize=24,
leading=30,
alignment=TA_CENTER,
spaceAfter=20,
textColor=HexColor('#1a1e24')
)
# 章节标题样式
h1_style = ParagraphStyle(
'CustomH1',
parent=styles['Heading1'],
fontName='SimHei',
fontSize=18,
leading=24,
spaceBefore=20,
spaceAfter=12,
textColor=HexColor('#3B6D8A')
)
# 子章节标题样式
h2_style = ParagraphStyle(
'CustomH2',
parent=styles['Heading2'],
fontName='SimHei',
fontSize=14,
leading=18,
spaceBefore=15,
spaceAfter=8,
textColor=HexColor('#2C2C30')
)
# 正文样式
body_style = ParagraphStyle(
'CustomBody',
parent=styles['BodyText'],
fontName='SimSun',
fontSize=10.5,
leading=16,
alignment=TA_JUSTIFY,
spaceBefore=6,
spaceAfter=6,
firstLineIndent=24,
textColor=HexColor('#2C2C30')
)
# 列表样式
bullet_style = ParagraphStyle(
'CustomBullet',
parent=styles['BodyText'],
fontName='SimSun',
fontSize=10.5,
leading=16,
leftIndent=36,
bulletIndent=18,
spaceBefore=3,
spaceAfter=3,
textColor=HexColor('#2C2C30')
)
# 图片说明样式
caption_style = ParagraphStyle(
'Caption',
parent=styles['BodyText'],
fontName='SimSun',
fontSize=9,
leading=12,
alignment=TA_CENTER,
spaceBefore=6,
spaceAfter=12,
textColor=HexColor('#7A7A84')
)
# 创建PDF文档
output_path = '/Users/chenxuan/Documents/CODE/visual-html./docs/软件说明书_v2.pdf'
doc = SimpleDocTemplate(
output_path,
pagesize=A4,
rightMargin=2.79*cm,
leftMargin=2.79*cm,
topMargin=2.79*cm,
bottomMargin=2.5*cm
)
# 读取content.json
content_file = '/Users/chenxuan/Documents/CODE/visual-html./.dumate/pdf-软件说明书-20260726-a4e67093/content.json'
with open(content_file, 'r', encoding='utf-8') as f:
content = json.load(f)
# 构建文档内容
story = []
# 添加封面
cover_title = Paragraph("可视化大屏模板系统<br/>软件说明书", title_style)
story.append(Spacer(1, 100))
story.append(cover_title)
story.append(Spacer(1, 30))
# 版本信息
cover_info = Paragraph("<b>版本号:V1.0</b><br/>开发完成日期:2026年7月", ParagraphStyle(
'CoverInfo',
parent=body_style,
alignment=TA_CENTER,
fontSize=12,
spaceBefore=20
))
story.append(cover_info)
story.append(PageBreak())
# 处理内容块
image_counter = 0
for block in content:
block_type = block.get('type', '')
if block_type == 'h2':
text = block.get('text', '').replace('<b>', '').replace('</b>', '')
story.append(Paragraph(text, h1_style))
elif block_type == 'h3':
text = block.get('text', '').replace('<b>', '').replace('</b>', '')
story.append(Paragraph(text, h2_style))
elif block_type == 'body':
text = block.get('text', '')
# 移除HTML标签
text = re.sub(r'<[^>]+>', '', text)
if text.strip():
story.append(Paragraph(text, body_style))
elif block_type == 'bullet':
text = block.get('text', '')
text = re.sub(r'<[^>]+>', '', text)
story.append(Paragraph('• ' + text, bullet_style))
elif block_type == 'figure':
image_path = block.get('path', '')
caption = block.get('caption', '')
if image_path and os.path.exists(image_path):
try:
img = Image(image_path, width=16*cm, height=9*cm)
img.hAlign = 'CENTER'
story.append(Spacer(1, 12))
story.append(img)
if caption:
image_counter += 1
story.append(Paragraph(f"图 {image_counter}: {caption}", caption_style))
story.append(Spacer(1, 12))
except Exception as e:
print(f"Error adding image {image_path}: {e}")
# 生成PDF
doc.build(story)
print(f"PDF生成成功: {output_path}")
print(f"共插入 {image_counter} 张图片")