Template 系统数据结构流动详解

🔄 完整数据流动图


用户输入 ──────────────────── API请求 ──────────────── 模板解析 ──────────────── 内容生成 ──────────────── 最终渲染

│ │ │ │ │

▼ ▼ ▼ ▼ ▼

┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐

│GenerateRequest│ │LayoutModel │ │ SlideSchema │ │ SlideContent │ │RenderedSlide │

│ Request │ ───▶ │PresentationLayout│ ───▶│ Definition │ ───▶ │ Generated │ ───▶ │ Component │

└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘

📋 1. 用户请求阶段 - GeneratePresentationRequest


POST /api/v1/ppt/presentation/generate

{

"prompt": "Introduction to Machine Learning", // 🎯 用户输入的主题

"n_slides": 8, // 📊 幻灯片数量

"language": "Chinese", // 🌐 语言设置

"template": "general", // 🎨 选择的模板名称

"export_as": "pptx" // 📦 导出格式

}

  

↓ 转换为内部数据结构

  

class GeneratePresentationRequest:

prompt: str # 用户主题描述

n_slides: int = 8 # 幻灯片数量 (5-15)

language: str = "English" # 展示语言

template: str = "general" # 模板名称

export_as: str = "pptx" # 导出格式 (pptx/pdf)

📋 2. 模板结构获取阶段 - PresentationLayoutModel


get_layout_by_name("general") 调用流程:

  

步骤1: HTTP 请求前端

GET http://localhost:3001/api/layout?group=general

  

步骤2: Puppeteer 访问 Schema 页面

访问: http://localhost:3001/schema?group=general

  

步骤3: 前端返回的原始数据

<div data-layouts='[

{

"id": "general-intro-slide",

"name": "Intro Slide",

"description": "介绍幻灯片布局",

"json_schema": {

"type": "object",

"properties": {

"title": {

"type": "string",

"description": "Main title",

"minLength": 3,

"maxLength": 40

},

"description": {

"type": "string",

"description": "Main description",

"minLength": 10,

"maxLength": 150

},

"presenterName": {

"type": "string",

"description": "Presenter name",

"minLength": 2,

"maxLength": 50

},

"image": {

"type": "object",

"properties": {

"__image_url__": {"type": "string"},

"__image_prompt__": {"type": "string"}

}

}

},

"required": ["title", "description"]

}

},

{

"id": "general-content-bullets",

"name": "Content with Bullets",

"description": "带项目符号的内容幻灯片",

"json_schema": {

"type": "object",

"properties": {

"title": {"type": "string"},

"bullets": {

"type": "array",

"items": {"type": "string"},

"description": "Bullet points"

},

"subtitle": {"type": "string"}

}

}

}

]'>

  

步骤4: 转换为结构化模型

class PresentationLayoutModel:

name: str = "general" # 模板名称

ordered: bool = False # 是否要求顺序

slides: List[SlideLayoutModel] = [ # 幻灯片类型列表

SlideLayoutModel(

id="general-intro-slide",

name="Intro Slide",

description="介绍幻灯片布局",

json_schema={...} # JSON Schema 定义

),

SlideLayoutModel(

id="general-content-bullets",

name="Content with Bullets",

description="带项目符号的内容",

json_schema={...}

)

# ... 更多幻灯片类型

]

📋 3. 大纲生成阶段 - PresentationOutlineModel


LLM 调用: generate_ppt_outline()

输入参数:

- prompt: "Introduction to Machine Learning"

- n_slides: 8

- language: "Chinese"

- available_layouts: PresentationLayoutModel

  

LLM 返回的 JSON 流:

{

"title": "机器学习入门介绍",

"slides": [

{

"title": "什么是机器学习",

"body": "机器学习是人工智能的一个分支,通过算法让计算机从数据中学习模式...",

"slide_type": "general-intro-slide" # 👈 关键: 指定使用的布局类型

},

{

"title": "机器学习的主要类型",

"body": "监督学习、无监督学习、强化学习的概念和应用场景",

"slide_type": "general-content-bullets"

},

{

"title": "监督学习详解",

"body": "分类和回归问题的定义、常见算法和实际应用案例",

"slide_type": "general-content-bullets"

}

// ... 更多幻灯片大纲

],

"notes": [

"重点讲解机器学习与传统编程的区别",

"准备实际案例演示不同算法的效果"

]

}

  

