# AI PPT 接口说明（前端调用）

基于 `AIPptMixin` 提供的 PPT 相关接口，挂载在 **ai_chat_session** 下。所有接口需登录，请求头携带 `Authorization: JWT <token>`。

**Base URL**：`{host}/base/api/system/ai_chat_session/`（以项目实际配置为准）

**通用**：POST 请求体为 JSON；GET 无 body。统一响应格式：成功 `{ "code": 2000, "data": {...}, "msg": "success" }`，失败 `{ "code": 400, "data": null, "msg": "错误信息" }`。

---

## 一、主流程（推荐调用顺序）

1. **生成大纲** → `generate_ppt_outline`  
2. **根据大纲生成 HTML 演示稿** → `generate_ppt_html`（可选流式）  
3. **预览**：使用返回的 `html_url` 在浏览器打开或 iframe 展示  
4. **生成 PPTX**：若有 `html_to_pptx` 接口则调之，否则可在 `generate_ppt_html` 时传 `also_generate_pptx: true`  
5. **下载**：使用返回的 `pptx_url` 或 `html_url` 触发下载  

---

## 二、接口列表

### 1. 生成 PPT 大纲（接口1）

**POST** `generate_ppt_outline/`

根据主题生成大纲，供后续 `generate_ppt_html`、`build_ppt_slides` 使用。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| topic | string | 是 | 主题 |
| slide_count | number | 否 | 页数 1–30，默认 10 |
| previous_outline | array | 否 | 已有大纲，在其基础上重新生成/优化 |
| provider / model / use_settings / api_key / base_url | - | 否 | AI 模型配置 |

**请求示例**

```json
{
  "topic": "人工智能发展趋势",
  "slide_count": 8
}
```

**响应 data**

```json
{
  "outline": [
    { "title": "封面", "points": ["项目名称"] },
    { "title": "目录", "points": ["第一部分", "第二部分"] }
  ],
  "raw": "...",
  "model": "...",
  "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 }
}
```

---

### 2. 根据大纲生成 HTML 演示稿（接口2）

**POST** `generate_ppt_html/`

根据大纲生成每页内容（HTML），保存到 `media/slides/`，并同步写入 `templates/ppt/` 便于验证。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| outline | array | 与 topic 二选一 | 大纲，来自 `generate_ppt_outline`；每项 `{ "title", "points" }` |
| topic | string | 与 outline 二选一 | 仅传 topic 时会先生成大纲再生成 HTML |
| slide_count | number | 否 | 仅无 outline 时有效，1–30，默认 10 |
| style | string | 否 | 风格 id，默认 `bold_signal`，可选见 `get_ppt_html_styles` |
| stream | number/boolean | 否 | 0/1 或 false/true，是否流式 SSE，默认 0 |
| per_slide | boolean | 否 | 是否逐页生成，默认 true |
| generate_slide_image | boolean | 否 | 是否每页生成配图（万相），默认 true |
| also_generate_pptx | boolean | 否 | 是否同时生成 .pptx，默认 false |
| template_id | string | 否 | 布局模板 id |
| max_tokens | number | 否 | 仅 per_slide=false 时有效，1024–65536，默认 8192 |
| wanxiang_api_key / wanxiang_model / wanxiang_size | string | 否 | 通义万相配置 |
| provider / model / api_key / base_url | - | 否 | AI 模型配置 |

**请求示例**

```json
{
  "outline": [
    { "title": "封面", "points": ["项目名称"] },
    { "title": "目录", "points": ["第一部分", "第二部分"] }
  ],
  "topic": "人工智能汇报",
  "style": "bold_signal",
  "stream": 0,
  "generate_slide_image": true,
  "also_generate_pptx": false
}
```

**响应 data（非流式）**

