33-离线编辑覆盖远端-用版本号和冲突结果保护数据

📅 2026/7/16 19:05:44
33-离线编辑覆盖远端-用版本号和冲突结果保护数据
第33篇离线编辑覆盖远端用版本号和冲突结果保护数据摘要离线编辑覆盖远端通常是提交时只看本地草稿不看打开页面时的远端版本。用户 A 离线改简介用户 B 已经在线改过同一课程A 恢复网络后直接提交就会把 B 的更新覆盖掉。更稳的做法是让草稿携带 baseVersion提交前比较远端版本版本不同就生成冲突结果而不是静默覆盖。一个课程简介编辑页支持离线保存。用户在地铁里改了简介回到办公室联网后一键同步结果把后台刚审核过的新简介覆盖了。后来看代码草稿只保存了文本没有保存它基于哪个远端版本。这篇文章解决四个实际问题如何让离线草稿记录 baseVersion。如何区分可直接提交、需要合并、必须人工确认。如何把冲突变成页面可展示结果。如何验证双端编辑和弱网恢复路径。草稿必须知道自己基于哪个版本exportinterfaceOfflineCourseDraft{courseId:stringbaseVersion:numbertitle:stringsummary:stringeditedAt:number}exportinterfaceRemoteCourseSnapshot{courseId:stringversion:numbertitle:stringsummary:stringupdatedAt:number}baseVersion是离线编辑的安全带。没有它恢复网络后无法判断远端是否已经变化。同步结果要显式表达冲突exporttypeSyncResult|{kind:submitted;version:number}|{kind:conflict;local:OfflineCourseDraft;remote:RemoteCourseSnapshot}|{kind:failed;message:string}不要用一个 boolean 表示同步成功失败。冲突不是普通失败它需要用户或业务规则做选择。提交前先比较版本exportclassOfflineCourseSyncService{constructor(privatereadonlyremote:CourseRemoteRepository){}asyncsubmitDraft(draft:OfflineCourseDraft):PromiseSyncResult{constlatestawaitthis.remote.getCourse(draft.courseId)if(latest.version!draft.baseVersion){return{kind:conflict,local:draft,remote:latest}}constnextVersionawaitthis.remote.updateCourse(draft)return{kind:submitted,version:nextVersion}}}版本不一致时先返回冲突不静默覆盖。页面拿到冲突结果后再展示差异。冲突页面只展示差异和选择exportinterfaceConflictChoice{courseId:stringmode:keep_remote|use_local|manual_mergemergedSummary:string}冲突 UI 不直接写远端。它只收集用户选择最后再交给 SyncService 执行。手动合并也要带最新版本exportclassConflictResolveService{constructor(privatereadonlyremote:CourseRemoteRepository){}asyncresolve(choice:ConflictChoice,remoteVersion:number):PromiseSyncResult{if(choice.modekeep_remote){return{kind:submitted,version:remoteVersion}}constnextVersionawaitthis.remote.updateCourseWithVersion(choice.courseId,choice.mergedSummary,remoteVersion)return{kind:submitted,version:nextVersion}}}合并提交仍然要带最新版本防止用户处理冲突期间远端又被别人改了一次。验证清单离线编辑后远端未变恢复网络能直接提交。离线期间远端被修改提交返回冲突结果。用户选择保留远端本地草稿被清理。用户手动合并提交时带最新版本。冲突处理期间远端再次变化不能静默覆盖。日志只记录 courseId 和版本不记录完整敏感正文。哪些字段可以自动合并哪些必须人工确认不是所有冲突都要弹复杂对比页。可以按字段类型决定。字段推荐策略浏览次数、计数可按规则合并标题、简介人工确认标签集合可做集合合并后提示富文本正文人工对比更新时间使用远端最新值先把字段策略写清楚冲突页才不会变成“全部覆盖”或“全部拒绝”。冲突结果要能被保存用户处理冲突时可能离开页面所以冲突结果也需要一个短期记录。exportinterfaceSavedConflict{conflictId:stringcourseId:stringlocalVersion:numberremoteVersion:numbercreatedAt:number}exportinterfaceConflictStore{save(conflict:SavedConflict):Promisevoidremove(conflictId:string):Promisevoid}这不是长期业务事实只是帮助用户回到冲突处理现场。处理完成后应删除避免下一次同步误判。冲突页要把差异讲清楚冲突不是一句“数据已变化”就够了。用户需要知道本地改了什么、远端现在是什么、继续提交会覆盖什么。展示项作用本地修改时间判断草稿是否还值得保留远端更新时间判断谁的版本更新字段差异看清标题、简介、标签变化操作按钮保留远端、使用本地、手动合并如果冲突页只给“覆盖远端”按钮用户大概率会误点。高风险字段必须让用户看到差异后再决定。同步队列里也要保存 baseVersion离线状态下不一定立刻提交草稿可能先进同步队列。队列项也要带 baseVersion不能只带最终内容。exportinterfacePendingSyncItem{itemId:stringcourseId:stringbaseVersion:numberpayloadText:stringcreatedAt:number}exportinterfacePendingSyncQueue{enqueue(item:PendingSyncItem):Promisevoidremove(itemId:string):Promisevoid}恢复网络后SyncService 从队列取出 item再按 baseVersion 和远端版本比较。这样即使应用重启也不会丢掉冲突判断依据。真实回归路径A 端离线修改简介B 端在线修改同一简介。A 端恢复网络提交必须进入冲突结果。A 端选择保留远端本地 pending item 被清理。A 端选择手动合并提交时再次校验 remoteVersion。合并期间 B 端再改一次A 端不能静默覆盖。日志记录 courseId、baseVersion、remoteVersion不记录完整正文。交付前验收表验收项通过标准版本一致离线草稿能直接提交版本冲突返回 conflict不静默覆盖手动合并再次提交前校验远端版本队列恢复重启后仍保留 baseVersion离线编辑的关键不是让用户随时能写而是恢复网络后不破坏别人已经提交的事实数据。冲突处理后要清理本地队列离线冲突处理完成后别忘了清理本地 pending item 和已保存的 conflict。否则用户下次打开应用时同一个冲突又会出现。exportclassConflictCleanupService{constructor(privatereadonlyqueue:PendingSyncQueue,privatereadonlyconflictStore:ConflictStore){}asynccleanup(itemId:string,conflictId:string):Promisevoid{awaitthis.queue.remove(itemId)awaitthis.conflictStore.remove(conflictId)}}清理动作应该放在冲突提交成功之后。如果提交失败pending item 要保留用户才能继续处理。发布前要模拟多端时序离线冲突不是单机路径。至少要用两个端或两个账号窗口模拟A 打开旧版本B 修改并提交A 离线修改后恢复网络。只有这个时序能证明 baseVersion 真正生效。单端改一遍再提交只能证明普通保存能跑通不能证明冲突保护有效。建议把时序记录成表方便复盘顺序A 端动作B 端动作期望结果1打开课程详情记录 baseVersion无A 保存旧版本号2断网后编辑草稿在线修改并提交远端版本递增3恢复网络后提交无A 端进入冲突结果4手动合并再提交可继续修改再次校验远端版本小结离线提交前先问远端有没有变离线编辑要用版本号保护数据。草稿记录 baseVersion提交前拉远端版本版本不一致就生成冲突结果。用户确认后再合并或覆盖不能把本地草稿当成最终事实直接写回远端。无 | A 保存旧版本号 || 2 | 断网后编辑草稿 | 在线修改并提交 | 远端版本递增 || 3 | 恢复网络后提交 | 无 | A 端进入冲突结果 || 4 | 手动合并再提交 | 可继续修改 | 再次校验远端版本 |小结离线提交前先问远端有没有变离线编辑要用版本号保护数据。草稿记录 baseVersion提交前拉远端版本版本不一致就生成冲突结果。用户确认后再合并或覆盖不能把本地草稿当成最终事实直接写回远端。