# PPT 文档导入与呈现服务 — 规划设计及实施方案

## 一、概述

### 1.1 背景与痛点

PPT（PowerPoint / Keynote / WPS 演示文稿）是企业内外部演讲、培训、方案汇报的核心文档格式。然而在大屏呈现场景中，PPT 面临以下突出痛点：

| 痛点 | 说明 |
|------|------|
| **终端碎片化** | 大屏涵盖智能电视机（Android）、机顶盒（Android）、Windows 各版本、鸿蒙 TV 等，PPT 在不同平台渲染效果差异显著 |
| **字体与排版漂移** | 缺少字体导致替代渲染，页面布局错位，精心排版的效果无法还原 |
| **演讲者被迫自带 PC** | 为保证呈现一致性，演讲者常常只能连接自己的笔记本电脑，增加准备成本和安全风险 |
| **互动能力缺失** | 原生 PPT 演示模式缺乏观众互动（投票、提问、弹幕、反馈）能力 |
| **协作效率低** | PPT 通过网盘或邮件传递，缺乏版本管理、多人协作、权限控制 |

### 1.2 目标

基于 [ICT 服务平台](ICT服务平台概要.md) 的统一认证底座（OpenLDAP + Keycloak）和 Git 基础设施（Gitea），构建 **PPT 文档导入与呈现服务平台**，实现：

- 在云端将 PPT 转化为 Web 页面，终端以**浏览器**为统一呈现载体
- 覆盖全部泛化终端（Android TV、Android STB、Windows、鸿蒙 TV、iPad 等）
- 互动信息（评论、投票、提问、弹幕）与 PPT-Web 每页画面精确绑定
- 基于 Git 管理个人文档与工作组文档，支持多组合协作关系
- 用户界面保持文件目录树方式，符合日常使用习惯

### 1.3 核心设计原则

- **浏览器即终端**：PPT 转 Web 后，任何支持现代浏览器的设备均可精确呈现，从根本上消除终端差异
- **Git 为唯一真实源**：PPT 原文件及转换产物均存储于 Git 仓库，版本可追溯
- **开源优先，商业增强**：核心链路采用开源方案，高保真转换环节引入商业方案保障效果
- **认证复用**：全部接入 ICT 平台 Keycloak SSO
- **自动化驱动**：Git 推送即触发 PPT 转换、发布、同步，零人工干预

### 1.4 用户角色

| 角色 | 说明 | 典型场景 |
|------|------|---------|
| 演讲者 (Presenter) | PPT 上传者与现场演讲控制者 | 上传 PPT 到 Git，远程/现场控制翻页 |
| 观众 (Audience) | 通过大屏或个人设备观看演示的人员 | 浏览器观看 PPT-Web、扫码参与互动 |
| 协作者 (Collaborator) | 参与 PPT 文档协同编辑与版本管理的成员 | 通过 Git 分支协作修改 PPT 资料 |
| 管理员 (Admin) | 管理文档空间、权限、转换策略的 IT 人员 | 配置仓库权限与转换规则 |

---

## 二、系统架构

### 2.1 整体架构图

```plantuml
@startuml
skinparam componentStyle rectangle
skinparam nodesep 30
skinparam ranksep 40
title PPT 文档导入与呈现服务 - 系统架构

' ===== 用户层 =====
actor "演讲者" as Presenter
actor "观众" as Audience

' ===== 终端层 =====
node "演讲者终端" as PClient {
  component "VS Code + Qoder" as IDE
}

node "泛化终端 (浏览器统一呈现)" as AClient {
  component "Android TV / STB" as TV
  component "Windows / Mac" as WinMac
  component "鸿蒙 TV / iPad" as HM
}

' ===== 应用服务层 =====
node "互联网应用服务器" as AppServer {
  component "Nginx + SSL" as Nginx
  component "Keycloak SSO" as KC

  package "文档管理" {
    component "Gitea" as Gitea
    component "MeiliSearch" as Search
  }

  package "PPT 转换引擎" {
    component "SlideForge" as SF
    component "ONLYOFFICE" as OO
    component "LibreOffice" as LO
  }

  package "演示与互动" {
    component "SlidePortal" as Portal
    component "InteractHub" as Interact
  }
}

' ===== 数据层 =====
node "私有云 [数据后端]" as PCloud {
  database "PostgreSQL" as DB
  database "OpenLDAP" as LDAP
  storage "Git 仓库存储" as Store
}

' == 演讲者流 ==
Presenter -down-> IDE : 上传 PPT
IDE -down-> Gitea : git push (SSH)

' == 观众流 ==
Audience -down-> AClient
AClient -down-> Nginx : HTTPS

' == 接入与认证 ==
Nginx -down-> KC : 认证校验
Nginx -down-> Portal : 演示页面

' == 转换链 ==
Gitea -right-> SF : Webhook 触发
SF -down-> OO : PPTX 转 HTML
SF -down-> LO : 旧格式转换
SF -right-> Portal : Web 幻灯片

' == 互动 ==
Portal -down-> Interact : 互动事件

' == 数据存储 ==
KC -down-> LDAP : 用户目录
Gitea -down-> Store : 仓库数据
SF -down-> DB : 转换元数据
Interact -down-> DB : 互动数据
@enduml
```

