zhixi-document-runtime/docs/architecture.md
wangdl dd360c88e2 fix: RagChatModule 导入 AiModule,修复 AiGatewayService 未注入
AiGatewayService 使用了 @Optional() 导致不报错但始终为 null,
sendMessage 永远走 fallbackReply。现在导入 AiModule 正确注入。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 13:38:57 +08:00

85 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Architecture
## 分层架构
```text
┌──────────────────────────────────────────────┐
│ iOS / Android / 鸿蒙 / macOS / Windows / Web │ ← 宿主 App
├──────────────────────────────────────────────┤
│ UniFFI proc-macro C-ABI bridge │ ← zx_document_ffi
├──────────────────────────────────────────────┤
│ zx_document_core (Rust) │ ← 核心逻辑
│ ├─ file_type 文件类型识别 │
│ ├─ markdown MD 解析为 DocumentBlock │
│ ├─ text TXT 读取 │
│ ├─ image_meta 图片 metadata │
│ ├─ epub EPUB 结构解析 │
│ ├─ pdf PDF 位置模型 │
│ ├─ progress ReadingPosition │
│ ├─ events ReadingEvent │
│ ├─ search 基础搜索 │
│ └─ anchors NoteAnchor │
└──────────────────────────────────────────────┘
```
## 职责边界
### Rust Core 负责
| 模块 | 职责 |
|------|------|
| 文件类型识别 | 根据 magic bytes → MIME → 扩展名判断 MaterialType |
| Markdown 解析 | 读取 .md 文件,输出 DocumentBlock 列表 |
| TXT 读取 | 读取 .txt 文件,输出段落/行 block |
| 图片 metadata | 读取宽高、格式、文件大小 |
| 阅读位置 | 提供统一的 ReadingPosition跨格式 |
| 阅读事件 | 生成 MaterialOpened/Closed/PositionChanged/Heartbeat 事件 |
| 搜索 | 大小写不敏感,返回 block/snippet |
| 笔记锚点 | 从 ReadingPosition 生成 NoteAnchor |
| FFI 绑定 | 通过 proc-macro (#[uniffi::export]) + UDL bindgen 暴露 API 给 Swift/Kotlin |
### 宿主 App 负责
| 模块 | 职责 |
|------|------|
| 网络请求 | COS 下载、API 调用、事件上报 |
| Token 管理 | 用户登录、JWT 存储 |
| UI 渲染 | SwiftUI/Compose 渲染 DocumentBlock |
| 系统预览 | PDF/Office 通过 PDFKit/QuickLook 预览 |
| 文件选择 | 系统文件选择器 |
| 分享/删除 | 系统分享面板、文件管理 |
### Rust Core 明确不负责
- 不做网络请求
- 不保存 Token
- 不直接访问后端 API
- 不做 AI / RAG 解析
- 不做向量化
- 不做 Office 高保真预览
- 不做 OCR
- 不做 PDF 标注
- 不做富文本编辑器
- 不做完整 UI
## 数据流
```text
1. App 下载文件到本地COS → 沙盒)
2. App 调用 detect_material_type(file_path)
3. 根据 MaterialType 决定预览方式:
- NativeReader → 调用 open_document → get_xxx_blocks → 原生渲染
- PlatformPreview → iOS QuickLook / Android 系统预览
- ExternalOpen → 打开外部 App
4. 阅读过程中 App 调用 update_reading_position / heartbeat
5. App 定期调用 export_pending_events → 上传到后端
```
## Crate 拆分
| Crate | 类型 | 用途 |
|-------|------|------|
| zx_document_core | library | 核心 Rust 逻辑,纯计算 |
| zx_document_ffi | library | UniFFI proc-macro 绑定(#[uniffi::export] + UDL bindgen |
| xtask | binary | 构建脚本,生成 binding打包 artifact |