HTML Report PPT 是一个本地运行的网页汇报工具:内容写在结构化 JSON 里,浏览器负责像 PPT 一样展示,编辑器负责增删页面、替换图片和自动保存。它适合组会汇报、论文进展、项目复盘这类“经常改、经常讲、需要图文并排”的材料。
这个仓库只保留通用模板和运行代码。你的真实汇报内容、未公开图片和临时草稿应该放在私有目录,或使用 .local.json / assets/uploaded/ 这类默认不会提交的路径。
前端页面不写死任何具体内容。content/reports.json 负责登记有哪些汇报,每一份汇报再指向一个独立 JSON 文件。比如默认的 starter_deck 指向 content/report.json,新建的组会汇报可以指向 content/reports/group_meeting.json。
这样做的好处是:你可以长期维护同一套展示和编辑界面,只替换内容包。一次组会、一轮论文计划、一次实验复盘,它们都可以共享相同的页面结构、图片上传和自动保存逻辑。
常用页面有两种:图文页和纯文字要点页。图文页左侧放主图,右侧放一句核心判断和若干要点;纯文字页没有图片时会自动扩展成整页文字布局。
一个典型场景是实验汇报:你把关键曲线贴到左侧,右侧只写“这张图改变了什么判断”。另一个场景是开题讨论:没有图的时候直接写结论、风险和下一步计划。页面结构会跟着内容自动调整,不需要每一页手写 HTML。
编辑页支持直接双击改标题、主句、要点、讲稿备注、公式和图片。修改后会自动写回当前汇报 JSON;图片会上传到 assets/uploaded/,JSON 里只保存图片路径。
这意味着内容文件仍然是普通文本,可以进 Git、做 diff、回滚版本;图片则作为外部资产管理,避免把大段二进制内容塞进 JSON。
在项目根目录执行:
uv run python server.py如果 8765 端口被占用,可以换一个端口:
$env:REPORT_PORT=8766
uv run python server.py如果没有使用 uv,也可以直接运行:
python server.py启动后访问:
- 展示页:
http://127.0.0.1:8765/ - 编辑页:
http://127.0.0.1:8765/editor - 指定汇报展示:
http://127.0.0.1:8765/?report=<report_id> - 指定汇报编辑:
http://127.0.0.1:8765/editor?report=<report_id>
推荐在编辑页点击顶部“新建PPT”。系统会复制 content/reports/new_report_template.json 的结构,生成新的 content/reports/<report_id>.json,并把它登记到 content/reports.json。
也可以手动复制模板文件,再在 content/reports.json 里添加一项:
{
"id": "group_meeting",
"title": "组会汇报",
"subtitle": "本周进展与下周计划",
"file": "reports/group_meeting.json",
"description": "一份新的组会汇报。"
}web/index.html 和 web/editor.html 都加载同一个 web/app.js。页面启动后,前端先请求 /api/reports 获取汇报清单,再根据 URL 里的 report 参数请求 /api/report?report=<report_id>。
展示页拿到 JSON 后把 modules 渲染成一页页内容。编辑页拿到同一份 JSON 后,把文本、图框、公式和页面顺序变成可编辑状态。
server.py 是一个轻量本地服务,主要做四件事:
- 读取
content/reports.json,告诉前端当前有哪些汇报。 - 读取和保存每一份
content/*.json汇报内容。 - 接收图片上传,把文件写入
assets/uploaded/。 - 提供
web/和assets/下的静态文件,并关闭缓存,方便开发时刷新生效。
核心接口如下:
| 方法 | 路径 | 作用 |
|---|---|---|
GET |
/api/reports |
返回汇报清单 |
GET |
/api/report?report=<id> |
返回指定汇报内容 |
POST |
/api/report?report=<id> |
保存指定汇报内容 |
POST |
/api/reports |
新建汇报 |
POST |
/api/reports/rename |
重命名汇报 |
POST |
/api/reports/delete |
删除汇报 |
POST |
/api/upload |
上传或粘贴图片 |
前后端之间不传 HTML 片段,而是传结构化数据。最重要的字段是:
meta:标题、副标题、语言和展示模式。modules:每一页汇报内容,包括标题、核心问题、主句、要点、正文、公式和图片。visuals:图片槽位,只保存路径、占位状态和说明文字。
这一层契约让代码和内容分开。前端只关心“如何渲染一个模块”,后端只关心“把 JSON 读出来、存回去”,真正的汇报内容留在 content/ 里。
开源时建议维护一个独立目录或独立 Git 仓库,而不是直接把个人汇报目录推上 GitHub:
html-report-ppt/
server.py
web/
content/
report.json
reports.json
reports/new_report_template.json
assets/
uploaded/.gitkeep
真实汇报可以放在另一个私有目录,或者放在 content/private/、content/reports/*.local.json 这类 .gitignore 已经忽略的位置。
提交通用代码、模板内容和少量占位文件。比如 web/app.js、web/style.css、server.py、content/reports/new_report_template.json 都应该进入开源仓库。
不要提交真实组会内容、论文未公开细节、实验截图、导师评论、临时草稿和上传图片。assets/uploaded/ 默认被忽略,只保留 .gitkeep 让目录存在。
具体地说,如果你做了一份内部汇报,应该把它保存为 content/reports/my_report.local.json,图片放进 assets/uploaded/。这样你在本地能正常使用,Git 默认不会把它们带到公开仓库。
.
├── server.py # 本地 HTTP 服务与 JSON/API 文件读写
├── web/
│ ├── index.html # 展示页入口
│ ├── editor.html # 编辑页入口
│ ├── app.js # 前端渲染、编辑、上传、自动保存逻辑
│ └── style.css # 展示与编辑样式
├── content/
│ ├── reports.json # 多汇报入口清单
│ ├── report.json # 默认示例汇报
│ ├── editor_schema.yaml # 编辑字段约定
│ └── reports/
│ └── new_report_template.json
└── assets/
└── uploaded/ # 本地上传图片目录,默认不提交图片
这个项目追求“本地零依赖可跑”,所以后端只使用 Python 标准库,运行时直接读写 JSON。editor_schema.yaml 目前是字段说明,不是运行时强校验器。
如果后续要增强,最自然的方向是:增加导出静态 HTML、复制当前汇报、导入 Markdown、以及把 YAML 和 JSON 的同步流程做成脚本。