### 2.2 核心组件清单

| 组件 | 技术方案 | 用途 | 许可证 |
|------|---------|------|--------|
| PPT 转换调度 | **自研 SlideForge**（Node.js） | 接收 Webhook，调度转换引擎，管理转换产物 | — |
| 反馈引擎 | **FeedbackEngine**（SlideForge 子模块） | 互动数据聚合、反馈报告生成、修订闭环管理 | — |
| PPT 转 HTML（主引擎） | **ONLYOFFICE Document Server** | 高保真 PPTX 转 HTML | AGPL v3 |
| PPT 转 HTML（兼容引擎） | **LibreOffice Headless** | 旧格式（PPT/ODP）转换 | MPL 2.0 |
| PPT 转 HTML（高保真） | **Aspose.Slides Cloud** | 复杂动画与特殊排版的精确还原 | 商业授权 |
| Web 幻灯片框架 | **Reveal.js** | 浏览器端幻灯片呈现、翻页、全屏 | MIT |
| 实时互动 | **自研 InteractHub**（Socket.io） | 投票、提问、弹幕、遥控翻页 | — |
| 演示平台 | **自研 SlidePortal**（Next.js） | 文件管理 UI、演示控制台、观众端 | — |
| Git 仓库 | **Gitea**（已有） | PPT 文件存储与版本管理 | MIT |
| 全文检索 | **MeiliSearch**（已有） | PPT 标题、标签、内容搜索 | MIT |
| 认证中心 | **Keycloak**（已有） | OIDC SSO 统一登录 | Apache 2.0 |
| 反向代理 | **Nginx**（已有） | SSL 终止、路由分发、WebSocket 代理 | BSD |

---

## 三、PPT 转 Web 关键技术

### 3.1 技术路线概览

PPT 转 Web 是本系统的**核心技术环节**，直接决定终端呈现质量。业界存在以下主要技术路线：

```
PPT 原文件
  │
  ├─ 路线 A：PPT → HTML（直接转换）
  │    └─ ONLYOFFICE / Aspose.Slides / GroupDocs
  │
  ├─ 路线 B：PPT → PDF → HTML（两步转换）
  │    └─ LibreOffice → pdf2htmlEX
  │
  ├─ 路线 C：PPT → SVG/PNG + JSON → Reveal.js（解构重建）
  │    └─ Apache POI / python-pptx → 自定义渲染
  │
  └─ 路线 D：PPT → 在线编辑器实时渲染
       └─ ONLYOFFICE Viewer / Microsoft Graph API
```

### 3.2 方案详细对比

| 维度 | ONLYOFFICE | LibreOffice | Aspose.Slides | pdf2htmlEX 管线 | POI + Reveal.js | MS Graph API |
|------|-----------|-------------|---------------|----------------|-----------------|--------------|
| **类型** | 开源 AGPL v3 | 开源 MPL 2.0 | 商业 | 开源 GPL v3 | 开源 Apache 2.0 | 云服务 |
| **转换质量** | ★★★★☆ | ★★★☆☆ | ★★★★★ | ★★★★☆ | ★★★☆☆ | ★★★★★ |
| **字体保真** | 优 | 中（依赖系统字体） | 优（字体嵌入） | 优（PDF 字体） | 差 | 优 |
| **动画支持** | CSS 动画还原 | 不支持 | CSS/JS 动画 | 不支持 | 需自定义 | 原生动画 |
| **母版/图表** | 完整支持 | 基本支持 | 完整支持 | 视觉保留 | 需自行解析 | 完整支持 |
| **自托管** | Docker 部署 | 原生/Docker | JAR/Docker | 原生/Docker | 纯代码 | 仅云端 |
| **旧格式 PPT** | 支持 | 良好 | 支持 | 间接 | 仅 PPTX | 支持 |
| **ODP/Keynote** | ODP 支持 | 良好 | 有限 | 间接 | 不支持 | 有限 |
| **并发性能** | 中（~5 并发/实例） | 中（进程隔离） | 高 | 中 | 高 | 高（弹性） |
| **年成本** | 免费（社区版） | 免费 | ~30K RMB/服务器 | 免费 | 免费 | ~20K RMB/年 |
| **集成难度** | 中 | 低（CLI） | 低（REST API） | 中 | 高 | 低（REST） |

