Initial commit: README with technical boundary and architecture
This commit is contained in:
commit
785715c13a
772
README.md
Normal file
772
README.md
Normal file
@ -0,0 +1,772 @@
|
|||||||
|
# zhixi-document-runtime
|
||||||
|
|
||||||
|
## 1. 仓库定位
|
||||||
|
|
||||||
|
`zhixi-document-runtime` 是知习的跨平台文档阅读与学习记录内核。
|
||||||
|
|
||||||
|
支撑平台:
|
||||||
|
|
||||||
|
```text
|
||||||
|
iOS
|
||||||
|
Android
|
||||||
|
鸿蒙
|
||||||
|
macOS
|
||||||
|
Windows
|
||||||
|
Web
|
||||||
|
```
|
||||||
|
|
||||||
|
统一处理资料阅读相关的底层能力。
|
||||||
|
|
||||||
|
它的目标不是做一个完整 App,也不是做 AI/RAG 解析,而是提供一个跨端复用的 Document Core。
|
||||||
|
|
||||||
|
本仓库服务于知习的资料阅读、阅读进度、笔记锚点、资料搜索和学习事件采集。知习主 App 继续负责账号、导航、知识库、AI 接口、上传、权限、UI 页面等业务能力。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 核心原则
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 原文件预览和 AI 解析彻底分离。
|
||||||
|
2. Rust Core 不负责网络请求。
|
||||||
|
3. Rust Core 不直接访问后端 API。
|
||||||
|
4. Rust Core 不保存用户 Token。
|
||||||
|
5. Rust Core 不负责完整 App UI。
|
||||||
|
6. Rust Core 输出统一文档模型、阅读事件、搜索结果和锚点。
|
||||||
|
7. 各端 App 负责下载文件、缓存文件、展示 UI、调用后端接口。
|
||||||
|
8. 不追求全格式完美预览。
|
||||||
|
9. Word / Excel 第一版走系统预览或外部应用兜底。
|
||||||
|
10. PPT、OCR、复杂富文本、PDF 标注暂不进入第一版。
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 技术路线
|
||||||
|
|
||||||
|
本仓库采用:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Rust Core
|
||||||
|
+ UniFFI 跨语言绑定
|
||||||
|
+ 各端原生 App 宿主
|
||||||
|
```
|
||||||
|
|
||||||
|
Rust 编译后会作为库打包进 App。iOS/macOS 可以打成静态库或 XCFramework;Android 可以打成 `.so`;Web 后续可以考虑编译成 WASM。Cargo 支持 `staticlib`、`cdylib` 等库产物类型,`cdylib` 用于生成可被其他语言加载的动态系统库。
|
||||||
|
|
||||||
|
跨语言绑定优先使用 **UniFFI**。UniFFI 可以为 Rust crate 生成 Swift、Kotlin 等语言绑定,适合把 Rust Core 暴露给 iOS 和 Android 使用。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Rust Core 负责什么
|
||||||
|
|
||||||
|
```text
|
||||||
|
负责:
|
||||||
|
1. 文件类型识别
|
||||||
|
2. Markdown / TXT 解析
|
||||||
|
3. EPUB 结构解析
|
||||||
|
4. PDF 阅读位置模型
|
||||||
|
5. PDF 渲染 POC
|
||||||
|
6. 图片 metadata
|
||||||
|
7. 阅读位置模型
|
||||||
|
8. 阅读时长事件
|
||||||
|
9. 搜索模型
|
||||||
|
10. 笔记锚点模型
|
||||||
|
11. App ↔ Rust 事件协议
|
||||||
|
12. Swift / Kotlin binding
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Rust Core 不负责什么
|
||||||
|
|
||||||
|
```text
|
||||||
|
不负责:
|
||||||
|
1. 网络请求
|
||||||
|
2. COS 下载
|
||||||
|
3. 用户登录
|
||||||
|
4. Token 管理
|
||||||
|
5. 后端 API 调用
|
||||||
|
6. App 页面导航
|
||||||
|
7. 系统分享
|
||||||
|
8. 文件选择器
|
||||||
|
9. AI / RAG 解析
|
||||||
|
10. 向量化
|
||||||
|
11. Office 高保真预览
|
||||||
|
12. 完整 PDF 标注
|
||||||
|
13. OCR
|
||||||
|
14. 富文本编辑器
|
||||||
|
15. Rust 全 UI 阅读器
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 支持格式分级
|
||||||
|
|
||||||
|
### 内置阅读 / 基础支持
|
||||||
|
|
||||||
|
| 格式 | 支持方式 | Rust 责任 | App 责任 |
|
||||||
|
| ------- | ------ | ----------------------- | ------------------------------------- |
|
||||||
|
| `.md` | 内置阅读 | Markdown 解析为 block tree | 原生渲染 block |
|
||||||
|
| `.txt` | 内置阅读 | 文本读取、搜索 | 原生文本渲染 |
|
||||||
|
| `.pdf` | 平台阅读优先 | 阅读位置模型,后续 PDF metadata | iOS 用 PDFKit / QuickLook,Android 后续适配 |
|
||||||
|
| 图片 | 内置查看 | metadata、阅读事件 | 原生图片查看 |
|
||||||
|
| `.epub` | 后续支持 | EPUB 结构解析 | WebView / 原生阅读器渲染章节 |
|
||||||
|
|
||||||
|
Markdown 解析建议使用 `comrak`,它是 CommonMark + GitHub Flavored Markdown 兼容的 Rust parser / renderer,支持表格、任务列表、删除线、自动链接等 GFM 扩展。
|
||||||
|
|
||||||
|
图片 metadata 可用 `image` crate。它提供 Rust 原生图像编码、解码和基础图像处理能力。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 系统预览 / 外部打开
|
||||||
|
|
||||||
|
| 格式 | 支持策略 |
|
||||||
|
| --------------- | -------------------------------------------- |
|
||||||
|
| `.docx` / Word | iOS/macOS 用 QuickLook;Android 用外部 App / 系统能力 |
|
||||||
|
| `.xlsx` / Excel | iOS/macOS 用 QuickLook;Android 用外部 App / 系统能力 |
|
||||||
|
| `.pptx` / PPT | 暂不承诺内置预览,可外部打开 |
|
||||||
|
|
||||||
|
这些格式不进入 Rust Core 第一版。原因是 Office 高保真排版复杂,第一版不应该消耗精力在 Word / Excel / PPT 自研预览上。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 后续增强
|
||||||
|
|
||||||
|
| 格式 / 能力 | 策略 |
|
||||||
|
| ----------- | -------------------- |
|
||||||
|
| PDF Rust 渲染 | 评估 PDFium / MuPDF |
|
||||||
|
| PDF 文本搜索 | 优先读取 PDF 文本层 |
|
||||||
|
| EPUB 阅读 | 解析结构 + 原生/Web 渲染 |
|
||||||
|
| Word 转 PDF | 后端或本地转换后复用 PDF 阅读 |
|
||||||
|
| Excel 表格预览 | 后端转 HTML / CSV / PDF |
|
||||||
|
| PPT | 后续再评估 |
|
||||||
|
| OCR | 暂不做 |
|
||||||
|
| PDF 标注 | 后移 |
|
||||||
|
| 富文本笔记 | 后移 |
|
||||||
|
|
||||||
|
PDF 后续可评估 `pdfium-render`。它是 Pdfium 的 Rust 高层接口,Pdfium 可渲染 PDF 页面为 bitmap,也能提取文本和图片。
|
||||||
|
|
||||||
|
EPUB 不是 Word 那类复杂办公格式,它本质上更接近打包的 Web 内容。移动端电子书可以参考 Readium,Readium Swift / Kotlin Toolkit 面向 iOS、iPadOS、Android、ChromeOS 等平台,支持 EPUB、PDF、有声书、漫画等出版物格式;但 Readium 也说明它提供的是底层工具,UI 和数据层仍需应用自己实现。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 推荐 Rust 依赖包
|
||||||
|
|
||||||
|
### 7.1 Core 基础依赖
|
||||||
|
|
||||||
|
```toml
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
thiserror = "2"
|
||||||
|
anyhow = "1"
|
||||||
|
tracing = "0.1"
|
||||||
|
uuid = { version = "1", features = ["v4", "serde"] }
|
||||||
|
time = { version = "0.3", features = ["serde"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
用途:
|
||||||
|
|
||||||
|
| 包 | 用途 |
|
||||||
|
| ------------ | --------------------- |
|
||||||
|
| `serde` | 数据结构序列化 / 反序列化 |
|
||||||
|
| `serde_json` | JSON 协议、调试输出、事件序列化 |
|
||||||
|
| `thiserror` | 定义稳定错误类型 |
|
||||||
|
| `anyhow` | CLI / demo / 内部错误快速处理 |
|
||||||
|
| `tracing` | 日志与诊断 |
|
||||||
|
| `uuid` | 事件 ID、session ID |
|
||||||
|
| `time` | 时间戳、阅读事件时间 |
|
||||||
|
|
||||||
|
Serde 是 Rust 生态常用的序列化 / 反序列化框架,适合把 Rust 数据结构转换成 JSON 传给 Swift/Kotlin。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.2 文件类型识别
|
||||||
|
|
||||||
|
```toml
|
||||||
|
infer = "0.16"
|
||||||
|
mime_guess = "2"
|
||||||
|
```
|
||||||
|
|
||||||
|
用途:
|
||||||
|
|
||||||
|
```text
|
||||||
|
infer:根据文件头判断类型
|
||||||
|
mime_guess:根据扩展名推测 MIME
|
||||||
|
```
|
||||||
|
|
||||||
|
策略:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 优先读取 magic bytes
|
||||||
|
2. 其次使用 MIME
|
||||||
|
3. 最后使用扩展名
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.3 Markdown
|
||||||
|
|
||||||
|
```toml
|
||||||
|
comrak = "latest-compatible"
|
||||||
|
```
|
||||||
|
|
||||||
|
用途:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 解析 Markdown
|
||||||
|
2. 支持 GFM 表格、任务列表、删除线
|
||||||
|
3. 输出 block tree
|
||||||
|
4. 可选输出 HTML,调试用
|
||||||
|
```
|
||||||
|
|
||||||
|
不推荐只输出 HTML。更推荐输出知习自己的 block model:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub enum DocumentBlock {
|
||||||
|
Heading { id: String, level: u8, text: String },
|
||||||
|
Paragraph { id: String, text: String },
|
||||||
|
List { id: String, ordered: bool, items: Vec<String> },
|
||||||
|
CodeBlock { id: String, language: Option<String>, code: String },
|
||||||
|
Quote { id: String, text: String },
|
||||||
|
Table { id: String, rows: Vec<Vec<String>> },
|
||||||
|
Image { id: String, src: String, alt: Option<String> },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.4 图片
|
||||||
|
|
||||||
|
```toml
|
||||||
|
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "webp", "gif"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
用途:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 读取图片尺寸
|
||||||
|
2. 判断图片格式
|
||||||
|
3. 后续生成缩略图
|
||||||
|
```
|
||||||
|
|
||||||
|
不做 OCR,不承诺选择图片文字。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.5 EPUB
|
||||||
|
|
||||||
|
```toml
|
||||||
|
zip = "latest-compatible"
|
||||||
|
roxmltree = "latest-compatible"
|
||||||
|
quick-xml = "latest-compatible"
|
||||||
|
```
|
||||||
|
|
||||||
|
用途:
|
||||||
|
|
||||||
|
| 包 | 用途 |
|
||||||
|
| ----------- | ------------------------------ |
|
||||||
|
| `zip` | EPUB 本质是 zip 容器,用于读取 EPUB 内部文件 |
|
||||||
|
| `roxmltree` | 解析 OPF / nav XML 为只读树 |
|
||||||
|
| `quick-xml` | 后续处理大型 XML 或流式解析 |
|
||||||
|
|
||||||
|
EPUB 目标不是完整渲染,而是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 识别 EPUB
|
||||||
|
2. 读取 metadata
|
||||||
|
3. 解析 spine
|
||||||
|
4. 解析目录
|
||||||
|
5. 输出章节列表
|
||||||
|
6. 建立章节级阅读位置
|
||||||
|
```
|
||||||
|
|
||||||
|
章节 HTML 的最终渲染可以交给宿主 App 的 WebView / 原生 HTML 渲染能力。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.6 PDF
|
||||||
|
|
||||||
|
第一版不强制引入 PDF 渲染库。
|
||||||
|
后续可选:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
pdfium-render = { version = "latest-compatible", optional = true }
|
||||||
|
```
|
||||||
|
|
||||||
|
用途:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. PDF metadata
|
||||||
|
2. PDF 页数
|
||||||
|
3. PDF 文本提取
|
||||||
|
4. PDF 页面 bitmap 渲染 POC
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:PDF 在 iOS 可以先用 PDFKit / QuickLook。Rust Core 只统一 PDF 阅读位置模型:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct PdfReadingPosition {
|
||||||
|
pub page_number: u32,
|
||||||
|
pub page_progress: f32,
|
||||||
|
pub overall_progress: f32,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.7 搜索
|
||||||
|
|
||||||
|
先自己实现轻量搜索:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Markdown / TXT:
|
||||||
|
- lowercase
|
||||||
|
- simple contains
|
||||||
|
- 返回 blockId + snippet
|
||||||
|
|
||||||
|
PDF:
|
||||||
|
- 先交给平台 PDFKit
|
||||||
|
```
|
||||||
|
|
||||||
|
后续如果需要本地全文索引,可以评估:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
tantivy = { version = "latest-compatible", optional = true }
|
||||||
|
```
|
||||||
|
|
||||||
|
Tantivy 是 Rust 的全文搜索引擎库,类似 Lucene。
|
||||||
|
|
||||||
|
但第一版不建议直接上 Tantivy,避免移动端包体、索引存储和复杂度过早增加。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.8 UniFFI
|
||||||
|
|
||||||
|
```toml
|
||||||
|
uniffi = "latest-compatible"
|
||||||
|
```
|
||||||
|
|
||||||
|
用于生成 Swift / Kotlin bindings。UniFFI 支持为 Rust crate 生成外部语言绑定,适合本仓库作为跨端内核。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Cargo workspace 建议
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = [
|
||||||
|
"crates/zx_document_core",
|
||||||
|
"crates/zx_document_ffi",
|
||||||
|
"crates/xtask"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### `crates/zx_document_core`
|
||||||
|
|
||||||
|
核心 Rust 逻辑。
|
||||||
|
|
||||||
|
```text
|
||||||
|
负责:
|
||||||
|
- 文件类型识别
|
||||||
|
- Markdown / TXT 解析
|
||||||
|
- 图片 metadata
|
||||||
|
- EPUB 结构解析
|
||||||
|
- 阅读位置
|
||||||
|
- 阅读事件
|
||||||
|
- 搜索
|
||||||
|
- 锚点
|
||||||
|
```
|
||||||
|
|
||||||
|
### `crates/zx_document_ffi`
|
||||||
|
|
||||||
|
FFI 绑定层。
|
||||||
|
|
||||||
|
```text
|
||||||
|
负责:
|
||||||
|
- UniFFI 暴露 API
|
||||||
|
- Swift binding
|
||||||
|
- Kotlin binding
|
||||||
|
- 类型转换
|
||||||
|
```
|
||||||
|
|
||||||
|
### `crates/xtask`
|
||||||
|
|
||||||
|
开发辅助工具。
|
||||||
|
|
||||||
|
```text
|
||||||
|
负责:
|
||||||
|
- 构建 iOS XCFramework
|
||||||
|
- 生成 bindings
|
||||||
|
- 跑 fixtures 测试
|
||||||
|
- 打包 release artifact
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 推荐目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
zhixi-document-runtime/
|
||||||
|
├── README.md
|
||||||
|
├── Cargo.toml
|
||||||
|
├── crates/
|
||||||
|
│ ├── zx_document_core/
|
||||||
|
│ │ ├── Cargo.toml
|
||||||
|
│ │ └── src/
|
||||||
|
│ │ ├── lib.rs
|
||||||
|
│ │ ├── error.rs
|
||||||
|
│ │ ├── material_type.rs
|
||||||
|
│ │ ├── document.rs
|
||||||
|
│ │ ├── blocks.rs
|
||||||
|
│ │ ├── markdown.rs
|
||||||
|
│ │ ├── text.rs
|
||||||
|
│ │ ├── image_meta.rs
|
||||||
|
│ │ ├── epub.rs
|
||||||
|
│ │ ├── pdf.rs
|
||||||
|
│ │ ├── search.rs
|
||||||
|
│ │ ├── progress.rs
|
||||||
|
│ │ ├── events.rs
|
||||||
|
│ │ └── anchors.rs
|
||||||
|
│ │
|
||||||
|
│ ├── zx_document_ffi/
|
||||||
|
│ │ ├── Cargo.toml
|
||||||
|
│ │ ├── build.rs
|
||||||
|
│ │ ├── src/
|
||||||
|
│ │ │ └── lib.rs
|
||||||
|
│ │ └── zx_document.udl
|
||||||
|
│ │
|
||||||
|
│ └── xtask/
|
||||||
|
│ ├── Cargo.toml
|
||||||
|
│ └── src/
|
||||||
|
│ └── main.rs
|
||||||
|
│
|
||||||
|
├── bindings/
|
||||||
|
│ ├── ios/
|
||||||
|
│ ├── android/
|
||||||
|
│ └── generated/
|
||||||
|
│
|
||||||
|
├── fixtures/
|
||||||
|
│ ├── markdown/
|
||||||
|
│ ├── text/
|
||||||
|
│ ├── pdf/
|
||||||
|
│ ├── images/
|
||||||
|
│ └── epub/
|
||||||
|
│
|
||||||
|
├── docs/
|
||||||
|
│ ├── architecture.md
|
||||||
|
│ ├── supported-formats.md
|
||||||
|
│ ├── event-protocol.md
|
||||||
|
│ ├── reading-position-model.md
|
||||||
|
│ ├── note-anchor-model.md
|
||||||
|
│ ├── ios-integration.md
|
||||||
|
│ ├── android-integration.md
|
||||||
|
│ └── roadmap.md
|
||||||
|
│
|
||||||
|
└── scripts/
|
||||||
|
├── build-ios.sh
|
||||||
|
├── build-android.sh
|
||||||
|
└── generate-bindings.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 核心数据模型
|
||||||
|
|
||||||
|
### 10.1 MaterialType
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub enum MaterialType {
|
||||||
|
Markdown,
|
||||||
|
Text,
|
||||||
|
Pdf,
|
||||||
|
Image,
|
||||||
|
Epub,
|
||||||
|
Word,
|
||||||
|
Excel,
|
||||||
|
PowerPoint,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 PreviewMode
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub enum PreviewMode {
|
||||||
|
NativeReader,
|
||||||
|
PlatformPreview,
|
||||||
|
ExternalOpen,
|
||||||
|
Unsupported,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
含义:
|
||||||
|
|
||||||
|
```text
|
||||||
|
NativeReader:
|
||||||
|
由知习内置阅读器展示,例如 MD / TXT / 图片 / 后续 EPUB。
|
||||||
|
|
||||||
|
PlatformPreview:
|
||||||
|
由平台能力展示,例如 iOS QuickLook。
|
||||||
|
|
||||||
|
ExternalOpen:
|
||||||
|
交给外部 App 打开。
|
||||||
|
|
||||||
|
Unsupported:
|
||||||
|
暂不支持。
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10.3 DocumentInfo
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct DocumentInfo {
|
||||||
|
pub material_id: String,
|
||||||
|
pub title: String,
|
||||||
|
pub material_type: MaterialType,
|
||||||
|
pub preview_mode: PreviewMode,
|
||||||
|
pub file_size: u64,
|
||||||
|
pub page_count: Option<u32>,
|
||||||
|
pub word_count: Option<u32>,
|
||||||
|
pub created_at: Option<String>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10.4 ReadingPosition
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub enum ReadingPosition {
|
||||||
|
Markdown {
|
||||||
|
block_id: String,
|
||||||
|
scroll_progress: f32,
|
||||||
|
},
|
||||||
|
Text {
|
||||||
|
line_number: u32,
|
||||||
|
scroll_progress: f32,
|
||||||
|
},
|
||||||
|
Pdf {
|
||||||
|
page_number: u32,
|
||||||
|
page_progress: f32,
|
||||||
|
overall_progress: f32,
|
||||||
|
},
|
||||||
|
Image {
|
||||||
|
zoom_scale: f32,
|
||||||
|
offset_x: f32,
|
||||||
|
offset_y: f32,
|
||||||
|
},
|
||||||
|
Epub {
|
||||||
|
chapter_id: String,
|
||||||
|
chapter_progress: f32,
|
||||||
|
overall_progress: f32,
|
||||||
|
},
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10.5 ReadingEvent
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub enum ReadingEvent {
|
||||||
|
MaterialOpened {
|
||||||
|
material_id: String,
|
||||||
|
timestamp_ms: i64,
|
||||||
|
},
|
||||||
|
MaterialClosed {
|
||||||
|
material_id: String,
|
||||||
|
timestamp_ms: i64,
|
||||||
|
active_seconds: u32,
|
||||||
|
},
|
||||||
|
PositionChanged {
|
||||||
|
material_id: String,
|
||||||
|
position: ReadingPosition,
|
||||||
|
timestamp_ms: i64,
|
||||||
|
},
|
||||||
|
Heartbeat {
|
||||||
|
material_id: String,
|
||||||
|
active_seconds: u32,
|
||||||
|
position: Option<ReadingPosition>,
|
||||||
|
timestamp_ms: i64,
|
||||||
|
},
|
||||||
|
MarkedAsRead {
|
||||||
|
material_id: String,
|
||||||
|
timestamp_ms: i64,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10.6 NoteAnchor
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub enum NoteAnchor {
|
||||||
|
Material {
|
||||||
|
material_id: String,
|
||||||
|
},
|
||||||
|
MarkdownBlock {
|
||||||
|
material_id: String,
|
||||||
|
block_id: String,
|
||||||
|
},
|
||||||
|
PdfPage {
|
||||||
|
material_id: String,
|
||||||
|
page_number: u32,
|
||||||
|
},
|
||||||
|
EpubChapter {
|
||||||
|
material_id: String,
|
||||||
|
chapter_id: String,
|
||||||
|
},
|
||||||
|
KnowledgeItem {
|
||||||
|
knowledge_item_id: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. App ↔ Rust 调用边界
|
||||||
|
|
||||||
|
### App 调用 Rust
|
||||||
|
|
||||||
|
```text
|
||||||
|
detect_material_type(file_path)
|
||||||
|
open_document(file_path, material_id)
|
||||||
|
get_document_info(document_handle)
|
||||||
|
get_markdown_blocks(document_handle)
|
||||||
|
search_document(document_handle, query)
|
||||||
|
update_position(material_id, position)
|
||||||
|
export_pending_events()
|
||||||
|
create_note_anchor(material_id, position)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rust 返回 App
|
||||||
|
|
||||||
|
```text
|
||||||
|
DocumentInfo
|
||||||
|
DocumentBlock[]
|
||||||
|
SearchResult[]
|
||||||
|
ReadingEvent[]
|
||||||
|
NoteAnchor
|
||||||
|
DocumentError
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rust 不直接做
|
||||||
|
|
||||||
|
```text
|
||||||
|
download_file()
|
||||||
|
upload_reading_events()
|
||||||
|
call_ai_chat()
|
||||||
|
save_note_to_backend()
|
||||||
|
share_file()
|
||||||
|
delete_material()
|
||||||
|
```
|
||||||
|
|
||||||
|
这些由宿主 App 调接口完成。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. iOS 接入方式
|
||||||
|
|
||||||
|
iOS 侧目标:
|
||||||
|
|
||||||
|
```text
|
||||||
|
SwiftUI 页面
|
||||||
|
→ 调用 UniFFI Swift binding
|
||||||
|
→ Rust Core 返回 DocumentInfo / Blocks / Events
|
||||||
|
→ SwiftUI 渲染
|
||||||
|
→ App 上传阅读事件
|
||||||
|
```
|
||||||
|
|
||||||
|
支持:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. Markdown block 渲染
|
||||||
|
2. TXT 渲染
|
||||||
|
3. 图片预览
|
||||||
|
4. PDF 先走 PDFKit / QuickLook
|
||||||
|
5. Word / Excel 先走 QuickLook
|
||||||
|
6. 阅读位置上报
|
||||||
|
7. 标记已读
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Android / 鸿蒙接入方式
|
||||||
|
|
||||||
|
Android 以后通过 Kotlin binding 接入:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Kotlin / Compose
|
||||||
|
→ UniFFI Kotlin binding
|
||||||
|
→ Rust Core
|
||||||
|
```
|
||||||
|
|
||||||
|
鸿蒙如果 UniFFI 没有直接支持,需要再评估:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. C ABI
|
||||||
|
2. Rust 编译动态库
|
||||||
|
3. 鸿蒙侧通过 FFI / NAPI / C bridge 调用
|
||||||
|
```
|
||||||
|
|
||||||
|
这部分不进入第一版。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. 第一版不允许做的事
|
||||||
|
|
||||||
|
为了防止 Agent 发散,明确禁止:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 不做 Rust UI 阅读器。
|
||||||
|
2. 不做 PDFium 集成。
|
||||||
|
3. 不做 Office 解析。
|
||||||
|
4. 不做 PPT。
|
||||||
|
5. 不做 OCR。
|
||||||
|
6. 不做 AI/RAG。
|
||||||
|
7. 不做富文本编辑器。
|
||||||
|
8. 不做后端 API 请求。
|
||||||
|
9. 不做文件上传下载。
|
||||||
|
10. 不做知识库业务逻辑。
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. 最小验收标准
|
||||||
|
|
||||||
|
第一版完成时,必须能做到:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. Rust 能识别 md/txt/pdf/image/epub/docx/xlsx/pptx 类型。
|
||||||
|
2. Rust 能把 Markdown 解析成 DocumentBlock。
|
||||||
|
3. Rust 能读取 TXT 内容。
|
||||||
|
4. Rust 能读取图片尺寸。
|
||||||
|
5. Rust 能生成 ReadingPosition。
|
||||||
|
6. Rust 能生成 ReadingEvent。
|
||||||
|
7. Swift 能通过 UniFFI 调用 Rust。
|
||||||
|
8. iOS demo 能展示 Markdown blocks。
|
||||||
|
9. iOS demo 能收到阅读位置事件。
|
||||||
|
10. 所有核心模型都有单元测试。
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. 最终技术决策
|
||||||
|
|
||||||
|
```text
|
||||||
|
第一版不做万能阅读器。
|
||||||
|
第一版只做跨平台 Document Core。
|
||||||
|
|
||||||
|
Markdown / TXT / 图片 metadata / 阅读事件是第一目标。
|
||||||
|
PDF 先由平台阅读能力承接。
|
||||||
|
Word / Excel 先由系统预览或外部应用承接。
|
||||||
|
EPUB 放到后续版本。
|
||||||
|
Office 高保真、PDF 标注、OCR、富文本编辑器全部后移。
|
||||||
|
```
|
||||||
|
|
||||||
|
一句话:
|
||||||
|
|
||||||
|
> `zhixi-document-runtime` 的第一版目标不是"支持所有文件预览",而是先建立跨平台文档内核、阅读位置模型、学习事件协议和 iOS 接入链路;只有这个底座稳定,后面 Android、鸿蒙、Mac、Windows、Web 才不会重复造轮子。
|
||||||
Loading…
x
Reference in New Issue
Block a user