↓ 解析为结构化数据

  

class PresentationOutlineModel:

title: str = "机器学习入门介绍"

slides: List[SlideOutlineModel] = [

SlideOutlineModel(

title="什么是机器学习",

body="机器学习是人工智能的一个分支...",

slide_type="general-intro-slide" # 布局类型引用

),

SlideOutlineModel(

title="机器学习的主要类型",

body="监督学习、无监督学习...",

slide_type="general-content-bullets"

)

# ...

]

notes: List[str] = ["重点讲解...", "准备实际案例..."]

📋 4. 幻灯片内容生成阶段 - SlideModel


对每张幻灯片调用: get_slide_content_from_type_and_outline()

  

输入:

- slide_outline: SlideOutlineModel (大纲信息)

- slide_layout: SlideLayoutModel (布局Schema)

- presentation_outline: PresentationOutlineModel (整体大纲)

  

处理过程:

1. 根据 slide_type 找到对应的 JSON Schema

2. LLM 根据 Schema 约束生成结构化内容

3. 验证生成的数据是否符合 Schema 要求

  

示例 - 生成 "general-intro-slide" 内容:

  

LLM 输入 Schema:

{

"type": "object",

"properties": {

"title": {"type": "string", "minLength": 3, "maxLength": 40},

"description": {"type": "string", "minLength": 10, "maxLength": 150},

"presenterName": {"type": "string", "minLength": 2, "maxLength": 50},

"presentationDate": {"type": "string"},

"image": {

"type": "object",

"properties": {

"__image_url__": {"type": "string"},

"__image_prompt__": {"type": "string"}

}

}

}

}

  

LLM 生成结果:

{

"title": "什么是机器学习",

"description": "机器学习是人工智能的一个分支,它使用算法和统计模型让计算机系统能够从数据中学习和改进,而无需明确编程。",

"presenterName": "AI 专家",

"presentationDate": "2024年12月",

"image": {

"__image_url__": "", # 稍后由图片服务填充

"__image_prompt__": "modern computer analyzing data with AI algorithms visualization"

}

}

  

↓ 存储为数据库记录

  

class SlideModel:

id: UUID = uuid.uuid4()

presentation_id: UUID # 所属演示文稿ID

slide_number: int = 1 # 幻灯片序号

layout_id: str = "general-intro-slide" # 布局类型ID

content: Dict = { # 结构化内容数据

"title": "什么是机器学习",

"description": "机器学习是人工智能...",

"presenterName": "AI 专家",

"presentationDate": "2024年12月",

"image": {

"__image_url__": "https://generated-image-url.jpg",

"__image_prompt__": "modern computer..."

}

}

created_at: datetime

updated_at: datetime

📋 5. 图片资源处理阶段 - ImageModel


图片生成流程:

  

输入: image.__image_prompt__ = "modern computer analyzing data with AI algorithms"

  

调用: ImageGenerationService.generate_image()

  

根据配置的图片提供商处理:

- DALL-E 3: OpenAI API 调用

- Gemini Flash: Google API 调用

- Pexels: 搜索相关图片

- Pixabay: 搜索免费图片

  

返回结果:

{

"image_url": "https://images.example.com/generated/uuid.jpg",

"local_path": "/app_data/images/presentation_id/slide_1_image.jpg",

"prompt_used": "modern computer analyzing data with AI algorithms",

"provider": "dall-e-3",

"generated_at": "2024-12-11T10:30:00Z"

}

  

更新幻灯片数据:

slide.content["image"]["__image_url__"] = image_result["image_url"]

📋 6. 前端渲染阶段 - React Component Props


前端获取幻灯片数据:

GET /api/v1/ppt/presentation/{presentation_id}/slides

  

返回数据结构:

