Skip to content

Latest commit

 

History

History
115 lines (81 loc) · 8.05 KB

File metadata and controls

115 lines (81 loc) · 8.05 KB

v0.10.1 — 第十阶段补丁:编辑机制修复 + 笔记图片显示

状态: 规划定稿(2026-08-21 三轮探讨定稿) 目标: ① 修复 v0.10.0 编辑模式的三处语义矛盾与两处实现缺陷(不推翻 Ctrl+E 机制); ② 让笔记显示图片——存量配图行显示 + 本地图片插入 + 会话图自动插入验证加固。 依据: v0.10.0 交付代码审查(2026-08-21)· v0.10.0 状态一致性规则(版本快照只在显式保存/AI 采纳时建立)· 产品定位"学习的枢纽"(浏览为主场景、内容为机器生成 Markdown 非从零写作) 关联: v0.10.0(本版修复其缺陷)· v0.7.3 屏配图(REQ-160)· v0.8.0 M4 版本化(REQ-144)· assetProtocol 配置


一、探讨结论(2026-08-21 三轮)

1.1 编辑机制复杂度探讨

裁决:保留 Ctrl+E 双向切换机制(Obsidian 实证"读用预览、写用源码",toggle 心智简单), 不推翻。复杂度真实来源是叠加的"保存/版本"语义,共发现三处自相矛盾 + 两处实现缺陷:

# 问题 证据 定级
1 数据串写:编辑中点击左侧其他笔记 → 旧内容覆盖新笔记(NoteEditView 内部 state 不随 prop 重置) NotesPage 列表点击只 setSelected 不退出编辑 P0 真实 bug
2 「Ctrl+S 建版本」文案假象:前端 createVersion 参数未传后端,4 条保存路径后端行为全同(每次 update_note 无条件建版本) NoteEditView saveDraft vs commands.rs update_note P0 规范偏离
3 版本噪音:versioned_save 无内容去重,30s 自动保存/失焦也建版本,污染版本时间线 db_notes_versions.rs P1
4 「取消」假取消:按钮语义是"取消"行为是无条件保存草稿后退出 NoteEditView handleCancel P1 语义矛盾
5 Ctrl+E 实现分散:window/textarea 双监听 + effect 依赖 [selected, editing] 反复重绑 NotesPage/NoteEditView P2
6 Ctrl+Shift+S 双义:课堂页=截图、编辑器=拆分段(页面互斥下不触发) ClassroomPage/NoteEditView P3 登记不改

1.2 浏览态价值探讨

裁决:笔记=机器生成、浏览为主场景 → 浏览态必须从"信息消费"升级为"学习加工"(主动回忆 + 再次出发)。 浏览态增值任务移交 0.11.0(段落级主动回忆标记/回顾流/健康度/勾选进度四候选)。

1.3 图片功能选型探讨

裁决:一步到位(显示 + 本地插入 + 会话图自动插入验证);图片引用统一"data_dir 相对引用"约定; 解析校验在 Rust 收口(resolve 命令)。


二、编辑机制修复包

# 修复 修法 提交
F1 串写 列表点击/新建时退出编辑态;NoteEditView 卸载时 dirty 自动保存(dirtyRef);key={note.id} 兜底强制重建 本次
F2 版本参数接通 update_note 增 create_version: Option;false 走轻量更新(只刷新 title/content/updated_at);前端 saveDraft 传参;任务勾选回写传 false(v0.10.0 规范"勾选不建版本") 本次
F3 版本去重 update_note 显式保存路径:内容与最新版本相同 → 跳过 versioned_save(防 Ctrl+S 空保存) 本次
F4 取消→完成 「取消(Ctrl+E)」改名「完成(Ctrl+E)」(保存草稿后退出,行为不变语义诚实);补 ESC 退出编辑 本次
F5 实现收敛 Ctrl+E window 监听 handler 稳定化(ref 持有,消除 [selected, editing] 反复重绑) 本次
F6 Ctrl+Shift+S 冲突 登记不改(页面互斥;0.11 引入同屏能力前必须处理) 登记

三、笔记图片功能