### 3.3 推荐方案：三级混合转换引擎

采用**三级转换策略**，在效果与成本之间取得最优平衡：

```plantuml
@startuml
skinparam componentStyle rectangle
title PPT 转 Web 三级混合转换引擎

start
:SlideForge 接收 PPT 文件;
:解析文件格式与复杂度;
note right
  检查项：
  动画数量/SmartArt/图表
  嵌入字体/媒体/母版复杂度
end note

if (PPTX 且复杂度 <= 阈值 ?) then (是)
  :ONLYOFFICE 转换;
  note right: 开源主引擎, 覆盖约 80%
else (否)
  if (PPT/ODP/旧格式 ?) then (是)
    :LibreOffice 转换;
    note right: 旧格式兼容引擎
  else (PPTX 高复杂度)
    :Aspose.Slides 转换;
    note right: 商业高保真引擎
  endif
endif

:Reveal.js 封装后处理;
note right
  注入翻页框架 + 互动 SDK
  嵌入字体子集(WOFF2)
  压缩图片(WebP) + 生成缩略图
end note

:存入 Git 仓库 + 注册 PostgreSQL;
stop
@enduml
```

#### 三级引擎定位

| 引擎 | 定位 | 覆盖场景 | 预计占比 |
|------|------|---------|---------|
| **ONLYOFFICE** | 主引擎 | 标准 PPTX，中低复杂度 | ~80% |
| **LibreOffice** | 兼容引擎 | PPT (旧格式)、ODP、Keynote 导出 | ~10% |
| **Aspose.Slides** | 高保真引擎 | 复杂动画、特殊排版、精确还原 | ~10% |

### 3.4 转换后处理：Reveal.js 封装

无论哪个引擎产出 HTML，SlideForge 均进行统一后处理，封装为 **Reveal.js** 格式：

```
转换引擎产出
  │
  ├─ 每页幻灯片 → <section> 标签
  ├─ 注入 Reveal.js 框架（翻页/全屏/进度条/演讲者视图）
  ├─ 注入 InteractHub SDK（每页互动面板 + WebSocket）
  ├─ 字体子集嵌入（fonttools → WOFF2，仅保留使用字符）
  └─ 图片优化（sharp → WebP 转换 + 响应式多尺寸）
```

### 3.5 转换质量保障

| 措施 | 说明 |
|------|------|
| **自动截图对比** | 转换后逐页截图，与 LibreOffice 渲染的参考 PDF 对比相似度（Puppeteer + pixelmatch） |
| **人工校验标记** | 演讲者在 SlidePortal 中逐页预览，可标记"需优化"触发高级引擎重试 |
| **引擎降级重试** | 转换失败或相似度低于阈值时，自动切换更高级引擎重试 |
| **字体白名单** | 维护常用中英文字体库，缺失字体自动提示上传或从字体库补充 |

---

## 四、Git 文档管理体系

### 4.1 仓库结构

PPT 文档管理复用 ICT 平台的 Gitea 基础设施，按组织层级划分仓库：

| 仓库类型 | 命名规范 | 说明 |
|---------|---------|------|
| **个人文档** | `slides-{username}` | 个人 PPT 资料，私有仓库 |
| **工作组文档** | `slides-{group}` | 部门/项目组共享，按组权限 |
| **公开演示** | `slides-public` | 对外发布的演示资料 |
| **模板库** | `slides-templates` | 企业 PPT 模板，全员可读 |

#### 仓库目录结构示例

```
slides-marketing/                     # 市场部工作组仓库
  ├── 2026-Q1/
  │   ├── 新品发布会.pptx
  │   ├── 客户方案-ABC公司.pptx
  │   └── 季度总结.pptx
  ├── templates/
  │   ├── 标准汇报模板.pptx
  │   └── 产品介绍模板.pptx
  ├── .slideforge.yml                 # 转换配置
  └── README.md
```

### 4.2 Git 协作优势（对比网盘）

