208 lines
12 KiB
Markdown
208 lines
12 KiB
Markdown
# Wolai-clone 思维导图方案(v3.1)——复刻 MindManager 体验并与 BlockNote 大纲双向同步
|
||||
|
|
|
|||
|
|
## 0. 背景与目标
|
|||
|
|
|
|||
|
|
- v3.0 架构已确定使用 Next.js + BlockNote + Yjs,需新增思维导图模块,实现与笔记大纲/块树实时联动,体验对齐 MindManager/Wolai/Kmind。
|
|||
|
|
- 核心诉求:**极致整齐的自动布局**、**节点富内容(图片/富文本/图标/link)**、**跨文档/跨导图的链接能力**、**与笔记大纲双向同步**。
|
|||
|
|
- 设计方向:继续使用 @xyflow/react(React Flow 11+)作为画布内核,自研布局 & 样式层,数据完全托管在 Supabase(documents 表)与独立 mindmap 表中。
|
|||
|
|
|
|||
|
|
## 1. 体验原则
|
|||
|
|
|
|||
|
|
1. **MindManager 级布局**:节点水平/垂直间距固定,主干左右对称;支持“经典曲线”“直角线”两种连线;节点宽度随内容自动适配,最多两行后溢出省略。
|
|||
|
|
2. **富内容节点**:每个节点可包含标题、富文本摘要、图标、emoji、标签、封面图片;支持 Markdown/快捷键编辑。
|
|||
|
|
3. **多级链接**:节点可跳转到:
|
|||
|
|
- 当前文档某块(blockId)→ 通过 `block://{id}` 链接并高亮目标块。
|
|||
|
|
- 其他笔记(documentId)→ 打开对应页面。
|
|||
|
|
- 其他导图的节点(mindmapId+nodeId)→ 支持导图嵌套导航。
|
|||
|
|
4. **实时同步**:导图结构映射到笔记大纲(Tree);改导图 = 改大纲;在 BlockNote 中增删标题块 = 导图自动更新节点。
|
|||
|
|
5. **Wolai/Kmind 外观**:圆角矩形 + 轻投影,hover 显示手型 + 菜单,选中高亮;暗黑/亮色一致。支持缩放、平移、迷你地图。
|
|||
|
|
|
|||
|
|
## 2. 技术架构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
BlockNote (Y.Doc: document_tree)
|
|||
|
|
│
|
|||
|
|
├─ outline nodes ↔ mindmap nodes (双向映射表)
|
|||
|
|
│
|
|||
|
|
Mindmap SubDoc (Y.Doc: mindmap_{document_id})
|
|||
|
|
│
|
|||
|
|
React Flow 画布 + 自研 MindLayout Engine
|
|||
|
|
│
|
|||
|
|
Supabase tables:
|
|||
|
|
documents (content jsonb)
|
|||
|
|
mindmap_meta (id, document_id, layout_prefs, theme)
|
|||
|
|
mindmap_nodes (id, mindmap_id, block_id, parent_id, data jsonb, position cache)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- 每份文档默认有一份 mindmap(也支持多个 mindmap);mindmap 数据存于 `mindmap_nodes`,并同步缓存到 BlockNote content(便于离线/导出)。
|
|||
|
|
- 协作层使用 Yjs SubDoc:当打开导图时订阅 `mindmap_{document_id}`,React Flow 节点/边与 SubDoc 同步,保持毫秒级更新。
|
|||
|
|
|
|||
|
|
## 3. 视觉规格(融合 MindManager 细节)
|
|||
|
|
|
|||
|
|
- **节点样式**:
|
|||
|
|
- 尺寸:`min-w 240px`,默认 280px,最大 384px;高度随内容自动撑开,不超过两行,超出显示省略。
|
|||
|
|
- 圆角 24px、2px 边框;选中 `border-blue-500 ring-4 ring-blue-100 scale-105`,未选中 `border-slate-300 hover:border-blue-400 hover:shadow-2xl`。
|
|||
|
|
- 背景渐变 `linear-gradient(135deg,#ffffff 0%,#f8fafc 100%)`,阴影 `0 4px 15px rgba(0,0,0,0.08)`;选中提升到 `0 10px 25px rgba(59,130,246,0.15)`。
|
|||
|
|
- 左上角支持图标徽章(36px 圆形),顶部可插入封面(最大高 160px),右侧有链接指示器。
|
|||
|
|
- 示例 className:
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
const base = `
|
|||
|
|
relative px-5 py-3 min-w-60 max-w-96 rounded-2xl
|
|||
|
|
bg-white border-2 shadow-lg transition-all duration-200
|
|||
|
|
`;
|
|||
|
|
const active = 'border-blue-500 ring-4 ring-blue-100 scale-105';
|
|||
|
|
const idle = 'border-slate-300 hover:border-blue-400 hover:shadow-2xl';
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- **连线样式**:
|
|||
|
|
- MindManager 曲线:`M sx sy C sx+100 sy targetX-100 targetY targetX targetY`,颜色 `#94a3b8`,宽度 3px。
|
|||
|
|
- 备选直角线(smoothstep)满足 Kmind 用户;末端 arrowhead 半径 6px。
|
|||
|
|
|
|||
|
|
- **画布与工具栏**:
|
|||
|
|
- 画布背景 `bg-gradient-to-br from-slate-50 to-slate-100`,使用 React Flow `Background` gap 24px。
|
|||
|
|
- 顶部 56px 工具栏,包含自动排版、主题切换、导出、折叠/展开、缩放重置;工具栏按钮遵循 `px-4 py-2 rounded-lg` 规范。
|
|||
|
|
|
|||
|
|
## 4. 对齐 MindManager 的布局策略
|
|||
|
|
|
|||
|
|
1. **层级布局**:根节点居中,一级节点左右分布;根据用户设置(左/右/双向)动态计算。
|
|||
|
|
2. **自动间距**:使用自研 `MindLayout Engine`(基于 DAG 布局),输入节点树 + 样式参数,输出绝对坐标;支持:
|
|||
|
|
- 同层节点纵向等距排列。
|
|||
|
|
- 子节点根据最长文本宽度自动算水平偏移,保证连线整齐。
|
|||
|
|
- 支持节点折叠/展开,折叠时子树隐藏但保留布局缓存。
|
|||
|
|
3. **连线样式**:提供“曲线(贝塞尔)”“直角线”两种;线条宽度、颜色可继承主题。
|
|||
|
|
4. **对齐辅助**:拖动节点时展示辅助线,松手后自动吸附至推荐位置;支持 `Shift+拖拽` 只在水平或垂直方向移动。
|
|||
|
|
|
|||
|
|
## 5. 节点内容设计
|
|||
|
|
|
|||
|
|
字段结构(存储于 `mindmap_nodes.data`):
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"title": "节点标题",
|
|||
|
|
"richText": "<p>富文本</p>",
|
|||
|
|
"icon": "mdi-lightbulb",
|
|||
|
|
"emoji": "💡",
|
|||
|
|
"tags": ["优先级:高", "待讨论"],
|
|||
|
|
"image": { "url": "...", "width": 200, "height": 120 },
|
|||
|
|
"link": {
|
|||
|
|
"type": "block" | "document" | "mindmap-node" | "url",
|
|||
|
|
"targetId": "block_xxx / doc_xxx / mindmap_y/node_z",
|
|||
|
|
"title": "跳转提示"
|
|||
|
|
},
|
|||
|
|
"status": "todo | doing | done",
|
|||
|
|
"collapsed": false
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- 富文本编辑器使用 `@tiptap/react` 迷你实例或 BlockNote 内嵌 mini editor,支持粗体/斜体/高亮/超链接。
|
|||
|
|
- 图片可从 Supabase Storage 选择或粘贴上传,节点支持设置小型封面或内嵌图片。
|
|||
|
|
- 节点图标:内置 MindManager 风格图标库(优先级、进度、标记),同时支持 emoji。
|
|||
|
|
|
|||
|
|
## 6. 链接和导航
|
|||
|
|
|
|||
|
|
| 类型 | 格式 | 交互 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 块链接 | `block://{blockId}` | hover 显示块摘要,点击在文档中滚动并高亮该块。 |
|
|||
|
|
| 文档链接 | `doc://{documentId}` | 打开对应页面,可在侧边栏预览。 |
|
|||
|
|
| 导图节点 | `mind://{mindmapId}/{nodeId}` | 若当前导图即目标,则定位;否则打开目标导图并定位。 |
|
|||
|
|
| 外部 URL | `https://...` | 新标签页打开。 |
|
|||
|
|
|
|||
|
|
- 链接编辑面板提供快速搜索(块/页面/导图节点),并记录最近使用项。
|
|||
|
|
- 支持「一键转块」:把导图节点转换为 BlockNote 内的块,或把块拖入导图生成节点。
|
|||
|
|
|
|||
|
|
## 7. 大纲与导图的双向同步
|
|||
|
|
|
|||
|
|
### 数据映射
|
|||
|
|
|
|||
|
|
- 维护 `outlineNodeId ↔ mindmapNodeId` 映射表,存储在 `mindmap_nodes.block_id` 字段。
|
|||
|
|
- BlockNote 标题块(H1~H4)与导图层级对应;非标题块可作为节点备注(richText)。
|
|||
|
|
|
|||
|
|
### 同步策略
|
|||
|
|
|
|||
|
|
1. **导图 → 大纲**
|
|||
|
|
- 新建节点:创建对应 BlockNote 标题块(Yjs 操作),插入到同级相应位置。
|
|||
|
|
- 删除节点:删除/归档对应块。
|
|||
|
|
- 拖动节点:更新块的父级和排序(BlockNote reorder API)。
|
|||
|
|
2. **大纲 → 导图**
|
|||
|
|
- 在大纲中新建/调整标题块时,触发同步 Hook 更新 mindmap SubDoc。
|
|||
|
|
- 对于仅存在于导图的节点,可标记 `detached=true`,大纲不显示;用户可手动“附着”到大纲。
|
|||
|
|
|
|||
|
|
### 冲突处理
|
|||
|
|
|
|||
|
|
- 通过 Yjs transaction + `lastWriterWins` 策略;若同一节点同时被导图与大纲修改,变更合并后派生 diff,在 UI 中提示“有更新,点击同步”。
|
|||
|
|
- 提供“锁定导图”开关,当导图处于演示模式时暂停同步,避免误差。
|
|||
|
|
|
|||
|
|
## 8. 前端组件分层
|
|||
|
|
|
|||
|
|
1. `MindmapCanvas`:封装 React Flow + 主题/布局;负责渲染节点、连线、背景、缩放器。
|
|||
|
|
2. `MindLayoutEngine`:输入节点树返回位置/尺寸,支持缓存与局部更新。
|
|||
|
|
3. `MindNodeCard`:节点内容组件,内嵌富文本、标签、图片、链接、hover toolbar。
|
|||
|
|
4. `MindLinkPanel`:统一链接管理,搜索块/文档/导图节点。
|
|||
|
|
5. `OutlineSyncController`:监听 BlockNote、导图 SubDoc,执行同步动作。
|
|||
|
|
6. `MindHistorySidebar`:展示导图版本历史/快照(可依赖 Supabase table versions)。
|
|||
|
|
|
|||
|
|
## 9. 数据库 & API
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
create table mindmap_meta (
|
|||
|
|
id uuid primary key default uuid_generate_v4(),
|
|||
|
|
document_id uuid references documents(id),
|
|||
|
|
title text,
|
|||
|
|
layout_prefs jsonb, -- 左/右布局、连线样式、主题
|
|||
|
|
theme text default 'wolai-light',
|
|||
|
|
created_by uuid references auth.users,
|
|||
|
|
created_at timestamptz default now(),
|
|||
|
|
updated_at timestamptz default now()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
create table mindmap_nodes (
|
|||
|
|
id uuid primary key default uuid_generate_v4(),
|
|||
|
|
mindmap_id uuid references mindmap_meta(id) on delete cascade,
|
|||
|
|
parent_id uuid references mindmap_nodes(id),
|
|||
|
|
block_id uuid, -- 可为空(纯导图节点)
|
|||
|
|
order_index integer,
|
|||
|
|
data jsonb,
|
|||
|
|
cached_position jsonb,
|
|||
|
|
created_at timestamptz default now(),
|
|||
|
|
updated_at timestamptz default now()
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- FastAPI Endpoints:
|
|||
|
|
- `GET /mindmaps/{id}`:返回 meta + nodes + outline mapping。
|
|||
|
|
- `POST /mindmaps`:创建新导图(可附加到文档)。
|
|||
|
|
- `PATCH /mindmaps/{id}`:更新布局/主题。
|
|||
|
|
- `POST /mindmaps/{id}/nodes`、`PATCH /.../{nodeId}`、`DELETE ...`:供批量导入/AI/脚本使用。
|
|||
|
|
- `POST /mindmaps/{id}/export`:导出为 MMAP、OPML、PNG、SVG。
|
|||
|
|
|
|||
|
|
## 10. 实施计划
|
|||
|
|
|
|||
|
|
| 阶段 | 目标 | 核心任务 | 输出 |
|
|||
|
|
|------|------|----------|------|
|
|||
|
|
| P0 需求确认(0.5d) | 对齐视觉规范 & 交互 | - 与设计确认节点样式、主题变量、连线风格<br>- 列出与大纲同步的详细规则/边界<br>- 明确链接搜索/跳转需求 | 更新 PRD + Figma 草图 |
|
|||
|
|
| P1 数据与 API(1.5d) | 建表 + 后端接口 | - Supabase 建 `mindmap_meta`/`mindmap_nodes` + RLS<br>- FastAPI mindmap CRUD + 导出占位<br>- 单元测试覆盖 | 后端 PR + Swagger |
|
|||
|
|
| P2 前端内核(2d) | React Flow + 布局引擎 | - 封装 `MindLayoutEngine`,实现左右对称/直角/曲线<br>- 节点/连线主题实现,支持折叠/缩放 | 画布 demo |
|
|||
|
|
| P3 节点富内容(2d) | 节点编辑能力 | - 富文本/图标/图片/标签/状态组件<br>- 链接面板 + 搜索块/文档/导图节点<br>- 粘贴逻辑(从 MindManager/文本导入) | 节点交互完成 |
|
|||
|
|
| P4 同步控制器(2d) | 导图 ↔ 大纲 | - 建立 block ↔ node 映射 SubDoc<br>- 实现双向增删改同步/冲突提示<br>- E2E 测试(Cypress + Playwright 多窗口) | 同步稳定 |
|
|||
|
|
| P5 打磨 & 导出(1.5d) | 性能/体验 | - 虚拟化/懒加载,支持 2k+ 节点<br>- 导出 PNG/SVG/OPML<br>- 快捷键、迷你地图、历史记录 | 发布候选 |
|
|||
|
|
|
|||
|
|
## 11. 验收标准
|
|||
|
|
|
|||
|
|
- [ ] 导图布局与 MindManager 对齐:节点间距统一,拖动自动吸附。
|
|||
|
|
- [ ] 节点支持图片/富文本/图标/标签/链接,复制 MindManager 内容可无损粘贴。
|
|||
|
|
- [ ] 节点链接在不同类型 (block/doc/mind/node) 下跳转准确,带 hover 预览。
|
|||
|
|
- [ ] 与 BlockNote 大纲实时同步,双向修改 200ms 内可见,无冲突。
|
|||
|
|
- [ ] 多人协作时节点光标、拖拽、折叠状态实时共享,无明显抖动。
|
|||
|
|
- [ ] 支持导出 PNG/SVG/OPML/MMAP(后续),可导入 MindManager 文件(可放在扩展阶段)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. 落地提示
|
|||
|
|
|
|||
|
|
- P2 阶段可直接引入 `grok` 方案中的 `MindManagerNode`/`MindManagerEdge` 作为主题模板,结合 Tailwind CSS 变量封装成 `MindNodeCard` 多主题体系。
|
|||
|
|
- 布局计算使用 elkjs(`algorithm=layered`、`elk.layered.nodePlacement.strategy=BRANDES_KOEPF`),封装 `getMindManagerLayout` 并缓存,确保自动排版按钮在 200ms 内完成 500+ 节点重新布局。
|
|||
|
|
- 同步控制器上线前,编写 OPML/MMAP → `mindmap_nodes` 的导入脚本,用真实 MindManager 数据验证字段与链接策略,并准备导图 ↔ 大纲操作回放工具以排查协作冲突。
|
|||
|
|
|
|||
|
|
此方案在保留 MindManager 用户习惯的同时,借助 Supabase + React Flow 构建可扩展的思维导图系统,并与 BlockNote 文档深度联动。按 P0-P5 推进,可在 1.5~2 周内完成 MVP 并持续迭代高级功能。
|