```json
{
  "html_url": "/media/slides/xxx.html",
  "filename": "xxx.html",
  "outline": [...],
  "slide_count": 5,
  "style": "bold_signal",
  "saved_path": "media/slides/xxx.html",
  "saved_path_abs": "/path/to/media/slides/xxx.html",
  "templates_path": "/path/to/templates/ppt/xxx.html",
  "pptx_url": "/media/slides/xxx.pptx",
  "pptx_filename": "xxx.pptx"
}
```

`pptx_url` / `pptx_filename` 仅在 `also_generate_pptx: true` 时有值；`templates_path` 在成功写入 templates 时才有。

**流式（stream: 1）**：Content-Type 为 `text/event-stream`，事件依次为 `outline` → 多次 `slide` → `done`，`done` 的 data 与上面结构一致。

---

### 3. 单页重新生成大纲

**POST** `regenerate_ppt_outline_page/`

只重新生成指定页的 title 与 points。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| topic | string | 是 | 主题 |
| page_index | number | 是 | 页下标，从 0 开始 |
| outline | array | 是 | 当前完整大纲（对象数组） |
| provider / model / ... | - | 否 | AI 配置 |

**请求示例**

```json
{
  "topic": "人工智能发展趋势",
  "page_index": 1,
  "outline": [
    { "title": "封面", "points": ["项目名称"] },
    { "title": "目录", "points": ["第一部分", "第二部分"] }
  ]
}
```

**响应 data**

```json
{
  "slide": { "title": "目录", "points": ["第一部分", "第二部分", "第三部分"] },
  "page_index": 1,
  "raw": "...",
  "model": "...",
  "usage": {}
}
```

前端可将返回的 `slide` 写回本地 `outline[page_index]` 再调 `generate_ppt_html`。

---

### 4. 生成配图描述（仅文案）

**POST** `generate_ppt_slide_image_prompt/`

根据本页标题与要点生成配图描述与关键词，不调用画图接口。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| title | string | 是 | 本页标题 |
| topic | string | 否 | 整体主题 |
| points | array | 否 | 本页要点，最多取前 5 条 |
| provider / model / ... | - | 否 | AI 配置 |

**响应 data**

```json
{
  "image_prompt": "英文短句，用于文生图",
  "image_keywords": ["关键词1", "关键词2"],
  "suggestion": "一句话中文配图建议",
  "model": "...",
  "usage": {}
}
```

---

### 5. 生成配图并返回图片 URL

**POST** `generate_ppt_slide_image/`

根据本页标题与要点生成配图描述并调用通义万相，直接返回图片 URL。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| title | string | 是 | 本页标题 |
| topic | string | 否 | 整体主题 |
| points | array | 否 | 本页要点 |
| wanxiang_api_key / wanxiang_model / wanxiang_size | string | 否 | 万相配置 |
| provider / model / ... | - | 否 | AI 配置 |

**响应 data**

```json
{
  "image_url": "https://...",
  "image_urls": ["https://..."],
  "image_prompt": "...",
  "image_keywords": [],
  "suggestion": "...",
  "error": null
}
```

---

### 6. 获取布局规范与模板

**GET** `get_ppt_slide_layout_spec/`

无请求体。返回单页布局 schema 与预设模板，供前端做布局选择，并将选中的 `template_id` 传给 `build_ppt_slides`、`generate_ppt_html`。

**响应 data**

```json
{
  "schema": {
    "description": "单页 PPT 元素布局，position/size 为相对画布的百分比 0-100",
    "title": { "text": "...", "position": {...}, "font_size": 28, ... },
    "body": { "content": "...", "position": {...}, ... },
    "image": { "url": "...", "position": {...}, "fit": "cover" }
  },
  "templates": [
    { "id": "title_top_text_left_image_right", "name": "标题上、左文右图", "title": {...}, "body": {...}, "image": {...} },
    { "id": "title_top_text_below_image_bottom", "name": "标题上、正文中、图片下", ... },
    { "id": "title_center_text_only", "name": "仅标题+正文（无图）", ... },
    { "id": "title_left_image_full_right", "name": "标题左上、大图占右半", ... }
  ]
}
```

---