| 维度 | Git 仓库管理 | 网盘管理 |
|------|-------------|---------|
| **版本管理** | 完整 Git 历史，任意版本可回溯 | 无版本或仅有限快照 |
| **协作模式** | 分支 + 合并请求，多人并行不冲突 | 文件锁定或覆盖冲突 |
| **权限控制** | 按仓库/分支/路径细粒度控制 | 按文件夹粗粒度控制 |
| **自动化** | Webhook 触发转换/发布/通知 | 需人工操作 |
| **多组合协作** | Fork 后独立修改，跨组共享，MR 合并 | 复制粘贴，难以追踪来源 |
| **审计** | 每次变更有作者、时间、说明 | 无或有限审计 |
| **离线使用** | 本地完整仓库，离线可用 | 依赖网络 |

### 4.3 多组合协作关系

Git 的分支与 Fork 机制天然支持跨部门多组合协作：

```plantuml
@startuml
skinparam componentStyle rectangle
title Git 多组合协作模式

package "市场部仓库" as MKT {
  component "main" as Main
  component "feature/新品发布" as F1
}

package "研发部 Fork" as RD {
  component "技术内容补充" as RDWork
}

package "设计部 Fork" as DS {
  component "视觉优化" as DSWork
}

actor "市场部成员" as M
actor "研发部成员" as R
actor "设计部成员" as D

M -down-> F1 : 内容编写
R -down-> RDWork : 技术补充
D -down-> DSWork : 视觉优化
RDWork -right-> Main : Merge Request
DSWork -right-> Main : Merge Request
F1 -down-> Main : 分支合并
@enduml
```

---

## 五、终端泛化呈现

### 5.1 目标终端矩阵

| 终端类型 | 操作系统 | 浏览器内核 | 分辨率 | 输入方式 |
|---------|---------|-----------|--------|---------|
| 智能电视机 | Android TV | Chromium WebView | 1080p / 4K | 遥控器 |
| 大屏机顶盒 | Android | Chromium WebView | 1080p / 4K | 遥控器 |
| 鸿蒙 TV | HarmonyOS | ArkWeb (Chromium) | 1080p / 4K | 遥控器 |
| Windows PC | Windows 10/11 | Chrome / Edge | 多种 | 键鼠 / 翻页笔 |
| Mac | macOS | Safari / Chrome | 多种 | 键鼠 / 翻页笔 |
| iPad / 平板 | iPadOS / Android | Safari / Chrome | 多种 | 触屏 |
| 手机（控制端） | iOS / Android | Safari / Chrome | 多种 | 触屏 |

### 5.2 浏览器统一呈现架构

核心思路：**所有终端均通过浏览器访问 PPT-Web 页面，不安装任何原生 PPT 应用**。

```
云端 PPT → Reveal.js Web 幻灯片
  │
  ├─ Android TV / STB  → WebView 全屏打开
  ├─ 鸿蒙 TV           → ArkWeb 全屏打开
  ├─ Windows / Mac     → Chrome/Edge/Safari 全屏
  ├─ iPad / 平板        → Safari/Chrome 全屏
  └─ 手机              → 浏览器打开（演讲者遥控端）
```

### 5.3 终端适配策略

| 维度 | 策略 |
|------|------|
| **分辨率** | Reveal.js `width/height` + CSS `scale` 自适应，幻灯片按原始比例等比缩放 |
| **字体** | 转换时嵌入字体子集（WOFF2），不依赖终端系统字体 |
| **遥控器** | 拦截遥控器方向键 → 映射为 Reveal.js 上/下/左/右翻页 |
| **触屏** | Reveal.js 原生支持滑动翻页 |
| **翻页笔** | USB 翻页笔发送 Page Up/Down，Reveal.js 原生支持 |
| **全屏** | Fullscreen API 自动进入全屏；遥控器返回键退出 |
| **弱网** | Service Worker 缓存全部资源，首次加载后离线可翻页 |

---

## 六、互动反馈系统

### 6.1 互动功能矩阵

互动信息与 PPT-Web **每页画面精确绑定**，每一页幻灯片可独立配置互动组件：

| 互动功能 | 说明 | 绑定粒度 |
|---------|------|---------|
| **实时投票** | 演讲者发起单选/多选投票，观众扫码参与 | 绑定到具体页 |
| **在线提问 (Q&A)** | 观众提交问题，可点赞，演讲者选择展示 | 绑定到具体页 |
| **弹幕** | 观众发送弹幕，叠加显示在幻灯片上方 | 绑定到具体页 |
| **实时反应** | 观众发送表情反应，悬浮动画展示 | 绑定到具体页 |
| **标注批注** | 审阅者对具体页面留下文字批注 | 绑定到具体页 |
| **演讲者注释** | 仅演讲者可见的备注与提示 | 绑定到具体页 |
| **远程遥控** | 演讲者通过手机控制翻页、激光笔 | 全局 |