{

"slides": [

{

"id": "slide-uuid-1",

"slide_number": 1,

"layout_id": "general-intro-slide",

"content": {

"title": "什么是机器学习",

"description": "机器学习是人工智能的一个分支...",

"presenterName": "AI 专家",

"presentationDate": "2024年12月",

"image": {

"__image_url__": "https://images.example.com/generated/uuid.jpg",

"__image_prompt__": "modern computer analyzing data"

}

}

}

// ... 更多幻灯片

]

}

  

React 组件渲染:

1. LayoutContext 根据 layout_id 加载对应组件

2. 将 slide.content 作为 props 传递给组件

  

// IntroSlideLayout 组件接收的 props:

interface IntroSlideLayoutProps {

data?: {

title?: string; // "什么是机器学习"

description?: string; // "机器学习是人工智能的一个分支..."

presenterName?: string; // "AI 专家"

presentationDate?: string; // "2024年12月"

image?: {

__image_url__?: string; // "https://images.example.com/..."

__image_prompt__?: string; // "modern computer analyzing data"

}

}

}

  

// 最终渲染的 JSX:

<div className="w-full h-full bg-white">

<div className="flex h-full">

<div className="flex-1">

<img src="https://images.example.com/generated/uuid.jpg"

alt="modern computer analyzing data" />

</div>

<div className="flex-1">

<h1>{data.title}</h1> {/* 什么是机器学习 */}

<p>{data.description}</p> {/* 机器学习是人工智能... */}

<div className="presenter-info">

<span>{data.presenterName}</span> {/* AI 专家 */}

<span>{data.presentationDate}</span> {/* 2024年12月 */}

</div>

</div>

</div>

</div>

📋 7. 导出阶段 - PPTX/PDF 数据


导出处理流程:

  

1. 获取完整演示文稿数据:

class PresentationWithSlides:

presentation: PresentationModel = {

"id": "presentation-uuid",

"title": "机器学习入门介绍",

"template": "general",

"export_format": "pptx"

}

slides: List[SlideModel] = [

SlideModel(...), # 所有幻灯片数据

SlideModel(...),

# ...

]

  

2. PPTX 生成过程:

PptxPresentationCreator.create_presentation()

  

输入处理:

- 遍历每个 SlideModel

- 根据 layout_id 确定幻灯片布局

- 将 slide.content 数据填充到模板中

  

生成的 PPTX 结构:

presentation.pptx

├── slide1.xml # 包含 "什么是机器学习" 的内容和布局

├── slide2.xml # 包含 "机器学习的主要类型" 的内容

├── media/

│ ├── image1.jpg # 第1张幻灯片的图片

│ └── image2.jpg # 第2张幻灯片的图片

└── theme/

└── theme1.xml # general 模板的主题样式

  

3. 最终返回结果:

{

"presentation_id": "presentation-uuid",

"path": "/static/exports/presentation-uuid/机器学习入门介绍.pptx",

"edit_path": "/presentation?id=presentation-uuid"

}

🔍 数据结构关键对应关系


模板组件 JSON Schema 生成内容 最终渲染

───────── ───────── ───────── ─────────

