Files
Mdeical_Sur_Report/过往经验/实现方案-2026-04-16-20-33-12.md

3.7 KiB
Raw Blame History

实现方案 — 2026-04-16-20-33-12

根因分析

autoCaptureFramesfor 循环内部,自动插入逻辑使用了:

if ((settings.autoInsertDelay || 0) > 0) {
  await new Promise<void>(r => setTimeout(r, (settings.autoInsertDelay || 0) * 1000));
}

await 会暂停整个 for 循环的执行,导致:

  1. 关键帧摘取被强制暂停,等待延迟结束;
  2. 所有帧必须一张一张串行处理,整体耗时 = 摘取时间 + 插入延迟 × 插入帧数;
  3. 用户体验上感觉"卡顿"或"慢"。

修改文件清单

文件 修改类型 说明
src/pages/ReportEditor.tsx 修改 autoCaptureFrames 中自动插入逻辑改为 setTimeout 非阻塞执行

具体代码变更

变更:autoCaptureFrames 中的插入逻辑(约第 523-535 行)

当前代码:

if (settings.autoInsertFrames && settings.autoInsertFrameIndices?.includes(i) && editorRef.current) {
  if ((settings.autoInsertDelay || 0) > 0) {
    await new Promise<void>(r => setTimeout(r, (settings.autoInsertDelay || 0) * 1000));
  }
  const emptyPlaceholder = editorRef.current.querySelector('.image-placeholder:not(.has-image)') as HTMLElement | null;
  if (emptyPlaceholder) {
    emptyPlaceholder.innerHTML = `...`;
    emptyPlaceholder.classList.add('has-image');
  }
}

修改为:

if (settings.autoInsertFrames && settings.autoInsertFrameIndices?.includes(i)) {
  const baseDelay = (settings.autoInsertDelay || 0) * 1000;
  const insertOrderIndex = settings.autoInsertFrameIndices.indexOf(i);
  const actualDelay = baseDelay > 0 ? baseDelay * (insertOrderIndex + 1) : 0;

  setTimeout(() => {
    if (!editorRef.current) return;
    const emptyPlaceholder = editorRef.current.querySelector('.image-placeholder:not(.has-image)') as HTMLElement | null;
    if (emptyPlaceholder) {
      emptyPlaceholder.innerHTML = `
        <span class="delete-btn" contenteditable="false">×</span>
        <img src="${newFrame.dataUrl}" style="max-width: 100%; height: auto; display: block; margin: 0 auto;" draggable="false">
      `;
      emptyPlaceholder.classList.add('has-image');
      contentRef.current = editorRef.current.innerHTML;
      saveDraftToStorage();
    }
  }, actualDelay);
}

效果:

  • for 循环全速运行,不再被插入延迟阻塞;
  • 每张需要插入的帧按顺序延迟(第 1 张 delay第 2 张 2×delay...),避免同时插入;
  • setTimeout 回调中实时查询 DOM 获取最新的空 placeholder
  • 插入后同步 contentRef.current 并保存草稿。

附加变更:移除循环后的批量 contentRef 更新

当前代码在循环结束后:

if (settings.autoInsertFrames && editorRef.current) {
  contentRef.current = editorRef.current.innerHTML;
}

由于每个 setTimeout 回调内部已经单独更新 contentRef 和保存草稿,且循环结束时可能 setTimeout 尚未执行,这句批量更新既不及时也可能遗漏。建议移除或保留不影响功能。为简化逻辑,选择保留但无实质影响,因为非阻塞的 setTimeout 回调会各自负责自己的保存。

风险点

风险 级别 应对措施
setTimeout 回调执行时 placeholder 已被用户手动填充 回调中实时查询 .image-placeholder:not(.has-image),找不到则跳过,不会覆盖用户内容
多张图片按顺序延迟插入时,用户快速离开页面 每次插入后都调用 saveDraftToStorage(),已插入的图片会被保存;未执行的 setTimeout 自然丢弃

回滚策略

修改范围极小,仅涉及 autoCaptureFrames 中的几行代码。如有异常可直接 revert。