### 6.2 互动技术架构

```plantuml
@startuml
skinparam componentStyle rectangle
skinparam nodesep 30
skinparam ranksep 40
title 互动反馈系统架构

node "演讲者手机" as Phone {
  component "遥控端 (翻页/激光笔)" as Remote
}

node "观众手机" as APhone {
  component "互动页面 (投票/提问/弹幕)" as APage
}

node "互联网应用服务器" as Server {
  component "InteractHub" as Hub
  component "Redis (在线状态缓存)" as Redis
}

node "大屏终端" as Screen {
  component "Reveal.js 幻灯片 (同步翻页)" as Slides
  component "互动叠加层 (实时推送)" as Overlay
}

database "PostgreSQL\n(持久化互动数据)" as DB

Remote -down-> Hub : WebSocket
APage -down-> Hub : WebSocket
Hub -down-> Slides : WebSocket
Hub -down-> Overlay : WebSocket
Hub -right-> Redis
Hub -right-> DB
@enduml
```

### 6.3 观众接入方式

观众通过扫描大屏二维码即时接入互动：

```
大屏当前页展示会话二维码
  → 观众手机扫码
  → 打开 https://slide.writech.cn/interact/{session_id}
  → WebSocket 建立连接
  → 实时参与当前页的投票/提问/弹幕
  → 翻页时互动面板自动切换到对应新页
```

### 6.4 互动数据与页面绑定模型

每条互动数据均绑定 `session_id + slide_index`，确保回放时可精确还原每页互动：

```
Session（演示会话）
  ├── slide_index: 0
  │     ├── votes: [{question, options, results}]
  │     ├── questions: [{user, content, upvotes}]
  │     └── reactions: {count_by_type}
  ├── slide_index: 1
  │     ├── danmaku: [{user, content, timestamp}]
  │     └── annotations: [{user, position, content}]
  └── slide_index: N
        └── ...
```

---

## 七、演示反馈闭环

### 7.1 闭环流程概述

演示互动数据不仅服务于现场体验，更构成**从演示到修订的完整闭环**：每场演示结束后，系统自动聚合互动数据、生成结构化反馈报告，推送至 PPT 原始编辑者，驱动文档持续优化迭代。

```plantuml
@startuml
skinparam componentStyle rectangle
title PPT 编辑版本闭环流程

start
:编辑者创建/修改 PPT 并推送到 Git;
:SlideForge 自动转换为 Web 幻灯片;
:演讲者发起演示会话;

:观众互动环节;
note right
  并行采集
  ----
  观众提问
  观众投票
  弹幕 / 表情反应
  审阅者批注
end note

:InteractHub 采集并持久化互动数据;
:演示会话结束;
:FeedbackEngine 聚合互动数据;
note right
  按页聚合 - 每页独立统计
  跨场次聚合 - 同一 PPT 多次演示
end note

:生成结构化反馈报告;
:反馈报告提交至 Git 仓库;
:MsgHub 通知原始编辑者;
:编辑者审阅反馈报告;

if (需要修订 ?) then (是)
  :创建修订分支, 修改 PPT;
  :推送新版本, 自动触发转换;
  note right: 新版本 commit 引用反馈报告
else (否)
  :标记已审阅, 无需修订;
endif

stop
@enduml
```

### 7.2 互动数据聚合

FeedbackEngine 在演示结束后从 PostgreSQL 提取互动数据，按两个维度进行聚合：

#### 逐页聚合

每页幻灯片独立生成反馈摘要：

| 数据维度 | 聚合内容 | 来源 |
|---------|---------|------|
| **提问** | 问题列表、点赞数排序、是否已回答 | Q&A 模块 |
| **投票** | 各选项得票率、参与人数 | 投票模块 |
| **弹幕关键词** | 高频词提取、情感倾向 | 弹幕模块 |
| **反应统计** | 各表情类型的分布 | 反应模块 |
| **批注** | 审阅者标注内容汇总 | 批注模块 |
| **停留时长** | 该页展示时长与全文均值的对比 | 翻页事件 |

#### 跨场次聚合

同一 PPT 可能被多次演示，FeedbackEngine 支持跨场次合并：

| 策略 | 说明 |
|------|------|
| **累计统计** | 所有场次的提问、投票、反应数据累加 |
| **趋势对比** | 对比不同场次同一页的反馈变化 |
| **最新优先** | 修订建议以最近一次演示的反馈为主 |
| **版本关联** | 每次聚合标注对应的 PPT commit hash |