layoutId: "properties": { LLM生成: React Props:

"general-intro-slide" "title": { "title": "什么是机器学习" data.title

"type": "string"

}

layoutName: "description": { "description": data.description

"Intro Slide" "type": "string" "机器学习是..."

React组件: "presenterName": { "presenterName": data.presenterName

IntroSlideLayout "type": "string" "AI 专家"

Zod Schema: "image": { "image": { data.image

introSlideSchema "type": "object" "__image_url__": "...",

} "__image_prompt__": "..."

}

🌐 完整 API 接口列表

📋 模板相关 API

1. 获取所有模板组


GET /api/templates

返回: GroupedLayoutsResponse[]

  

[

{

"groupName": "general",

"files": ["IntroSlideLayout.tsx", "TeamSlideLayout.tsx", ...],

"settings": {

"description": "General purpose layouts",

"ordered": false,

"default": true

}

},

{

"groupName": "modern",

"files": ["z10TeamSlideLayout.tsx", ...],

"settings": {

"description": "Modern design templates",

"ordered": false,

"default": false

}

}

]

2. 获取特定模板的布局结构 (前端内部API)


GET /api/layout?group={template_name}

示例: GET /api/layout?group=general

  

返回: PresentationLayoutModel

{

"name": "general",

"ordered": false,

"slides": [

{

"id": "general-intro-slide",

"name": "Intro Slide",

"description": "A clean slide layout with title...",

"json_schema": {

"type": "object",

"properties": {

"title": {"type": "string", "minLength": 3, "maxLength": 40},

"description": {"type": "string", "minLength": 10, "maxLength": 150},

// ...

}

}

}

// ... 更多幻灯片类型

]

}

3. Schema 提取页面 (Puppeteer 访问)


GET /schema?group={template_name}

示例: GET /schema?group=general

  

返回 HTML 页面,包含以下属性:

<div data-layouts='[...]' data-group-settings='{...}'>

📋 演示文稿生成相关 API

4. 生成完整演示文稿


POST /api/v1/ppt/presentation/generate

Content-Type: application/json

  

请求体:

{

"prompt": "Introduction to Machine Learning",

"n_slides": 8,

"language": "Chinese",

"template": "general",

"export_as": "pptx"

}

  

返回: PresentationPathAndEditPath

{

"presentation_id": "uuid-string",

"path": "/static/exports/presentation-uuid/机器学习入门介绍.pptx",

"edit_path": "/presentation?id=presentation-uuid"

}

5. 获取演示文稿详情


GET /api/v1/ppt/presentations/{presentation_id}

  

返回: PresentationModel

{

"id": "presentation-uuid",

"title": "机器学习入门介绍",

"template": "general",

"language": "Chinese",

"export_format": "pptx",

"status": "completed",

"created_at": "2024-12-11T10:00:00Z",

"updated_at": "2024-12-11T10:05:00Z"

}

6. 获取演示文稿的所有幻灯片


GET /api/v1/ppt/presentations/{presentation_id}/slides

  

返回: List[SlideModel]

[

{

"id": "slide-uuid-1",

"presentation_id": "presentation-uuid",

"slide_number": 1,

"layout_id": "general-intro-slide",

"content": {

"title": "什么是机器学习",

"description": "机器学习是人工智能的一个分支...",

"presenterName": "AI 专家",

"presentationDate": "2024年12月",

"image": {

"__image_url__": "https://images.example.com/generated/uuid.jpg",

"__image_prompt__": "modern computer analyzing data"

}

},

"created_at": "2024-12-11T10:01:00Z",

"updated_at": "2024-12-11T10:03:00Z"

}

// ... 更多幻灯片

]

📋 幻灯片操作相关 API

7. 获取单个幻灯片详情


GET /api/v1/ppt/slides/{slide_id}

  

返回: SlideModel

{

"id": "slide-uuid-1",

"presentation_id": "presentation-uuid",

"slide_number": 1,

"layout_id": "general-intro-slide",

"content": { /* 结构化内容数据 */ },

"created_at": "2024-12-11T10:01:00Z",

"updated_at": "2024-12-11T10:03:00Z"

}

8. 更新幻灯片内容


PUT /api/v1/ppt/slides/{slide_id}

Content-Type: application/json

  

请求体:

{

"content": {

"title": "更新后的标题",

"description": "更新后的描述内容...",

// ... 其他字段

}

}

  

返回: SlideModel (更新后的数据)

9. 重新生成幻灯片内容


POST /api/v1/ppt/slides/{slide_id}/regenerate

Content-Type: application/json

  

请求体:

{

"instruction": "请让内容更加简洁明了" // 可选的重新生成指示

}

  

返回: SlideModel (重新生成后的数据)

📋 图片生成相关 API

10. 生成图片


POST /api/v1/ppt/images/generate

Content-Type: application/json

  

请求体:

{

"prompt": "modern computer analyzing data with AI algorithms",

"provider": "dall-e-3", // dall-e-3, gemini_flash, pexels, pixabay

"size": "1024x1024" // 可选,默认 1024x1024

}

  

返回:

{

"image_url": "https://images.example.com/generated/uuid.jpg",

"local_path": "/app_data/images/uuid.jpg",

"prompt_used": "modern computer analyzing data with AI algorithms",

"provider": "dall-e-3",

"generated_at": "2024-12-11T10:30:00Z"

}

11. 获取图片列表


GET /api/v1/ppt/images?presentation_id={presentation_id}

  

返回: List[ImageModel]

[

{

"id": "image-uuid",

"presentation_id": "presentation-uuid",

"slide_id": "slide-uuid",

"image_url": "https://images.example.com/generated/uuid.jpg",

"local_path": "/app_data/images/uuid.jpg",

"prompt": "modern computer analyzing data",

"provider": "dall-e-3",

"created_at": "2024-12-11T10:30:00Z"

}

]

📋 布局和模板管理 API

12. 获取布局详情


GET /api/v1/ppt/layouts/{layout_name}

示例: GET /api/v1/ppt/layouts/general

  

返回: PresentationLayoutModel (同 /api/layout 返回格式)

13. 获取所有可用布局列表


GET /api/v1/ppt/layouts

  

返回: List[LayoutSummary]

[

{

"name": "general",

"description": "General purpose layouts",

"slide_count": 9,

"is_default": true

},

{

"name": "modern",

"description": "Modern design templates",

"slide_count": 7,

"is_default": false

}

]

📋 自定义模板相关 API

14. 上传 PPTX 创建自定义模板


POST /api/v1/ppt/template-management/upload

Content-Type: multipart/form-data

  

Form Data:

- file: [PPTX 文件]

- template_name: "我的自定义模板"

- description: "基于公司品牌的演示模板"

  

返回:

{

"presentation_id": "custom-template-uuid",

"template_name": "我的自定义模板",

"status": "processing",

"created_at": "2024-12-11T11:00:00Z"

}

15. 获取自定义模板摘要


GET /api/v1/ppt/template-management/summary

  

返回:

{

"presentations": [

{

"presentation_id": "custom-template-uuid",

"template": {

"name": "我的自定义模板",

"description": "基于公司品牌的演示模板"

},

"last_updated_at": "2024-12-11T11:05:00Z",

"slide_count": 6,

"status": "ready"

}

]

}

📋 导出相关 API

16. 导出演示文稿


POST /api/v1/ppt/presentations/{presentation_id}/export

Content-Type: application/json

  

请求体:

{

"format": "pptx", // pptx 或 pdf

"quality": "high" // low, medium, high

}

  

返回:

{

"export_id": "export-uuid",

"download_url": "/static/exports/presentation-uuid/presentation.pptx",

"status": "completed",

"file_size": 2048576, // 字节

"created_at": "2024-12-11T10:10:00Z"

}

17. 获取导出状态


GET /api/v1/ppt/exports/{export_id}/status

  

返回:

{

"export_id": "export-uuid",

"status": "completed", // pending, processing, completed, failed

"progress": 100, // 0-100

"download_url": "/static/exports/presentation-uuid/presentation.pptx",

"error_message": null

}

🔄 API 调用时序图


用户请求 ──────────────────── 后端处理 ──────────────────── 数据存储 ──────────────────── 前端渲染

│ │ │ │

├─ POST /generate ────────▶ ├─ GET /api/layout ──────▶ ├─ INSERT Presentation ──▶ ├─ GET /slides

│ ├─ LLM Content Gen ──────▶ ├─ INSERT Slides ──────▶ ├─ Load Components

│ ├─ POST /images/gen ─────▶ ├─ INSERT Images ──────▶ ├─ Render JSX

│ └─ POST /export ─────────▶ └─ UPDATE Status ──────▶ └─ Display Result

这样你就能清楚地看到数据是如何在整个系统中流动和转换的!每个阶段的数据结构都有明确的用途和转换规则,配合完整的API接口,整个系统的交互逻辑就非常清晰了。