12 KiB
01. Domain Model v0
更新时间:2026-04-11
适用范围:/mnt/Data1T/mnote-rust
1. 目标
本文件定义 mnote-rust 的核心领域模型。
它要解决的问题不是“前端怎么渲染”,而是:
- 系统里到底有哪些一等对象
- 哪些对象是事实层真相,哪些只是派生视图
- AI / CLI / Web / Desktop 应该围绕什么稳定对象工作
- OnlyOffice、Mindmap、OCR、RAG 这类能力应挂在哪一层
本文件优先保证:
- 长期稳定
- 脱离 UI 依赖
- 适合 Rust 内核实现
- 适合 AI 通过结构化协议读写
2. 建模原则
2.1 事实与视图分离
以下对象属于事实层:
- Workspace
- Page
- Block
- Asset
- Reference
- Task
- CommandLog
- Event
- AgentSession
以下对象默认属于派生层 / 视图层:
- 目录(TOC)
- 反链聚合
- 搜索结果列表
- Mindmap 视图树
- OnlyOffice 当前光标/当前页/当前选区
- AI 面板当前消息列表 UI 状态
原则:
派生层可以重建;事实层必须稳定、可审计、可迁移。
2.2 人与 AI 共用同一套领域对象
不能做人类一套模型、AI 一套模型。
要求:
- 人类编辑页面,本质是修改
Page / Block / Asset / Reference - AI 编辑页面,本质也是修改同样的对象
- CLI 批处理、同步任务、导入器也修改同样的对象
2.3 第三方编辑器不是事实源
Block editor、OnlyOffice、mindmap editor 都不是系统真相。
它们只能是:
- 某类对象的视图/交互适配器
- 输入输出变换器
- 外部文档能力宿主
2.4 结构化修改优先
优先通过:
- 显式对象
- 显式字段
- 显式命令
- 显式 ops
避免通过:
- UI 状态猜测
- 整文全文字符串替换
- 第三方编辑器内部瞬时结构直接落库
3. 对象总览
Workspace
├─ Page
│ ├─ DocumentBody
│ │ └─ Block*
│ ├─ PageProperty*
│ ├─ PageLink*
│ └─ Snapshot*
├─ Asset*
├─ Task*
├─ AgentSession*
├─ CommandLog*
└─ Event*
Reference
├─ block -> block
├─ block -> page
├─ block -> asset-fragment
├─ page -> asset
└─ task -> page/block/asset
4. Workspace
Workspace 是系统的顶层容器。
建议字段:
workspace_idslugtitlecreated_atupdated_atowner_actor_iddefault_localestorage_policysync_policyfeature_flagsarchived_at
职责:
- 隔离页面、资产、任务、日志
- 挂载存储策略与同步策略
- 作为权限边界与导出边界
不负责:
- 具体页面内容
- UI 布局
- 当前用户会话态
5. Page
Page 是笔记系统的主内容容器。
5.1 Page 的定位
它不是“某个编辑器文件”,而是:
- 一条知识对象
- 一个文档入口
- 一个块树正文容器
- 一个可被引用、索引、审计的实体
5.2 建议字段
page_idworkspace_idparent_page_id(允许页面树)titleslugiconcover_asset_idbody_root_block_idpage_type(note | doc | database_record | inbox | template | system)status(active | archived | deleted)created_atupdated_atlast_edited_atlast_edited_bycurrent_revision
5.3 PageProperty
页面属性不应和前端表格视图绑死。
建议独立对象:
property_keyvalue_typevaluedisplay_hintsource
可用于:
- 标签
- 时间
- 状态
- 优先级
- 自定义结构化元数据
6. DocumentBody 与 Block
6.1 为什么以 Block 为正文主模型
因为从既有 mnote / mnote-next 的稳定人层语义看,真正稳定的是:
- 单块编辑
- 在某块后插入块
- 删除块
- 重排块
- 缩进层级
- 页面引用与块引用占位
- 复杂块占位
这说明“块”比“整篇富文本 JSON”更接近系统真实操作单元。
6.2 Block 建议字段
block_idworkspace_idpage_idparent_block_idprev_block_idnext_block_idsort_keyblock_typecontentpropsannotationsstatuscreated_atupdated_atcreated_byupdated_byrevision
6.3 BlockType 建议
最小集合建议:
paragraphheadingbulleted_list_itemnumbered_list_itemtodoquotecode_blockdividercalloutpage_referenceblock_referenceembed_assetembed_viewembed_onlyofficeembed_mindmapembed_tablesystem_placeholder
原则:
- 类型应描述语义,不描述某个前端组件名
embed_*表示“外部能力挂件”,不是事实层自己变成那个系统
6.4 Block.content
建议:
- 文本类块使用结构化 inline span 序列
- 避免只存单纯 HTML
- 避免直接依赖第三方编辑器私有 schema
建议形态:
{
"spans": [
{ "type": "text", "text": "hello" },
{ "type": "page_ref", "page_id": "page_xxx", "title": "项目计划" },
{ "type": "text", "text": " world" }
]
}
6.5 Block.props
只放结构化、有限、可校验字段,例如:
levelcheckedcollapsedindentlanguagealignwidthheightasset_idview_id
避免把任意 UI 状态塞进 props。
7. Asset
Asset 是所有非正文主块树内容的统一挂载对象。
7.1 Asset 范围
包括:
- 图片
- docx
- xlsx
- pptx
- 音频
- 视频
- 导出文件
- OCR 中间产物
- 结构提取结果
7.2 建议字段
asset_idworkspace_idstorage_keyoriginal_namemime_typesize_byteschecksumorigin(upload / import / generated / synced)asset_kind(image / pdf / office / audio / video / binary / extracted_text)created_atupdated_atcreated_bystatuslatest_version_id
7.3 AssetVersion
附件应支持版本化。
建议:
asset_version_idasset_idversion_nostorage_keychecksumderived_from_version_idcreated_atcreated_bychange_reason
这样才能支撑:
- OnlyOffice 编辑回写
- OCR 重跑
- 导入转换
- AI 修改资产派生内容
8. Reference
Reference 是知识型系统的关键对象,不能只做正文里的临时 token。
8.1 Reference 范围
- 块引用块
- 页面引用
- 资产片段引用
- PDF 页码引用
- Office 书签/段落锚点引用
- URL 引用
- 检索结果引用
8.2 建议字段
reference_idworkspace_idsource_object_typesource_object_idtarget_object_typetarget_object_idanchorlabelsnippetconfidencecreated_atcreated_byref_kind
8.3 Anchor
anchor 建议作为独立结构:
{
"kind": "pdf_page",
"page": 12,
"bbox": null,
"text_quote": "..."
}
或:
{
"kind": "office_bookmark",
"bookmark": "Heading_3",
"text_quote": "..."
}
原则:
- 锚点是系统对象,不是编辑器私有游标
- 锚点失效时要能标记 stale,而不是静默消失
9. SelectionAnchor
SelectionAnchor 不是长期事实主对象,但在 Agent / 编辑器桥接中有价值。
它表示:
- 当前选区
- 当前光标
- 当前活动页
- 当前资产中的定位点
建议定位为:
- 短生命周期上下文对象
- 可存入 AgentSession / UI Session
- 默认不直接作为主事实落库
因为:
- 它变化太频繁
- 容易和编辑器宿主耦合
- 更适合作为命令输入上下文
10. Task
Task 既是用户任务,也是 AI 工作单元。
10.1 建议字段
task_idworkspace_idtitledescriptiontask_typestatuspriorityassignee_actor_idsource_page_idsource_block_idinput_payloadoutput_payloadcreated_atupdated_atdue_atcompleted_at
10.2 为什么纳入领域模型
因为 AI 长期介入后,很多能力不是即时编辑,而是:
- 导入任务
- 提取任务
- OCR 任务
- 摘要任务
- 索引重建任务
- 同步任务
这些都应进入系统内核,而不是散在外部脚本里。
11. AgentSession
AgentSession 表示某次 AI 介入的上下文单元。
11.1 建议字段
agent_session_idworkspace_idprovidermodelinitiator_actor_idstatusstarted_atupdated_atended_attool_policyconfirmation_policysummary
11.2 不应存什么
不应把整份聊天 UI 状态直接当作领域模型核心。
建议分开:
- 领域层只保留会话元信息、工具调用摘要、事件链路
- 详细消息可作为附属日志或导出工件保存
12. CommandLog 与 Event
12.1 CommandLog
代表一次显式操作请求。
建议字段:
command_idworkspace_idcommand_nameactorsourcetargetpayload_hashreasonrefsidempotency_keydry_runstatusrequested_atfinished_aterror_codeerror_message
12.2 Event
代表命令执行后产生的事实变化。
建议字段:
event_idworkspace_idcommand_idevent_typeobject_typeobject_idbefore_revisionafter_revisionpayloadcreated_at
原则:
- 命令与事件分离
- 先有意图,再有变化
- 审计必须能回答“谁因为什么改了什么”
13. View / Derived Object
以下对象建议明确标注为派生对象,不直接当真相:
- TOCView
- BacklinkView
- SearchHit
- KnowledgeGraphView
- MindmapProjection
- OnlyOfficeProjection
- PagePreview
- DailyDigest
它们的共同特点:
- 来自事实层投影
- 可以缓存
- 可以失效
- 可以重建
14. Mindmap 的正确定位
从既有设计看,Mindmap 很适合走结构化 ops 协议。
但在 mnote-rust 中,建议将其定义为:
Asset或ViewProjection的一种- 由
Page / Block / Reference / Asset投影生成或承载 - 支持独立存储其节点视图结构
- 但不让它成为全系统唯一知识主模型
建议:
- 若是“页面内导图块”,则作为
embed_mindmapblock 挂载 - 若是“独立导图资产”,则作为
Asset(kind=mindmap) - AI 修改导图时,走
MindmapOp[],但最终仍写入系统命令日志
15. OnlyOffice 的正确定位
OnlyOffice 不应被建模为“Page 本体”,应被建模为:
Asset(kind=office)AssetVersionOnlyOfficeAdapterSessionSelectionAnchor(kind=office_*)Reference(anchor=office_*)
也就是说:
- Office 文档是系统资产
- OnlyOffice 是该资产的一种编辑适配器
- 编辑产生新版本与事件
- AI 可以通过插件/适配器读当前选区、插入内容、替换内容
- 但系统真相依然在你的领域模型与资产版本链里
16. v0 必须避免的错误
16.1 不要把前端 store 当领域模型
例如:
- 当前页面 UI 选中态
- 面板展开态
- 聊天输入框草稿
这些不应进入核心领域。
16.2 不要把第三方编辑器 JSON 当系统法典
否则未来:
- 替换编辑器会非常痛苦
- AI 只能学编辑器私有结构
- CLI 难以稳定操作
16.3 不要把全文字符串替换当主修改方式
必须保留结构化修改能力。
16.4 不要把向量库结果当事实对象
向量结果是检索派生物,不是知识真相。
17. 一句话结论
mnote-rust 的领域模型应以 Workspace / Page / Block / Asset / Reference / Task / AgentSession / CommandLog / Event 为核心;
Mindmap、OnlyOffice、搜索结果、AI 面板都只是围绕这些核心对象形成的投影、适配器或任务系统,而不能反客为主。