添加API服务模块
This commit is contained in:
107
api/services/pdf_service.py
Normal file
107
api/services/pdf_service.py
Normal file
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
PDF 生成服务
|
||||
"""
|
||||
from typing import List
|
||||
from reportlab.lib.pagesizes import letter, A4
|
||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||
from reportlab.lib.units import inch
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
|
||||
from io import BytesIO
|
||||
import os
|
||||
|
||||
|
||||
class PDFService:
|
||||
"""PDF 生成服务"""
|
||||
|
||||
def __init__(self):
|
||||
# 尝试注册中文字体
|
||||
try:
|
||||
# 使用系统字体或 ReportLab 内置的中文字体
|
||||
# 如果没有中文字体文件,使用 UnicodeCIDFont
|
||||
pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
|
||||
self.chinese_font = 'STSong-Light'
|
||||
except Exception:
|
||||
# 如果注册失败,使用默认字体(可能不支持中文)
|
||||
self.chinese_font = 'Helvetica'
|
||||
|
||||
async def generate_pdf(self, book, chapters: List) -> bytes:
|
||||
"""
|
||||
生成 PDF
|
||||
|
||||
Args:
|
||||
book: 回忆录对象
|
||||
chapters: 章节列表
|
||||
|
||||
Returns:
|
||||
PDF 字节数据
|
||||
"""
|
||||
buffer = BytesIO()
|
||||
doc = SimpleDocTemplate(buffer, pagesize=A4)
|
||||
|
||||
# 创建样式
|
||||
styles = getSampleStyleSheet()
|
||||
title_style = ParagraphStyle(
|
||||
'CustomTitle',
|
||||
parent=styles['Heading1'],
|
||||
fontSize=24,
|
||||
spaceAfter=30,
|
||||
alignment=1, # 居中
|
||||
fontName=self.chinese_font
|
||||
)
|
||||
|
||||
heading_style = ParagraphStyle(
|
||||
'CustomHeading',
|
||||
parent=styles['Heading1'],
|
||||
fontSize=18,
|
||||
spaceAfter=12,
|
||||
fontName=self.chinese_font
|
||||
)
|
||||
|
||||
normal_style = ParagraphStyle(
|
||||
'CustomNormal',
|
||||
parent=styles['Normal'],
|
||||
fontSize=12,
|
||||
leading=18,
|
||||
fontName=self.chinese_font
|
||||
)
|
||||
|
||||
# 构建内容
|
||||
story = []
|
||||
|
||||
# 封面
|
||||
story.append(Paragraph(book.title, title_style))
|
||||
story.append(Spacer(1, 0.5*inch))
|
||||
story.append(PageBreak())
|
||||
|
||||
# 目录
|
||||
story.append(Paragraph("目录", heading_style))
|
||||
story.append(Spacer(1, 0.2*inch))
|
||||
for i, chapter in enumerate(chapters, 1):
|
||||
story.append(Paragraph(f"{i}. {chapter.title}", normal_style))
|
||||
story.append(PageBreak())
|
||||
|
||||
# 章节内容
|
||||
for chapter in chapters:
|
||||
story.append(Paragraph(chapter.title, heading_style))
|
||||
story.append(Spacer(1, 0.2*inch))
|
||||
|
||||
# 分段处理内容
|
||||
paragraphs = chapter.content.split('\n\n')
|
||||
for para in paragraphs:
|
||||
if para.strip():
|
||||
story.append(Paragraph(para.strip(), normal_style))
|
||||
story.append(Spacer(1, 0.1*inch))
|
||||
|
||||
story.append(PageBreak())
|
||||
|
||||
# 生成 PDF
|
||||
doc.build(story)
|
||||
buffer.seek(0)
|
||||
return buffer.read()
|
||||
|
||||
|
||||
# 全局实例
|
||||
pdf_service = PDFService()
|
||||
Reference in New Issue
Block a user