This commit is contained in:
jiahong
2026-03-22 15:19:22 +08:00
parent e6db29485b
commit e303bb868a
6 changed files with 3462 additions and 103 deletions
@@ -0,0 +1,900 @@
# PPT 文档导入与呈现服务 — 规划设计及实施方案
## 一、概述
### 1.1 背景与痛点
PPTPowerPoint / 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
├─ 路线 BPPT → PDF → HTML(两步转换)
│ └─ LibreOffice → pdf2htmlEX
├─ 路线 CPPT → 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/DownReveal.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 周 |