3.1 现状(已有 70%,缺口在新笔记页)

  • ✅ 图片生成:关键帧归档 data_dir/session-images/{sid}/full/{ts}.webp
  • ✅ 配图行内嵌:规则版 - ![画面 N](session-images/{sid}/full/{ts}.webp)(note_filter);AI 精修 F1 丢图合并;产物转笔记 ![关键帧](full/{ts}.webp) / ![步骤](image)
  • ✅ 会话侧视图显示:baseUrl + convertFileSrc(ArtifactView/ImageGallery 等)
  • ❌ v0.10.0 新笔记页:ReactMarkdown img 裸传递,session-images/... 相对引用在 WebView 加载失败
  • ⚠️ NotePreviewView baseUrl 拼接疑点:session-images/ 前缀重复拼接(配图行格式与 baseUrl 基准不一致)

3.2 新命令(Rust,全部校验在服务端收口)

命令 职责 安全约束
resolve_note_image(noteId, src) -> Option<String> Markdown src → 可 convert 的本地绝对路径 三规则:session-images/ 前缀(sid==笔记 session_id)、notes-images/ 前缀(nid==noteId)、裸 full|thumbs/(按笔记 session_id);拒绝 .. 穿越;不匹配返回 null
import_note_image(noteId, sourcePath) -> String 本地图复制进 data_dir/notes-images/{nid}/ 并返回相对引用 源存在 + 扩展名白名单(png/jpg/jpeg/webp/gif)+ 大小上限 10MB + 重名序号;零新增 fs 权限(dialog:default 已有)
app_data_dir() -> String 暴露 data_dir(NotePreviewView 拼接用) 只读返回

3.3 前端改动

  • NotesPage:img 渲染器 → 新组件 NoteImage(http(s)/data: 直出;其余 async resolve → convertFileSrc;失败 → alt + 占位不破版面);点击 → 复用 ImagePreviewOverlay 放大
  • NoteEditView:「图片」按钮拆分「🖼 本地图片」(dialog.open → import_note_image → 光标插入 ![图片](notes-images/...))/「🔗 链接」(保留 prompt URL)
  • NotePreviewView:配图行前缀判断(session-images/ → dataDir + src;其他相对 → baseUrl + src;http → 直出)

3.4 会话图自动插入:验证加固

三路生成管线均已内嵌配图(规则版/AI 精修 F1/产物转笔记),本次验证 + resolve 三规则格式兼容, 确保历史笔记与新建笔记全部可显示。手动笔记无会话图,不适用自动插入。

3.5 错误处理

  • 图片文件被删 → resolve 空 → alt + 占位(不破版面)
  • 越权引用(A 笔记引 B 会话图)→ 拒绝返回 null
  • 插入失败(源不存在/格式不支持/超限)→ 明确错误提示,不落脏数据

四、技术选型决策记录

决策点 结论 被否方案
图片引用格式 data_dir 相对引用(session-images/…、notes-images/…) 绝对路径(不可移植);data URL(膨胀/编辑污染)
解析位置 Rust resolve 命令收口(前缀白名单+穿越防护+归属校验) 前端约定拼接(防御弱)
插入入口 本地文件 dialog + 复制进 data_dir(硬约束:assetProtocol scope=$APPDATA/**) 会话图手动选择器(自动已覆盖,0.11 再评)
会话图插入 自动(生成管线内嵌已有,验证加固) 编辑态手动插图

五、里程碑与验收标准

步骤 内容 验收
M1 后端:update_note 版本参数 + 去重 + 三新命令 + 单测 单测覆盖:版本参数分支/去重/resolve 三规则+穿越+归属/import 白名单+超限+重名;cargo test 全绿
M2 前端:NoteEditView 修复 + NotesPage 修复 + NoteImage + 预览 编辑闭环:串写无复现、Ctrl+S 真建版本、自动保存不建版本、ESC 退出、完成按钮
M3 图片全链真机验收 旧笔记配图显示、新转笔记自动带图、本地插入、点击放大、图片删除降级
M4 回归 cargo clippy 干净;前端 tsc/build 通过;v0.10.0 验收项不劣化

六、0.11.0 移交(本次探讨已定方向)

  • 浏览态增值四候选:A 段落级主动回忆标记(已掌握/待复习/疑问 + 折叠)、B 回顾流基础版(延后 #16)、C 健康度基础版(#17)、D 勾选进度——核心判据:浏览态从"信息消费"升级为"学习加工"
  • 遗留决策:即改即存 vs 显式保存长期演进(0.10.1 维持现状);REQ-019/020/027 闪卡排期;图片随导出(#18 联动)