### 7.3 反馈报告

FeedbackEngine 生成的报告以 **Markdown** 存入 Git 仓库，与 PPT 源文件同目录管理：

```
slides-marketing/
  ├── 新品发布会.pptx
  ├── 新品发布会.feedback/
  │   ├── 2026-03-20_会议室A.md          # 单次演示反馈
  │   ├── 2026-03-25_客户现场.md          # 单次演示反馈
  │   └── _summary.md                    # 跨场次汇总报告
  └── .slideforge.yml
```

#### 报告内容结构

每份反馈报告包含以下板块：

| 板块 | 内容 |
|------|------|
| **演示概况** | 文件名、版本 hash、演讲者、日期、时长、观众数、互动参与率 |
| **逐页反馈** | 每页的提问列表(含赞数排序)、投票结果、弹幕关键词、情感倾向、批注汇总、停留时长异常标记 |
| **整体分析** | 全场互动率、情感曲线(逐页正/中/负占比)、高频关键词 Top 10、未回答问题清单 |
| **修订建议** | 基于数据的具体改进建议：高频提问对应补充内容、负面情感页优化表述、停留过短页扩充内容 |

#### 单次反馈报告示例

```markdown
# 演示反馈报告

## 演示概况

| 项目 | 内容 |
|------|------|
| 文件 | 新品发布会.pptx |
| 版本 | commit abc1234 |
| 演讲者 | 张三 |
| 日期 | 2026-03-20 |
| 时长 | 45 分钟 |
| 观众数 | 32 人 |
| 互动参与率 | 78% |

## 逐页反馈

### 第 3 页 - "产品架构"

- 停留时长: 4分12秒 (全文平均 3分)
- 提问 (5条):
  1. "架构中缓存层用的是什么方案?" (12赞)
  2. "支持私有化部署吗?" (8赞)
- 投票: "您认为该架构是否满足需求?"
  完全满足 45% / 基本满足 40% / 需改进 15%
- 情感倾向: 正面 72%, 中性 20%, 负面 8%

## 整体分析

- 观众参与度: 高 (78%)
- 第 7-9 页负面情绪上升
- 高频关键词: 价格、部署、兼容性
- 未回答问题: 3 条

## 修订建议

1. 第 3 页: 补充缓存方案说明
2. 第 7 页: 定价策略引发较多负面反馈, 建议优化表述
3. 第 12 页: 停留时长过短, 考虑扩充内容
```

### 7.4 编辑者修订工作流

反馈报告生成后驱动 PPT 编辑者完成修订闭环：

| 步骤 | 操作 | 说明 |
|------|------|------|
| 1 | 接收通知 | MsgHub 推送反馈通知至编辑者 |
| 2 | 查看反馈 | 在 SlidePortal 反馈看板中查看报告 |
| 3 | 逐页审阅 | 对照 PPT-Web 查看每页的互动数据与建议 |
| 4 | 创建分支 | 在 Gitea 中创建 `revision/{date}` 分支 |
| 5 | 修订 PPT | 在本地修改 PPT 文件并推送 |
| 6 | 自动转换 | SlideForge 自动触发新版本转换 |
| 7 | 关闭反馈 | 修订 commit 引用反馈报告，状态自动更新为“已修订” |

#### 反馈状态流转

| 状态 | 说明 |
|------|------|
| **待审阅** | 报告生成后初始状态 |
| **审阅中** | 编辑者已打开报告 |
| **修订中** | 编辑者已创建修订分支 |
| **已修订** | 修订版本已推送并完成转换 |
| **已关闭** | 编辑者标记无需修订 |

### 7.5 反馈看板

SlidePortal 为编辑者提供**反馈看板**视图，集中展示所有待处理反馈：

```
+------------------------------------------------------+
|  反馈看板                               [全部/待处理]   |
+------------------------------------------------------+
|  新品发布会.pptx                                       |
|    [待审阅] 03-25 客户现场  28人  互动率82%  建议4条    |
|    [已修订] 03-20 会议室A   32人  互动率78%  建议3条    |
|    [汇总] 2 场演示, 未回答问题 5 条                     |
|                                                       |
|  季度总结.pptx                                         |
|    [待审阅] 03-22 全员大会  156人  互动率45%  建议6条   |
+------------------------------------------------------+
```

### 7.6 版本关联与追溯

反馈报告与 PPT 版本形成双向可追溯的关联：

