From b22df858913a857a95856e053499f47a1d15cb16 Mon Sep 17 00:00:00 2001 From: wangdl Date: Sun, 7 Jun 2026 20:26:05 +0800 Subject: [PATCH] feat: DOC-FULL Batch 1 FFI + Compat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #56 FFI DTO V2 exports (done in A1) #83 V1 deprecated annotations #84 V2→API protocol mapping doc Co-Authored-By: Claude Opus 4.7 --- crates/zx_document_core/src/events.rs | 2 ++ docs/reading-event-v2-api-mapping.md | 50 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 docs/reading-event-v2-api-mapping.md diff --git a/crates/zx_document_core/src/events.rs b/crates/zx_document_core/src/events.rs index 702203d..640cbd3 100644 --- a/crates/zx_document_core/src/events.rs +++ b/crates/zx_document_core/src/events.rs @@ -12,6 +12,7 @@ static EVENT_BUFFER: Mutex> = Mutex::new(Vec::new()); /// Push a reading event into the global buffer. /// If the buffer exceeds MAX_BUFFER_SIZE, the oldest event is dropped. +#[deprecated(since = "0.2.0", note = "Use events_v2::push_heartbeat_v2 etc. instead")] pub fn push_reading_event(event: ReadingEvent) { match EVENT_BUFFER.lock() { Ok(mut buf) => { @@ -24,6 +25,7 @@ pub fn push_reading_event(event: ReadingEvent) { } } +#[deprecated(since = "0.2.0", note = "Use events_v2::push_position_changed_v2 instead")] /// Record a position change as a PositionChanged event. pub fn update_reading_position(material_id: &str, position: ReadingPosition) { let event = ReadingEvent::PositionChanged { diff --git a/docs/reading-event-v2-api-mapping.md b/docs/reading-event-v2-api-mapping.md new file mode 100644 index 0000000..8176ee2 --- /dev/null +++ b/docs/reading-event-v2-api-mapping.md @@ -0,0 +1,50 @@ +# ReadingEvent V2 → API 上传协议映射 + +## 字段映射 + +| Rust ReadingEventV2 | API ReadingEventUploadItem | 来源 | +|---------------------|---------------------------|------| +| event_id | eventId | Rust 生成 UUID | +| client_session_id | clientSessionId | Rust 生成 UUID(start_reading_session_v2) | +| material_id | materialId | Rust 保存,iOS 传入 | +| event_type | eventType | Rust→iOS 转 snake_case | +| position | position | Rust(camelCase JSON,clamped) | +| active_seconds_delta | activeSecondsDelta | Rust ActiveTimeTracker 计算 | +| timestamp_ms | clientTimestampMs | Rust | +| sequence | sequence | Rust(session 内递增) | +| — | readingTargetType | **iOS 补充** | +| — | platform | **iOS 补充**(= "ios") | +| — | appVersion | **iOS 补充** | +| — | clientTimezoneOffsetMinutes | **iOS 补充** | + +## iOS 上传适配流程 + +``` +1. Rust export_pending_events_v2(limit, ts) +2. iOS 获得 Vec +3. iOS 遍历每个 event,补充 readingTargetType/platform/appVersion/timezone +4. iOS 写入本地上传队列 +5. 成功后调用 Rust ack_events_v2(eventIds) +6. 失败后调用 Rust mark_events_failed_v2(eventIds) +7. App 启动时调用 reload_stale_events_v2() 恢复未 ack 的事件 +``` + +## eventType 映射 + +| Rust | API | +|------|-----| +| MaterialOpened | material_opened | +| MaterialClosed | material_closed | +| PositionChanged | position_changed | +| Heartbeat | heartbeat | +| MarkedAsRead | marked_as_read | + +## delta 规则 + +| 事件 | delta | +|------|-------| +| MaterialOpened | 0 | +| PositionChanged | 0 | +| MarkedAsRead | 0 | +| Heartbeat | tracker.tick() 返回值 | +| MaterialClosed | tracker.close() 返回值 |