# 实现方案 — 2026-04-16-18-51-06 ## 根因分析 `ReportEditor.tsx` 中使用了 `stateRef.current` 作为「草稿自动保存」的数据来源。组件卸载时,`saveDraftToStorage()` 会将 `stateRef.current` 写入 `localStorage`。 但在页面初始化(`useEffect` 和 `useLayoutEffect`)从已保存报告或 draft 恢复数据时,仅通过 `setState` 更新了 React state,**没有同步更新 `stateRef.current` 中的 `videos` 和 `capturedFrames` 字段**。 这导致: 1. 用户首次进入 `/report-editor` 时,数据从 localStorage 正确恢复; 2. 用户离开页面时,`stateRef.current` 仍保存着初始的空数组; 3. 组件卸载触发的 `saveDraftToStorage()` 用空数组覆盖了 draft; 4. 用户再次返回 `/report-editor` 时,系统优先读取被覆盖后的 draft,导致视频分析数据全部丢失。 ## 修改文件清单 | 文件 | 修改类型 | 说明 | |------|---------|------| | `src/pages/ReportEditor.tsx` | 修改 | 在 4 处数据恢复逻辑后追加 `stateRef.current` 同步赋值 | ## 具体代码变更 ### 修改点 1:初始化 useEffect — 从 draft 恢复已有报告(约第 128 行后) 在已有代码: ```tsx setLoadedTemplateId(draft.loadedTemplateId || ''); stateRef.current = { ...stateRef.current, loadedTemplateId: draft.loadedTemplateId || '' }; ``` **追加同步**: ```tsx stateRef.current = { ...stateRef.current, reportData: draft.reportData, videos: draft.videos, capturedFrames: draft.capturedFrames, loadedTemplateId: draft.loadedTemplateId || '' }; ``` ### 修改点 2:初始化 useEffect — 从已保存报告(found)恢复(约第 146 行后) 在设置完 `contentLoadedRef.current = true;` 之后,**追加同步**: ```tsx stateRef.current = { ...stateRef.current, reportData: found, videos: found.videos || [], capturedFrames: found.capturedFrames || [] }; ``` ### 修改点 3:初始化 useEffect — 从 draft 恢复新建报告(约第 176 行后) 与修改点 1 类似,在 `setLoadedTemplateId(draft.loadedTemplateId || '');` 之后,**追加同步**: ```tsx stateRef.current = { ...stateRef.current, reportData: draft.reportData, videos: draft.videos, capturedFrames: draft.capturedFrames, loadedTemplateId: draft.loadedTemplateId || '' }; ``` ### 修改点 4:useLayoutEffect 安全网 — 从 draft 恢复已有报告(约第 677 行后) 在 `setLoadedTemplateId(draft.loadedTemplateId || '');` 之后,**追加同步**: ```tsx stateRef.current = { ...stateRef.current, reportData: draft.reportData, videos: draft.videos, capturedFrames: draft.capturedFrames, loadedTemplateId: draft.loadedTemplateId || '' }; ``` ### 修改点 5:useLayoutEffect 安全网 — 从已保存报告(found)恢复(约第 692 行后) 在 `contentLoadedRef.current = true;` 之后,**追加同步**: ```tsx stateRef.current = { ...stateRef.current, reportData: found, videos: found.videos || [], capturedFrames: found.capturedFrames || [] }; ``` ### 修改点 6:useLayoutEffect 安全网 — 从 draft 恢复新建报告(约第 701 行后) 在 `setLoadedTemplateId(draft.loadedTemplateId || '');` 之后,**追加同步**: ```tsx stateRef.current = { ...stateRef.current, reportData: draft.reportData, videos: draft.videos, capturedFrames: draft.capturedFrames, loadedTemplateId: draft.loadedTemplateId || '' }; ``` ## 风险点 | 风险 | 级别 | 应对措施 | |------|------|---------| | `stateRef` 仍可能在其他未覆盖路径中不同步 | 低 | 已检查所有数据恢复入口(init effect + layout effect),后续若新增恢复逻辑需保持同步习惯 | | `found.videos` / `found.capturedFrames` 为 undefined | 低 | 代码中使用 `|| []` 做防御性处理 | ## 回滚策略 本次修改仅增加 `stateRef.current` 的同步赋值语句,不涉及删除或重构现有逻辑。如出现异常,可直接 `git revert` 回滚。 --- **⚠️ 请审核以上方案,确认无误后回复「确认」或提出修改意见,我将进入测试方案编写阶段。**