Files
TrueGrowth/docs/PPT_FRAME_DELETE_REORDER_LESSONS.md

4.2 KiB
Raw Blame History

PPT 页面删除后自动重排经验

更新日期2026-04-27

背景

PPT 页面底层是 Frame 元素。用户既可以在 PPT 编辑面板中删除页面,也可以在画布里选中 Frame 后按 Delete / Backspace,或通过画布浮动工具栏删除。只在面板按钮里处理重排,会导致不同删除入口行为不一致。

经验

1. 删除后的重排应放在画布删除链路,而不是单个 UI 入口

Plait 的键盘删除和工具栏删除最终都会走 board.deleteFragment(elements)。在 with-frame 插件里包一层 board.deleteFragment,可以覆盖:

  • PPT 编辑面板删除
  • 画布选中 Frame 后键盘删除
  • 画布浮动工具栏删除
  • 后续其它直接调用 board.deleteFragment 的入口

这样比在每个按钮回调里补重排更稳,也避免重复实现。

2. 删除前必须先做轻量快照

删除后 Frame 已从 board.children 移除,无法再可靠恢复原顺序和网格左上角。因此应在调用原始 deleteFragment 前记录:

  • 被删除的根级 Frame ID
  • 删除前有序 Frame 列表
  • 删除后的剩余 Frame ID 顺序
  • 当前 PPT 网格起点
  • 当前每行列数

快照只保存 ID、坐标和数字不复制页面内容避免额外内存占用。

3. getDeletedFragment 负责补齐 Frame 内容,deleteFragment 负责后置重排

getDeletedFragment 适合根据当前选中的 Frame把绑定到 Frame 的元素一起加入删除集合。

deleteFragment 更适合做重排,因为它能拿到最终删除集合,也能覆盖直接传入 elements 的删除调用。两者职责分开后,面板删除和画布删除不会出现漏删内容或漏重排。

4. 顺序源应优先使用 pptMeta.pageIndex

删除后重新排列时,应按 pptMeta.pageIndex 排序,缺失时回退到画布中的源顺序。重排完成后重新写入连续的 pageIndex,保证导出、播放、列表展示继续一致。

5. 移动 Frame 时必须带着绑定内容一起移动

自动重排不是只改 Frame 坐标。Frame 内图片、文本、媒体等内容也要一起移动,否则画布视觉会散开。

做法是删除后对剩余 Frame 收集关联元素,移动 Frame 时同步移动其关联内容,并在移动后调用 FrameTransforms.updateFrameMembers 修正绑定关系。

实现要点

  • with-frame 初始化时保存原始 deleteFragment
  • 删除前调用 collectPPTFrameDeletionReflowSnapshot(board, data)
  • 删除后调用统一的 reflowPPTFramesAfterDeletion(board, snapshot)
  • 重排使用已有 getPPTFrameGridPositionloadPPTFrameLayoutColumns
  • 只有删除根级 Frame 且仍有剩余 Frame 时才重排,删除普通元素不触发。

注意事项

  • 不要在 afterChange 里反推删除了哪些 Frame这里缺少删除前上下文。
  • 不要把重排逻辑只写在 FramePanel,否则画布删除入口会遗漏。
  • 不要复制或缓存 Frame 内容快照,删除前记录轻量元数据即可。
  • 不要重命名用户自定义页面名,只更新 Frame 1 / Slide 1 / PPT 页面 1 这类默认名。

验证建议

pnpm --dir packages/drawnix exec tsc -p tsconfig.lib.json --noEmit --pretty false
pnpm --dir packages/drawnix exec eslint src/plugins/with-frame.ts
git diff --check

手动验证:

  1. 生成多页 PPT。
  2. 在 PPT 编辑面板删除中间页,剩余页面自动补位并连续编号。
  3. 在画布里选中中间页 FrameDelete / Backspace,剩余页面自动补位并连续编号。
  4. 确认每页内部图片和文本仍跟随 Frame 移动。

提交备注模板

问题描述:
- PPT 页面只在面板删除后重排,画布中删除 Frame 后页面空位和 pageIndex 没有自动收敛。

修复思路:
- 在 with-frame 中统一包装 board.deleteFragment删除前保存剩余 PPT 页面顺序和网格起点,删除后自动重排并重新编号。
- 保留 getDeletedFragment 负责补齐 Frame 绑定内容,避免删除入口分散。

更新代码架构:
- 将 PPT 页面删除后的重排能力下沉到 Frame 插件层,覆盖面板、键盘和画布工具栏删除入口。
- 重排只使用轻量 ID/坐标快照,不复制页面内容,避免高并发文件处理场景下的额外内存压力。