### 7. 获取 HTML 风格预设

**GET** `get_ppt_html_styles/`

无请求体。返回生成 HTML 演示稿时可用的风格列表，供前端展示并传 `style` 给 `generate_ppt_html`。

**响应 data**

```json
{
  "styles": [
    { "id": "bold_signal", "name": "Bold Signal", "desc": "深色背景、高对比、自信专业" },
    { "id": "dark_botanical", "name": "Dark Botanical", "desc": "深色、柔和抽象形状、优雅" },
    { "id": "swiss_modern", "name": "Swiss Modern", "desc": "极简、线框、数据感" },
    { "id": "neon_cyber", "name": "Neon Cyber", "desc": "霓虹、科技、未来感" },
    { "id": "pastel_geometry", "name": "Pastel Geometry", "desc": "浅色、几何、友好" }
  ]
}
```

---

### 8. 根据大纲与图片拼装每页数据

**POST** `build_ppt_slides/`

不调 AI，根据已有 outline 与每页图片 URL 拼出每页完整布局数据，供前端渲染或导出 PPT。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| outline | array | 是 | 大纲，每项 `{ "title", "points" }` |
| image_urls | array | 否 | 按页顺序的图片 URL，`image_urls[i]` 对应第 i 页 |
| image_url_by_index | object | 否 | key 为页下标字符串 "0","1",...，value 为 URL 或 `{ "url" }` / `{ "image_url" }` |
| template_id | string | 否 | 布局模板 id，默认 `title_top_text_left_image_right` |

**请求示例**

```json
{
  "outline": [
    { "title": "封面", "points": ["项目名称"] },
    { "title": "正文", "points": ["要点一", "要点二"] }
  ],
  "image_urls": ["https://example.com/img0.png", ""],
  "template_id": "title_top_text_left_image_right"
}
```

**响应 data**

```json
{
  "slides": [
    {
      "title": { "text": "封面", "position": {...}, "font_size": 28, ... },
      "body": { "content": "...", "points": ["项目名称"], ... },
      "image": { "url": "https://...", "position": {...}, "fit": "cover" },
      "layout_id": "title_top_text_left_image_right"
    }
  ]
}
```

---

## 三、Outline 统一格式

所有涉及大纲的接口，**outline** 均为数组，每项为对象：

```ts
{ title: string; points: string[] }
```

示例：

```json
[
  { "title": "封面", "points": ["项目名称", "汇报人"] },
  { "title": "目录", "points": ["背景", "方案", "总结"] }
]
```

---

## 四、AI 模型通用参数（可选）

以下字段在需要调用大模型的接口中可选传入（否则使用系统/会话配置）：

- **provider**：如 `openai`、`deepseek`
- **model**：模型名
- **api_key**：API Key
- **base_url**：API 基础 URL
- **use_settings**：是否使用系统配置中的 key/url

---

## 五、curl 示例

```bash
# 1. 生成大纲
curl -X POST 'http://localhost:8000/base/api/system/ai_chat_session/generate_ppt_outline/' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: JWT <your_token>' \
  -d '{"topic": "人工智能发展趋势", "slide_count": 5}'

# 2. 根据大纲生成 HTML（使用上一步返回的 outline）
curl -X POST 'http://localhost:8000/base/api/system/ai_chat_session/generate_ppt_html/' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: JWT <your_token>' \
  -d '{"outline": [...], "topic": "人工智能发展趋势", "style": "bold_signal"}'

# 3. 获取风格列表
curl -X GET 'http://localhost:8000/base/api/system/ai_chat_session/get_ppt_html_styles/' \
  -H 'Authorization: JWT <your_token>'

# 4. 获取布局模板
curl -X GET 'http://localhost:8000/base/api/system/ai_chat_session/get_ppt_slide_layout_spec/' \
  -H 'Authorization: JWT <your_token>'
```

---

文档对应源码：`django_base_ai/system/views/ai_ppt.py`（AIPptMixin）。
