Files
mnote/bugs/05-editor-mainline/done/5-24-page-body-save-preserves-uploaded-image-and-attachment-v1.md
T
lix-2026 cdff672aa5 feat: align local-first workspace direction
Document the VSCode-like local-first product shape, demote Convex to a control-plane role, and retire stale architecture drafts.

Add local workspace migration/export references plus smoke coverage for no-Convex managed workspace startup, local markdown title/body/options persistence, asset upload behavior, and Convex fixture export.

Verification: git diff --cached --check; node scripts/check-local-first-convex-guard.js --staged; node scripts/task444-convex-workspace-export-local-fixture-smoke.js; node scripts/task166-local-first-managed-workspace-no-convex-smoke.js; node scripts/task167-local-markdown-title-body-options-no-convex-smoke.js
2026-05-19 08:11:58 +08:00

3.0 KiB
Raw Blame History

5-24 [done][bug] page.body.save 上传图片与附件持久化字段丢失 v1

发现时间:2026-05-18

状态:[done]

关联主线:05-editor-mainline

1. 问题定义

主编辑区文本保存修复后,继续验证上传图片与附件发现两个持久化缺陷:

  • 附件能插入到编辑器,并且 /api/documents/save 返回 200,但 /api/documents/content 回读时链接 mark 被降级成纯文本。
  • 图片能上传并触发保存,但 /api/documents/content 回读时图片块只剩 type: "image"props.src / alt / title / tiptapImage 为空。

这会导致刷新或跨浏览器打开后,附件不能作为 OnlyOffice 附件链接恢复,图片也缺少可渲染的资源地址。

2. 根因

保存链优先使用 editorDocument 生成 canonical legacy content 后再写入当前 Convex legacy substrate。

两个字段在这一步丢失:

  • legacy_content_from_editor_document 只用 legacy_text_from_editor_block() 生成纯文本,未保留 ContentNode.attrs.styles.link
  • EditorBlockDocument 反序列化时 BlockProps.extra 不是 flatten 字段,前端传来的 image props.src / alt / title / tiptapImage 会被 serde 忽略;hydrate_editor_document_props_from_raw 旧实现只回填 mindmap props,没有回填 image props。

3. 修复

  • legacy_content_from_editor_document 对带结构化样式的 inline 节点输出 legacy inline content 数组,保留 styles.link 等样式;普通纯文本段落仍保持旧的字符串 content。
  • hydrate_editor_document_props_from_raw 增加 image 分支,从原始 editorDocument.blocks[].props 回填 src / alt / title / tiptapImage
  • legacy_props_from_editor_block 对 image 块输出回填后的直接 props 与 tiptapImage

4. 验证

单测:

cargo fmt --manifest-path rust/Cargo.toml --all --check
cargo test --manifest-path rust/Cargo.toml -p bridge-runtime legacy_content_from_editor_document_preserves_inline_link_styles -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p bridge-runtime documents_save_hydrates_image_props_from_raw_editor_document -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p bridge-runtime documents_save_command_plan_prefers_valid_editor_document_over_other_sources -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web documents_save_route_executes_page_body_save_command -- --nocapture

浏览器验证:

  • 以测试账号登录 http://127.0.0.1:13000
  • 新建临时页面。
  • 通过 slash 上传 .docx 附件和 .png 图片。
  • 断言两次 /api/documents/save 均返回 200。
  • 断言 /api/documents/content 回读包含:
    • image props.src
    • 附件 inline styles.link
  • 刷新页面后,编辑器 DOM 中仍能找到附件链接与图片节点。

结果:通过;临时测试页面已 purge。

5. 剩余边界

当前仍是 legacy content substrate 下的过渡修复。完整 EditorBlockDocument 原生落库完成后,图片/附件 props 应由原生 schema 和迁移校验继续收紧。