| 关联关系 | 说明 |
|---------|------|
| 反馈报告 -> 演示版本 | 报告中记录演示时的 PPT commit hash |
| 修订版本 -> 反馈报告 | 修订 commit message 中引用反馈报告文件名 |
| 反馈报告 -> 修订版本 | 报告状态更新为“已修订”并记录新 commit hash |
| 跨场次汇总 -> 版本区间 | 汇总报告标注所覆盖的版本与场次列表 |

修订提交遵循以下 commit message 格式：

```
fix(slides): 根据反馈优化定价策略页

Feedback-Report: 新品发布会.feedback/2026-03-25_客户现场.md
- 第 3 页: 补充缓存方案说明
- 第 7 页: 调整定价策略表述
- 第 12 页: 增加技术细节
```

### 7.7 技术实现

FeedbackEngine 作为 SlideForge 的子模块，负责互动数据聚合与报告生成：

```
FeedbackEngine (SlideForge 子模块)
  ├─ SessionCollector     — 从 PostgreSQL 提取会话互动数据
  ├─ PageAggregator       — 按页聚合提问/投票/反应/批注
  ├─ CrossSessionMerger   — 跨场次数据合并与趋势分析
  ├─ SentimentAnalyzer    — 弹幕与反应的情感倾向统计
  ├─ ReportGenerator      — Markdown 反馈报告生成
  ├─ GitCommitter         — 报告写入 Git 仓库
  └─ MsgHub Client        — 通知编辑者
```

| 触发方式 | 说明 |
|---------|------|
| **会话结束** | 演示结束 5 分钟后自动生成该场次反馈报告 |
| **手动请求** | 编辑者在 SlidePortal 中手动生成跨场次汇总 |
| **定时汇总** | 每周一自动生成上周所有演示的汇总报告 |

---

## 八、用户界面

### 8.1 文件目录树

SlidePortal 以**文件目录树**为核心导航，与本地文件管理器体验一致：

```
+------------------------------------------------------+
|  我的演示文稿                             [搜索]      |
+------------------------------------------------------+
|  [+] 个人文档 (slides-zhangsan)                       |
|    [+] 2026-Q1                                        |
|      [-] 技术方案汇报.pptx             已转换         |
|      [-] 项目进展周报.pptx             已转换         |
|      [-] 新功能演示.pptx               转换中...      |
|    [+] 模板                                           |
|                                                       |
|  [+] 工作组文档                                       |
|    [+] 市场部 (slides-marketing)                      |
|      [-] 新品发布会.pptx               已转换         |
|      [-] 客户方案-ABC.pptx             已转换         |
|    [+] 研发部 (slides-rd)                             |
|    [+] 公开演示 (slides-public)                       |
|                                                       |
|  [+] 企业模板库 (slides-templates)                    |
+------------------------------------------------------+
```

### 8.2 文档操作

选中 PPT 文件后可执行的操作：

| 操作 | 说明 |
|------|------|
| **在线预览** | 浏览器内直接预览转换后的 Web 幻灯片 |
| **开始演示** | 创建演示会话，生成观众接入二维码，进入全屏 |
| **下载原文件** | 下载 PPT 原始文件（需有权限） |
| **查看历史版本** | 查看 Git 提交历史，可回溯任意版本 |
| **分享链接** | 生成带权限控制的分享链接 |
| **重新转换** | 手动触发重新转换（更换引擎或修复问题） |
| **互动数据** | 查看历次演示会话的互动统计 |

### 8.3 演讲者控制台

演讲者启动演示后，手机端显示控制台：

```
+---------------------------+
|  演讲者控制台              |
+---------------------------+
|                           |
|  < 上一页  3/15  下一页 > |
|                           |
|  +-------------------+    |
|  | 当前页缩略图       |    |
|  |                   |    |
|  +-------------------+    |
|                           |
|  演讲者备注：              |
|  "这里强调 Q1 增长..."    |
|                           |
|  已用时 12:35             |
|                           |
|  [发起投票] [Q&A面板]     |
|  [激光笔]   [结束演示]    |
+---------------------------+
```

---

## 九、转换配置

### 9.1 仓库级配置

每个 Git 仓库根目录的 `.slideforge.yml` 定义转换策略：

```yaml
# .slideforge.yml
conversion:
  default_engine: onlyoffice          # 默认转换引擎
  fallback_engine: libreoffice        # 备用引擎
  high_fidelity_engine: aspose        # 高保真引擎
  complexity_threshold: 5             # 复杂度阈值（超过则用高保真引擎）

fonts:
  embed: true                         # 嵌入字体子集
  fallback_fonts:
    - "Noto Sans SC"
    - "Microsoft YaHei"

output:
  format: revealjs
  image_quality: 85
  image_format: webp
  generate_thumbnail: true
  generate_pdf: true                  # 同时生成 PDF 版本

interaction:
  default_features: [vote, qna, reaction]
  danmaku: false                      # 弹幕默认关闭
```

