from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor import io def create_ppt(title: str, slides_data: list, template_style: str = "商务") -> bytes: """创建PPT""" prs = Presentation() # 设置模板颜色 colors = get_template_colors(template_style) # 添加标题页 add_title_slide(prs, title, colors) # 添加内容页 for slide_data in slides_data: add_content_slide(prs, slide_data, colors) # 保存到内存 buffer = io.BytesIO() prs.save(buffer) return buffer.getvalue() def get_template_colors(style: str) -> dict: """获取模板颜色""" templates = { "商务": { "primary": RGBColor(0, 82, 136), # 深蓝 "secondary": RGBColor(0, 120, 215), # 蓝色 "accent": RGBColor(255, 185, 0), # 金色 "text": RGBColor(51, 51, 51), # 深灰 "background": RGBColor(255, 255, 255) # 白色 }, "科技": { "primary": RGBColor(88, 86, 214), # 紫色 "secondary": RGBColor(0, 200, 150), # 青色 "accent": RGBColor(255, 100, 100), # 红色 "text": RGBColor(30, 30, 30), # 近黑 "background": RGBColor(245, 245, 250) # 浅灰蓝 }, "教育": { "primary": RGBColor(46, 139, 87), # 绿色 "secondary": RGBColor(70, 130, 180), # 钢蓝 "accent": RGBColor(255, 165, 0), # 橙色 "text": RGBColor(51, 51, 51), # 深灰 "background": RGBColor(255, 255, 255) # 白色 }, "简约": { "primary": RGBColor(60, 60, 60), # 深灰 "secondary": RGBColor(120, 120, 120), # 中灰 "accent": RGBColor(200, 50, 50), # 红色 "text": RGBColor(51, 51, 51), # 深灰 "background": RGBColor(255, 255, 255) # 白色 } } return templates.get(style, templates["商务"]) def add_title_slide(prs, title: str, colors: dict): """添加标题页""" slide_layout = prs.slide_layouts[0] # 标题布局 slide = prs.slides.add_slide(slide_layout) # 设置标题 title_shape = slide.shapes.title title_shape.text = title title_shape.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER title_shape.text_frame.paragraphs[0].font.size = Pt(44) title_shape.text_frame.paragraphs[0].font.color.rgb = colors["primary"] # 设置副标题 if len(slide.placeholders) > 1: subtitle = slide.placeholders[1] subtitle.text = "自动生成的演示文稿" subtitle.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER subtitle.text_frame.paragraphs[0].font.size = Pt(20) subtitle.text_frame.paragraphs[0].font.color.rgb = colors["secondary"] def add_content_slide(prs, slide_data: dict, colors: dict): """添加内容页""" slide_layout = prs.slide_layouts[1] # 标题和内容布局 slide = prs.slides.add_slide(slide_layout) # 设置标题 title_shape = slide.shapes.title title_shape.text = slide_data.get("title", "") title_shape.text_frame.paragraphs[0].font.size = Pt(32) title_shape.text_frame.paragraphs[0].font.color.rgb = colors["primary"] # 设置内容 if len(slide.placeholders) > 1: content = slide.placeholders[1] content.text = "" for point in slide_data.get("content", []): p = content.text_frame.add_paragraph() p.text = point p.font.size = Pt(18) p.font.color.rgb = colors["text"] p.space_after = Pt(12) p.level = 0 # 添加备注 if slide_data.get("notes"): notes_slide = slide.notes_slide notes_slide.notes_text_frame.text = slide_data["notes"] def create_ppt_from_outline(outline: str, template_style: str = "商务") -> bytes: """从大纲文本创建PPT""" lines = outline.strip().split('\n') title = lines[0] if lines else "演示文稿" slides_data = [] current_slide = None for line in lines[1:]: line = line.strip() if not line: continue # 判断是否是标题行(以数字开头或以#开头) if line[0].isdigit() or line.startswith('#') or line.startswith('**'): if current_slide: slides_data.append(current_slide) # 提取标题文本 slide_title = line.lstrip('0123456789.#* ').strip() current_slide = {"title": slide_title, "content": []} elif current_slide: # 作为要点添加 point = line.lstrip('- •* ').strip() if point: current_slide["content"].append(point) if current_slide: slides_data.append(current_slide) return create_ppt(title, slides_data, template_style)