WP18:PDF、PPTX 与打印的放映隔离
状态:完成(2026-10-17)。阶段:M1。主责:Runtime / 导出。 上层工作项:G03;详见模块计划。本包是该工作项的实施拆分,不是另一份配置契约。
前置与输入
前置完成:WP14、WP17。 字段与行为以统一契约为准;所有依赖编号见执行清单。
修改范围与交付
- 修改范围:OffscreenPageStage、PDF、PPTX 和打印的静态上下文、取消/finally 清理及主画布状态保护。
- 交付物:放映中可生成正确顺序和内容、且不污染主会话的实际导出文件。
- 提交边界:不将网页动画写为 PPTX 原生动画,不改无关图元和字体映射。
完成标准
- [x] 实现及评审覆盖上述修改范围,未超出提交边界。
- [x] 行为验收:离屏页面不自动开始;取消/超时清理;不覆盖用户中途停止意图;主画布页码和剩余时间保持。
- [x] 验证范围:导出服务回归、取消/失败测试及实际 PDF/PPTX/打印产物验证。
- [x] 关联验收:A16;见联调与验收计划。
- [x] 记录代码版本、实际测试命令/结果、未运行项及原因,产物保存到任务专属临时目录。
- [x] 回填本卡状态与证据;阶段能力是否开放由对应阶段出口包决定,单包完成不等于整阶段交付。
建议提交标题:WP18:PDF、PPTX 与打印的放映隔离。通常按一个可评审 PR 实施;若实际改动仍过大,先按输入/输出再拆子包,保留父编号和依赖。
测试环境与命令选择遵循 dev-start-test,不因执行本卡重复启动服务或重置开发数据。
实施记录
- 捕获上下文:OffscreenPageStage 同时在 iframe 的
location.search与 hash 路由写入runtimeCapture=1。执行策略只读取 search,缺少 search 标记时离屏页面会按presentation初始化;hash 标记继续供项目壳切换到RuntimeCaptureLayout并传递runtimeCaptureTicket。 - 取消链路:
CaptureOptions增加signal,OffscreenPageStage.capture把信号与期限传入preparePage;PDF 与打印在逐页捕获、保存前检查取消,取消后不下载、不写完成状态。PDF/打印任务采用retainLockOnCancel,取消后保持占用到finally释放离屏舞台,避免新旧任务共用 iframe。 - 主画布隔离:BrowserPrintService 的全部页打印改为逐页使用离屏舞台,不再
router.push主画布;当前页打印在项目路由下也走离屏舞台,项目外回退当前 DOM 并将动画冻结到最终状态。PDF/PPTX 原有离屏路径补齐信号与取消检查,异常、取消和超时都在finally释放舞台、模型静态帧与 iframe。 - 静态媒体:离屏页面就绪后冻结有限动画并暂停
video/audio、移除autoplay,不改变播放进度;主放映的页码、剩余时间和暂停/停止意图不受导出任务影响。 - 未改协议:
packages/render-contracts与 Renderer 未变;网页动画和自动翻页不会写成 PPTX 原生动画。 - 验证:
pnpm run test:runtime:gate通过(138 files / 1049 passed / 3 skipped,构建通过),新增/更新导出服务用例覆盖信号传递、取消清理、离屏打印与主画布不导航。真实浏览器(项目 118,auto_start=true、2000ms、loop=true)暂停后执行导出:PDF 3 页、301812 字节,3 张 3840×2160 截图按封面/中页/末页顺序嵌入,封面动画块冻结在最终绿色位置;PPTX 3 页、20187 字节,无<p:timing>,16:9 画布,封面绿色块存在;打印文档 3 页顺序正确;取消导出零下载且离屏 iframe 已释放。全过程主画布保持“已暂停 / 1 / 3 / 0:02”,主路由与 hash 导航计数不变,离屏舞台执行上下文始终为capture且无控制条。证据保存在.tmp/wp18/。 - 未运行项:媒体结束翻页、自动结果等待与双屏同步属于 M2(WP24–WP26);完整 M1 能力开放由 WP21 决定。