### 9.2 文件级配置

单个 PPT 可通过同目录 `.meta.yml` 覆盖仓库配置：

```yaml
# 新品发布会.meta.yml
conversion:
  engine: aspose                      # 强制使用高保真引擎

interaction:
  danmaku: true                       # 此演示开启弹幕
  vote_slides: [3, 7, 12]            # 第 3/7/12 页预设投票

publish:
  access: login                       # 需登录观看
  share_expires: "2026-06-30"
```

---

## 十、部署方案

### 10.1 服务部署清单

全部服务运行于**互联网应用服务器**（腾讯云 / 阿里云），数据后端在私有云：

| 服务 | 部署方式 | 运行位置 | 端口 |
|------|---------|---------|------|
| SlideForge 转换调度 | Docker (Node.js) | 互联网应用服务器 | 3010 |
| ONLYOFFICE Document Server | Docker | 互联网应用服务器 | 8000 |
| LibreOffice Headless | Docker (gotenberg) | 互联网应用服务器 | 3030 |
| SlidePortal 演示平台 | Docker (Next.js) | 互联网应用服务器 | 3011 |
| InteractHub 互动中心 | Docker (Node.js) | 互联网应用服务器 | 3012 |
| Redis | Docker（已有） | 互联网应用服务器 | 6379 |
| PostgreSQL | 原生安装（已有） | 私有云 | 5432 |
| Gitea | Docker（已有） | 互联网应用服务器 | 22/443 |
| Keycloak | Docker（已有） | 互联网应用服务器 | 8443 |

### 10.2 Nginx 路由规则

```nginx
# SlidePortal 演示平台
location /slides/ {
    proxy_pass http://127.0.0.1:3011;
}

# InteractHub WebSocket
location /ws/interact/ {
    proxy_pass http://127.0.0.1:3012;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

# SlideForge Webhook（仅限 Gitea 内部调用）
location /hook/slideforge {
    allow 127.0.0.1;
    deny all;
    proxy_pass http://127.0.0.1:3010;
}

# ONLYOFFICE（仅限 SlideForge 内部调用）
location /onlyoffice/ {
    allow 127.0.0.1;
    deny all;
    proxy_pass http://127.0.0.1:8000;
}

# 转换后的静态幻灯片资源
location /slide-assets/ {
    alias /var/www/slide-assets/;
    expires 30d;
}
```

---

## 十一、实施路线图

| 阶段 | 任务 | 预计周期 |
|------|------|--------|
| **第一阶段：基础转换** | ONLYOFFICE + LibreOffice 部署，SlideForge 调度开发 | 第 1-3 周 |
| **第一阶段** | Reveal.js 封装与后处理流水线开发 | 第 2-3 周 |
| **第一阶段** | Gitea Webhook 对接，Git 推送自动触发转换 | 第 3 周 |
| **第二阶段：演示平台** | SlidePortal MVP（目录树 + 在线预览 + 开始演示） | 第 4-5 周 |
| **第二阶段** | 演讲者手机控制台（遥控翻页 + 演讲者备注） | 第 5-6 周 |
| **第二阶段** | 终端适配测试（Android TV / 鸿蒙 TV / Windows / iPad） | 第 6-7 周 |
| **第三阶段：互动系统** | InteractHub 核心开发（WebSocket + 投票 + Q&A） | 第 7-8 周 |
| **第三阶段** | 弹幕与实时反应功能 | 第 8-9 周 |
| **第三阶段** | 观众扫码接入 + 互动数据与页面绑定 | 第 9 周 |
| **第四阶段：质量优化** | 转换质量自动检测（逐页截图对比） | 第 10 周 |
| **第四阶段** | Aspose.Slides 商业引擎集成（高保真场景） | 第 10-11 周 |
| **第四阶段** | 字体管理与嵌入优化 | 第 11 周 |
| **第五阶段：协作增强** | 多组合协作（Fork / Merge Request 流程） | 第 12 周 |
| **第五阶段** | FeedbackEngine 互动数据聚合与反馈报告生成 | 第 12-13 周 |
| **第五阶段** | 反馈看板 + 修订工作流 + 版本关联追溯 | 第 13-14 周 |
| **第五阶段** | 全链路测试与上线 | 第 14-15 周 |
