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("可视化大屏模板系统
软件说明书", title_style) story.append(Spacer(1, 100)) story.append(cover_title) story.append(Spacer(1, 30)) # 版本信息 cover_info = Paragraph("版本号:V1.0
开发完成日期: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('', '').replace('', '') story.append(Paragraph(text, h1_style)) elif block_type == 'h3': text = block.get('text', '').replace('', '').replace('', '') 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} 张图片")