DOC-FULL-020 P0 | position → NoteAnchor 转换 【status:partial】 #69

Closed
opened 2026-06-07 11:33:16 +08:00 by wangdl · 2 comments
Owner

6种 position 到 anchor 的映射,Unknown 兜底为 Material anchor,FFI 可调用

M-DOC-FULL 里程碑 issue。详见设计文档。

## 6种 position 到 anchor 的映射,Unknown 兜底为 Material anchor,FFI 可调用 M-DOC-FULL 里程碑 issue。详见设计文档。
wangdl added this to the M-DOC-FULL:Document Runtime 完整阅读内核与学习事件协议 milestone 2026-06-07 11:33:16 +08:00
wangdl changed title from DOC-FULL-020 P0 | position → NoteAnchor 转换 to DOC-FULL-020 P0 | position → NoteAnchor 转换 【status:partial】 2026-06-07 19:15:04 +08:00
Author
Owner

审查结论:document runtime 当前有文件类型识别/MaterialType/PreviewMode/DocumentInfo(基本)/Markdown解析/Text解析/ImageMeta/Search(V1 Markdown+Text)/NoteAnchor(V1)/ReadingEvent(V1)/ReadingPosition(V1)/EventBuffer(V1基础)/iOS构建/UniFFI绑定/docs。但 V2 核心模型(ReadingSession/EventV2/ActiveTimeTracker)不存在,EventBuffer 缺 ack/failed,Position 缺 camelCase+clamp,PDF/EPUB/Office 为 stub,测试覆盖不足 V2。

本 Issue: from_position() 已实现 6 种映射。缺: 测试、Unknown 兜底验证。

状态: status:partial
工作类型: work:extend-existing

## 审查结论:document runtime 当前有文件类型识别/MaterialType/PreviewMode/DocumentInfo(基本)/Markdown解析/Text解析/ImageMeta/Search(V1 Markdown+Text)/NoteAnchor(V1)/ReadingEvent(V1)/ReadingPosition(V1)/EventBuffer(V1基础)/iOS构建/UniFFI绑定/docs。但 V2 核心模型(ReadingSession/EventV2/ActiveTimeTracker)不存在,EventBuffer 缺 ack/failed,Position 缺 camelCase+clamp,PDF/EPUB/Office 为 stub,测试覆盖不足 V2。 **本 Issue**: from_position() 已实现 6 种映射。缺: 测试、Unknown 兜底验证。 **状态**: status:partial **工作类型**: work:extend-existing
Author
Owner

完成报告

改动文件

  • crates/zx_document_core/src/anchors.rs — 新增 NoteAnchor::to_position() 反向转换方法,from_position() 现在设置 position_snapshot: Some(pos.clone())
  • crates/zx_document_ffi/src/lib.rs — 新增 restore_position_from_anchor uniffi 导出
  • crates/zx_document_ffi/src/zx_document.udl — 新增 restore_position_from_anchor(NoteAnchor) -> ReadingPosition?

转换矩阵

NoteAnchor 变体 to_position() 行为
MarkdownBlock position_snapshot 或构造 Markdown{block_id}
TextLine position_snapshot 或构造 Text{line_number}
PdfPage position_snapshot 或构造 Pdf{page_number}
Image position_snapshot 或 None
EpubChapter position_snapshot 或构造 Epub{chapter_id}
Material position_snapshot 或 None
SearchResultAnchor 智能分发:page_number→Pdf, chapter_id→Epub, line_number→Text, block_id→Markdown
KnowledgeItem None(无位置信息)

测试覆盖(7 个新增)

  • test_to_position_with_snapshot / test_to_position_without_snapshot_uses_minimal
  • test_to_position_from_search_result_pdf / test_to_position_from_search_result_markdown
  • test_to_position_knowledge_item_returns_none / test_to_position_material_without_snapshot_returns_none
  • test_roundtrip_position_anchor_position(from_position → to_position 无损)

代码证据

pub fn to_position(&self) -> Option<ReadingPosition> {
    match self {
        NoteAnchor::MarkdownBlock { block_id, position_snapshot, .. } => {
            position_snapshot.clone().or_else(|| {
                Some(ReadingPosition::Markdown { block_id: block_id.clone(), scroll_progress: 0.0 })
            })
        }
        // ... 所有 7 种 + SearchResultAnchor 智能分发
    }
}

验证

cargo test anchors — 18 passed, 0 failed
cargo test — 139 passed, 0 failed
## 完成报告 ### 改动文件 - `crates/zx_document_core/src/anchors.rs` — 新增 `NoteAnchor::to_position()` 反向转换方法,`from_position()` 现在设置 `position_snapshot: Some(pos.clone())` - `crates/zx_document_ffi/src/lib.rs` — 新增 `restore_position_from_anchor` uniffi 导出 - `crates/zx_document_ffi/src/zx_document.udl` — 新增 `restore_position_from_anchor(NoteAnchor) -> ReadingPosition?` ### 转换矩阵 | NoteAnchor 变体 | to_position() 行为 | |---|---| | MarkdownBlock | position_snapshot 或构造 Markdown{block_id} | | TextLine | position_snapshot 或构造 Text{line_number} | | PdfPage | position_snapshot 或构造 Pdf{page_number} | | Image | position_snapshot 或 None | | EpubChapter | position_snapshot 或构造 Epub{chapter_id} | | Material | position_snapshot 或 None | | SearchResultAnchor | 智能分发:page_number→Pdf, chapter_id→Epub, line_number→Text, block_id→Markdown | | KnowledgeItem | None(无位置信息)| ### 测试覆盖(7 个新增) - `test_to_position_with_snapshot` / `test_to_position_without_snapshot_uses_minimal` - `test_to_position_from_search_result_pdf` / `test_to_position_from_search_result_markdown` - `test_to_position_knowledge_item_returns_none` / `test_to_position_material_without_snapshot_returns_none` - `test_roundtrip_position_anchor_position`(from_position → to_position 无损) ### 代码证据 ```rust pub fn to_position(&self) -> Option<ReadingPosition> { match self { NoteAnchor::MarkdownBlock { block_id, position_snapshot, .. } => { position_snapshot.clone().or_else(|| { Some(ReadingPosition::Markdown { block_id: block_id.clone(), scroll_progress: 0.0 }) }) } // ... 所有 7 种 + SearchResultAnchor 智能分发 } } ``` ### 验证 ``` cargo test anchors — 18 passed, 0 failed cargo test — 139 passed, 0 failed ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/zhixi-document-runtime#69
No description provided.