Runtime 翻页动画与自动放映实施计划
状态:M0 已实现(WP11、WP12:动画参数解析、过渡完成信号与真实 Chromium 验收);WP13–WP18 已交付调度状态机、执行上下文、Router/就绪桥接、单窗口控制、静态捕获与导出隔离(2026-10-17);WP22–WP26 已交付媒体 Schema/权限链、活动页媒体生命周期、媒体结束翻页、同步协议 v2 与观众唯一调度;WP30 已完成真实媒体、双窗口与捕获回归并开放媒体/演讲者能力(2026-10-18)。2026-10-18 全屏放映统一模型已实施:非全屏为预览、根元素全屏为放映,auto_start 表示进入放映时的初始自动/手动模式,演讲协议升级到 v3。配置由 Backend 提供,字段和覆盖语义以统一契约为准。
实施拆分见工作包执行清单:WP11 动画与信号、WP13–WP16 调度及上下文、WP23–WP26 媒体与双屏、WP31–WP33 长期运行。以下 R 编号保留为上层职责。
1. 现有入口与拆分
- PageTransitionHost.vue:双层动画、方向、快速导航合并及媒体离场暂停。
- RuntimePageStage.vue:RouterView 接入,但尚未上送
settled。 - runtime-session.ts:按 Router 隔离模式、导航意图和错误。
- usePresenterController.ts:跨窗口导航和视图同步。
- VideoViewer.vue、ViewPreview.vue:视频与真实页面预览。
拟在 runtime-shell 下拆分放映控制器、就绪适配、媒体控制和窗口同步模块;不要向已经较大的 ResponsiveLayout.vue、config.ts 或 presenter 控制器持续堆入全部逻辑。
2. 工作包
R01:参数解析与动画完成信号(M0,依赖 B03)
- [x] 消费 Backend 路由产物中的项目默认和叶子生效配置;保留旧产物缺字段时的手动行为和现有过渡兜底。
- [x] 将宿主
settled和渲染错误向上接通,信号携带路径与本次页面 generation,避免旧页完成事件启动新页计时。 - [x] 动画以目标层的过渡完成事件为主要收尾条件,保留有界计时兜底;过滤子元素冒泡事件,无动画/减少动态效果也必须恰好完成一次。
- [x] 明确
settled只表示整页过渡完成,不能替代页面 DOM/资源就绪;初次无动画挂载需在 DOM 提交后报告稳定页。 - [x] 当前页选择器排除离场层和缩略图,保留最多两层、反向推入、快速导航合并和失败恢复。
验收:默认与逐页动画在普通模式、观众窗口和构建产物一致;连续导航不重复完成、不残留旧媒体。
R02:单窗口调度器(M1,依赖 R01)
- [x] 将控制器绑定到 Router 会话而非页面组件,统一持有播放状态、当前路径、generation、剩余时间和计时句柄。
- [x] 实现
stopped、preparing、playing、paused、ended、blocked、error状态及明确的状态迁移;M1 不开放媒体模式。 - [x] 等待“当前路由提交+页面 DOM/必要视觉资源就绪+过渡完成”后开始停留计时;资源失败保留可见错误并暂停,不无限等待。
- [x] 复用现有导航目录和
navigateRuntimePage;只推进可见叶子页,隐藏页和分组不参与自动序列。 - [x] 用单调时钟计算本窗口剩余时间,使用可取消的一次性调度,避免固定 interval 与导航耗时叠加。
- [x] 手动跳页作废旧计时;播放中从新页重计时,暂停中保持暂停;停止保留当前页,重新开始从当前页计时。
- [x] 手动模式页面等待用户操作;末页完成后按项目设置停止或循环,单页循环同样有完整停留周期。
- [x] 普通窗口隐藏时暂停并保留剩余时间,重新可见后等待显式继续;回前台不连跳补课。全屏统一模型下每次进入全屏都开始新一轮会话,
auto_start只决定初始自动/手动模式。
WP13 交付与 Router/DOM 解耦的控制器,WP15 完成 Router 会话绑定、就绪桥接与导航目录接线,WP16 完成可见性暂停、控制条与一次性自动开始入口;上述已勾选项由虚拟时钟、宿主集成与真实浏览器用例覆盖。完整手动连跳与阶段能力开放在 WP21。
验收:暂停/继续不丢剩余时间,过渡和加载不吃停留时间,任何旧回调都不能重复翻页。
R03:执行上下文与操作区(M1,依赖 R02,向 G01 提供上下文契约)
- [x] 引入内部执行上下文,区分放映主画布、单页交互预览、缩略图、捕获和导出;嵌入式普通单页预览优先采用禁自动策略。
- [x] 缩略图、控制台当前/下一页小窗、卡片页、资源/组件预览禁止自动媒体播放;
inert只阻止交互,不能作为禁播实现。 - [x] 捕获和导出强制禁用自动开始、翻页及媒体播放;执行上下文优先级高于项目和页面配置。
- [x] 普通放映提供自动/手动、上一页/下一页、剩余时间/页码、状态、演讲与退出;空格切换自动/手动,系统暂停时继续;预览层空格只翻页。
- [x] 暂停放映同时暂停本会话媒体;只恢复此前正在播放的媒体,不启动用户手动暂停的媒体。
- [x] 不把 Runtime shell 控制器、缩略图或 presenter 内部能力放入公开 Runtime Kit manifest;WP25/WP26 未新增公开导出口,manifest 门禁保持通过。
WP14 已交付上下文解析、宿主传播、媒体禁播守卫与暂停/恢复协调器;WP16 已接入控制条、空格快捷键、可见性/模式清理与当前页媒体暂停/恢复,真实浏览器验证 1440/1180/960px 入口与全屏空格不双触发。WP17 已让 Renderer 捕获导航固定 runtimeCapture=1,并在 render-ready 桥中上报执行上下文与目标路由,真实 PNG 覆盖 poster 与无 poster 视频。WP18 已让 PDF、PPTX 与打印全部使用 capture 上下文的离屏舞台,捕获标记同时进入 search/hash,真实产物验证导出期间主画布暂停状态、页码与剩余时间不变。媒体结束与双屏仍属 M2。
验收:自动放映期间缩略图不抢播、捕获不跳页,卸载/模式切换清理计时和监听器。
R04:媒体生命周期与结束翻页(M2,依赖 B06 的 Schema/权限适配及 R03)
- [x] 当前活动画布内统一收集非循环原生音视频作为完成目标;
media_end主动播放并等待全部结束,没有目标时走停留时间。 - [x]
VideoViewer转发播放、暂停、结束和错误状态,提供可控实例或内部注册;原生 HTML 媒体采用相同规则。媒体事件在实际元素上监听或显式转发,不能依赖ended冒泡。 - [x] 目标页过渡前暂缓媒体启动,过渡完成后按模式执行;离场、取消、页面错误和卸载均停播并移除监听。
- [x] 处理
play()Promise 拒绝,进入blocked提供点击开始;error、断网和media_timeout_ms到期进入错误暂停,提供重试、下一页、停止。 - [x] 区分媒体停止、播放结束和循环;对多媒体、动态新增/移除、视频替换及迟到事件维护同页 generation 内的一次完成集合。
- [x] 自动播放默认不能推断为成功;真实播放状态来自 Promise 和事件。桌面 Chromium 已用有声非静音素材验证;移动端行内播放未验证,不列为已支持。
本期受控范围是当前画布内的原生音视频及 AssetVideo。第三方 iframe 播放器、Web Audio、自定义脚本在画布外创建的音频和任意页面内部定时动画不纳入统一暂停/结束判定承诺;需要适配时单独增加版本化能力与验收,不能用 DOM 扫描宣称已覆盖。
WP23 已交付 page-media-session:活动页根节点内的非循环音视频在实际元素监听,动态增删与替换会刷新集合,事件按页 generation 隔离;play() 区分阻止与错误,暂停/恢复只处理本会话记录的目标,销毁时停播并移除监听。VideoViewer 已转发原生事件并暴露受控元素,未向公开 Runtime Kit 增加新能力。media_end 何时启动、超时与受阻恢复的调度在 WP24 接入。
WP24 已把媒体会话接入调度:就绪后按 media_end 播放并等待完成集合,无媒体或动态清空退回停留时间;超时、失败进入错误暂停,策略阻止进入受阻态,控制条提供重试、下一页和停止。暂停保留媒体时限并只恢复本会话停播的目标,循环背景不参与完成但随暂停/销毁停播;单页循环会重建会话重播。WP30 在真实预览 artifact 中用 4.2 秒有声非静音 WebM 复验:媒体结束 3839ms 后翻页、无媒体回退 1590ms、受阻/错误/超时均可恢复,暂停后跳页保持暂停且无残留播放;移动端行内播放仍未验证。
验收:单/多视频、无视频、循环背景、播放被阻止和中途跳页均按契约执行。浏览器行为参见 Chrome autoplay 说明和 MDN ended 事件。
R05:演讲者双窗口(M2,依赖 R04)
- [x] 普通单窗口由当前窗口调度;双窗口由观众窗口唯一调度,控制台只发命令并显示状态,不运行第二个推进定时器。
- [x] 扩展现有 BroadcastChannel/localStorage 兜底消息,携带协议版本、频道/产物身份、owner epoch、命令 ID、递增 revision、当前路径、状态和剩余毫秒。
- [x] 新窗口 ready 后发送状态快照,重建本地时钟基准;不跨窗口直接比较
performance.now(),重复和过期消息必须去重。 - [x] 进入/退出演讲模式先暂停,再交接状态;调度权交接必须先失效旧 owner。观众窗口未就绪或关闭时控制台保持暂停,重新打开需显式继续;观众窗口必须全屏后才允许开始放映。
- [x] 控制台隐藏不暂停仍可见的观众窗口;观众窗口隐藏/失去可执行条件时暂停。不能只依据控制台
visibilitychange控制观众。 - [x] 全屏退出本身不重置播放进度;现有演讲计时面板继续表示演讲用时,与放映剩余时间分开。观众窗口退出全屏会暂停放映并恢复全屏提示。
- [x] 控制台手动跳页、观众自动推进和恢复都经过统一控制器,避免消息回声与双重计时;观众窗口只读,不注册本地播放/翻页快捷键。
- [x] 进入演讲时继承当前页和自动/手动模式;控制台通过同步协议 v3 回显
autoAdvanceEnabled并发送set-auto-advance。
WP25 已交付协议 v2 与纯处理器:信封携带频道/产物身份、owner epoch、revision、命令 ID 和完整播放快照;接收端在应用前拒绝旧版本、身份不匹配、重复、旧 revision 与旧 owner,并用本地到达时间重建 deadline。控制器的 playbackSnapshot/remotePlayback 已暴露给 WP26;WP26 在信封中追加 role 并按角色隔离 owner 水位。
WP26 已把观众窗口设为唯一调度者:显示宿主以 autoStart: false 启动,只执行控制台命令;控制台只回显观众状态与剩余时间。命令带目标 owner,旧观众窗口忽略;协议信封增加 role,观众只接受控制台来源的导航,owner 水位按角色隔离。观众先加载时补发一次身份回执,解决控制台晚加载的未连接问题;观众隐藏暂停、重新可见后显式继续,控制台隐藏不影响观众,全屏变化不重置进度。真实 Chromium 双窗口证据见 WP26 实施记录。
全屏统一模型把观众窗口的启动条件收紧为“根元素全屏”,并移除观众页本地键盘;主窗口在进入演讲时退出全屏,控制台传输栏合并自动/手动、翻页和放映状态。协议 v3 在播放快照中加入 autoAdvanceEnabled,新增 set-auto-advance 命令;双窗口必须同构建版本。
控制台传输栏按钮在观众窗口全屏前禁用,但控制台方向键/空格不受该门禁限制,仍向已连接的观众发送命令(设计意图:演讲者无需先聚焦按钮;观众侧对 start/resume 要求全屏,其余命令在放映未启动时被吸收)。重新打开的观众窗口按项目 auto_start 初始化,不继承控制台此前的临时自动/手动切换,控制台按观众回执刷新显示(设计意图:观众窗口以构建产物配置为基准,避免跨窗口残留状态)。
页面内元素(视频、图表等)全屏期间 fullscreenElement 不是根元素,放映状态保持不变并继续推进;退出该元素全屏后 Chromium 不恢复根全屏,fullscreenElement 为空,按退出全屏结束本次放映并回到预览。浏览器原生 F11/菜单全屏属于浏览器级全屏,不写 document.fullscreenElement,因此不进入放映;进入放映只有页面内“进入放映”按钮一条路径。
WP30 在真实预览 artifact 的演讲者模式下复验媒体推进:观众窗口为唯一调度者,媒体结束后推进到下一页,控制台跟随;控制台隐藏时观众继续,观众隐藏后暂停并需显式继续,关闭观众后控制台回显“已关闭”并暂停。完整 A21–A23 证据见 WP30 实施记录。
验收:控制台与观众状态一致、只有一次自动翻页,关闭重开和重复消息不会抢占或恢复旧播放。
R06:本地构建产物长稳(M3,独立验证)
- [x] 定义本地放映入口:通过普通用户鉴权下载不可变构建产物 ZIP,按产物 base 在本地静态服务放映;远端构建访问入口、构建访问票据/按构建 Cookie 和代理不属于 M3,由独立代理服务另行设计验收。
- [x] 验证本地服务中断、浏览器重载/崩溃后的显式恢复和失败提示,不引入无限重试或自动修改快照;浏览器重载路径已实测,崩溃后按同一重载路径重新进入,未注入 renderer crash。
- [x] 在目标浏览器验证防休眠与退出清理,权限被拒时回退为普通放映;不默认申请或承诺所有设备可用。
- [x] 完成多轮循环的媒体句柄、内存和监听器长稳验证;验收通过前不宣传全天无人值守或产品级远端放映。
WP31–WP33 已在真实构建任务 13(SHA-256 73580772e85a0f75aa3f783f9ae2b4c7b0c5894d6fd2285ead8d6eadb12807de)上完成本地验证:有头 Chromium 148.0.7778.96(Playwright 1.60.0,Windows 10.0.26300 x64,1280×720)连续 61.08 分钟、553 次自动翻页(约 138 轮);JS 堆 8.4→8.4MB、浏览器进程树 RSS 704.2→703.5MB、DOM 139–141、监听器低水位 66→66、媒体元素最大 2、活动计时器最大 3,外部输入 0。隐藏 15 秒、冻结/pageshow 20 秒、本地服务中断重试与浏览器重载均显式恢复;屏幕锁在有头浏览器持有,权限拒绝回退由 WP32 覆盖。完整证据与支持边界见 WP33 实施记录。该结论仅覆盖本地构建产物和限定桌面环境,不开放产品级远端无人值守。
R07:全屏放映统一模型(M3 后收敛,2026-10-18)
- [x] 非全屏为预览、根元素全屏为放映:控制器只在根元素全屏时创建;退出全屏销毁控制器、媒体与计时,当前页保持不变。
- [x]
auto_start改为进入放映时的初始自动/手动模式;PlaybackController增加会话级切换,手动只停止页面推进,不暂停媒体。 - [x] 放映控制条统一上一页、自动/手动、下一页、页码、状态、剩余时间、演讲与退出;预览态不显示控制条;放映中默认收起,指针进入窗口底部时显示、移开隐藏,暂停/错误/受阻/结束态保持显示。
- [x] 键盘归属:键位由
runtime/src/runtime-shell/keyboard/keyboard-map.ts统一维护;预览与放映均为空格/方向键/上下键/PageUp/PageDown 翻页,Home/End跳首末页,数字键跳页;预览另有O卡片模式、F进入放映、Shift+P演讲,放映保留Shift+P;不拦截 F11(F11/浏览器菜单全屏不进入放映);页面内元素全屏期间放映继续,退出该元素后按无全屏元素结束放映。 - [x] 演讲者模式观众窗口唯一调度,必须全屏后开始;主窗口退出全屏进入控制台;观众窗口只读;控制台传输栏合并翻页、自动/手动与状态;预览工具栏与放映控制条均可进入,预览入口按项目
auto_start起步,放映入口继承当前模式。 - [x] 演讲同步协议升级到 v3,快照携带
autoAdvanceEnabled,新增set-auto-advance;从放映进入演讲时继承当前页和模式。 - [x] Editor 文案与用户/开发文档同步;无人值守入口限制在 WP31/WP33 中补充。
自动化验证:Runtime 全量 143 个测试文件、1121 通过、3 跳过,vue-tsc -b 通过;虚拟时钟与组件测试覆盖自动/手动切换、媒体继续、手动页、预览无控制器、全屏进入/退出、控制条命令、工具栏按钮聚焦时方向键翻页、协议 v3 与观众全屏门禁。真实桌面 Chromium 双窗口验证 38/38 通过,覆盖预览/全屏切换、自动↔手动、演讲唯一调度、观众只读与退出全屏暂停,证据见验收计划。
3. 验证安排
纯控制器用虚拟时钟覆盖计时、暂停、作废回调、循环和状态迁移;挂载测试覆盖动画信号、上下文传播及媒体清理。真实浏览器验收动画、视频、权限、双窗口和缩放,不能仅依赖 JSDOM。具体场景、阶段门槛和证据见验收计划。