html-slide-report
Skill1 starsChanged 49 days agoMITView on GitHub
用一份 HTML 做业务汇报幻灯——全屏 scroll-snap 翻页、ECharts 图表、页面内嵌地图,再导出成 PDF 和 PPTX 两套可分发文件。当汇报要同时满足"现场投影讲、打印带回去、文件发出去"三种场合时使用。
- Installs packages
In this repository3 other files it gives its agents.
- excel-data-pipelineSkill
- share-doc-pipelineSkill
- single-file-dashboardSkill
The file
Files
HTML 幻灯式汇报材料
幻灯页面与导出的两套分发件(示例数据):
Image: 效果示例
什么时候用
- 汇报要现场讲(需要全屏、键盘翻页、投影友好);
- 同一份内容还要发出去(需要 PDF);
- 对方可能还要改(需要 PPTX)。
传统做法是做一套 PPT,但 PPT 里的图表是死的、数据一变就得手工重排。这里反过来:HTML 是唯一的事实来源,PDF 和 PPTX 都是从它导出的快照。改数据只需重跑脚本,出图和导出全自动。
代价是导出这一步有点绕——浏览器渲染 → 截图 → 拼装,见下文第 3 步。
第 1 步:幻灯骨架
核心是 CSS scroll-snap,让每一页在滚动时自动对齐整屏,达到翻页效果而不需要写 JS 翻页逻辑:
html { scroll-snap-type: y mandatory; scroll-behavior: smooth; }
.slide {
height: 100vh; scroll-snap-align: start;
display: flex; flex-direction: column;
padding: 56px 72px; box-sizing: border-box;
overflow: hidden;
}键盘导航是十来行 JS:
const slides = [...document.querySelectorAll('.slide')];
let i = 0;
addEventListener('keydown', e => {
if (['ArrowDown','ArrowRight',' ','PageDown'].includes(e.key)) { i = Math.min(i+1, slides.length-1); }
else if (['ArrowUp','ArrowLeft','PageUp'].includes(e.key)) { i = Math.max(i-1, 0); }
else return;
e.preventDefault();
slides[i].scrollIntoView({ behavior: 'smooth' });
});
// 滚动时反向同步页码(用户拖滚动条后页码不能错位)
const io = new IntersectionObserver(es => es.forEach(e => {
if (e.isIntersecting) i = slides.indexOf(e.target);
}), { threshold: 0.6 });
slides.forEach(s => io.observe(s));用 IntersectionObserver 反向同步当前页,不要只用键盘事件维护索引。 用户一旦滚了滚轮,键盘维护的索引就和实际页码脱节了,表现为"按一下方向键跳两页"。
完整可运行的骨架见 references/slide-spec.md。
第 2 步:内容组织
数据前置
把数据表格单独做成一页,放在观点页之前。 观众看到结论之前先看到原始依据,后面所有的分析才有落点。这是这套材料最受认可的一点。
典型页序:
0 封面
1 数据明细表(原始数据,密集但完整)
2 整体趋势分析(第一个观点)
3 明细排查表
4 分项深入分析(第二个观点)
5 地图(空间维度)
6-7 下一步工作计划
8 结束页工作计划要短周期
写"下周做什么"而不是"未来三年规划"。汇报对象要看的是可执行的动作和责任人,不是方向性表述。
数字给到位
保留两位小数的比率、精确到个位的绝对量。"显著改善"没有说服力,"从 18.3% 降到 9.7%"才有。
第 3 步:导出 PDF 与 PPTX
pip install playwright pillow pypdf python-pptx
playwright install chromium # 或用系统 Edge,见脚本里的 USE_SYSTEM_EDGE
python scripts/export_slides.py 汇报.html --outdir 导出流水线是:
Playwright 逐页滚动 → 每页截图(1920×1080,deviceScaleFactor=3)
→ PIL 转 PDF(resolution=150)→ pypdf 合并
→ python-pptx 逐页嵌入 → .pptx四个关键点,每一个都是踩出来的:
① deviceScaleFactor=3 是投影清晰度的下限。 1 倍出来的字在大屏上发虚,3 倍(等效 5760×3240)才够。代价是截图慢、文件大,值得。
② 每页高度取实际 scrollHeight,不要写死 1080。 内容多的页会溢出被截断。但要收口:
true_h = max(1080, min(scrollHeight + 40, 4000)) # 上限 4000 防止异常值撑爆③ PDF 用 PIL.Image.save(..., 'PDF') 逐页存再合并,不要用 page.pdf()。
浏览器直接导 PDF 时,scroll-snap 的整屏对齐会让分页错乱(页数异常、内容被腰斩)。用图片拼反而稳定,而且和 PPTX 共用同一批截图,两套文件内容必然一致。
④ PPTX 直接嵌整页图片,不做可编辑转换。 把 HTML 还原成可编辑的 PPT 元素是没有收益的——排版必然走样,而且没人会在 PPT 里改图表数据。嵌图至少保证"发出去的和讲的一模一样"。需要改内容就改 HTML 重新导出。
第 4 步:交付前检查
导出完必须把 PDF 翻一遍,重点看四件事:
- 有没有页面内容被截断(尤其表格页和长列表页);
- 最后一页能否正常显示(
scroll-snap的经典问题,见下); - 字体有没有回退成宋体(说明指定字体在导出环境不可用);
- 图表有没有因为渲染未完成而空白——导出脚本里每页
wait_for_timeout就是为这个,异步渲染的图表(地图、动画)需要更长的等待。
常见坑
| 现象 | 原因 | 处理 |
| 最后一页滚不到 / 被截掉一点 | scroll-snap 强制整屏对齐,最后一页高度略超视口时无法停稳 | 最后一页加 padding-bottom: 1px 缓解;仍不行就在导出脚本里对该页单独放宽高度上限 |
| 地图页截出来是空白 | 地图瓦片是异步加载的,截图时还没渲染完 | 等地图实例就绪(wait_for_function("() => !!window.map"))再额外等 3—4 秒 |
| 图表数据变了但图没变 | 图表在 load 时才初始化,数据是后注入的 | 先注入数据再初始化图表,或注入后调一次 setOption |
| 导出的 PDF 页数比幻灯页数多 | 用 page.pdf() 导致整屏对齐与分页冲突 | 改用截图 + PIL 拼装 |
| 中文在 PDF 里变方块 | 截图时字体未加载完 | 截图前 page.wait_for_timeout,或把字体转 base64 内嵌 |
| 图例文字被裁 | ECharts 默认 containLabel: false,轴标签超出绘图区 | 给 grid 设 containLabel: true |
目录内容
html-slide-report/
├── SKILL.md
├── scripts/
│ └── export_slides.py 逐页截图 → PDF + PPTX
└── references/
└── slide-spec.md 可运行的幻灯骨架 + 配色/排版规范配色规范、幻灯结构、导航与交互细节见 references/slide-spec.md。
数据准备见 excel-data-pipeline;材料要对外发布时,先过 share-doc-pipeline 的脱敏清单。
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

