过期响应不能覆盖当前编辑内容

**「刚写的字被回退」不是文件写错了,而是异步保存返回顺序不可靠:旧请求晚回来时,把过期的 `content_md` 又合并回了前端内存。** 修法:本地输入给正文版本号 +1,发起保存时记住版本号,返回时若当前版本已更新,则**不允许这次返回覆盖正文**。

一、链路与故障点

CodeMirror(受控,value={note.content_md})
  ← React state(内存里的笔记对象)
  ← 后台 debounce 写 vault 文件

用户输入 A → 内存 A → 后台保存 A;继续输入 B → 内存 AB → 保存 AB。若「保存 A」比「保存 AB」更晚返回,旧代码把 {...n, ...patch, updated_at: now} 合并回内存,patch 里带着旧 content_md,CodeMirror 收到 value=A,画面回退。

二、为什么保存返回本来就要回写内存

保存成功带回的是只有后端才知道的结果:updated_at(列表排序/时间显示)、title 变化导致的 slug / 文件名变化(untitled.md → 项目复盘.md)、content_loaded 状态。所以不能「保存返回就一律不回写」。

正确边界:

内容能否回写
updated_at / slug / id / content_loaded✅ 回写
content_md仅当没有更晚的本地输入时才允许

一句话:保存成功可以更新元信息,但不能用过期正文覆盖正在编辑的正文。

三、同源的显示问题:live preview 由光标位置决定

Markdown live preview 里 --- 与横线同时出现,是因为规则写成了「光标在本行:显示 ---,但仍然画横线」。改成光标在本行只显示源码 ---,离开本行才隐藏源码、只显示渲染结果,才是 Obsidian 那种体验。

两者共享同一主题:编辑器显示什么,要由「本地最新状态 / 光标位置」决定,而不是由过期的远端返回或固定的渲染规则决定。

相关