Files
mnote/design/s1-core-plan.md
T

152 lines
8.6 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.
# S1 核心内核实施方案(Mindmap 内核对标 KMind
目标:在不改变现有 Next.js + BlockNote + Yjs + Supabase 架构的前提下,完成 Stage S1 中的 5 个核心能力,形成可落地的代码骨架与开发清单。
---
## 1. MindmapCanvas(画布容器 / 多根模式 / 懒渲染)
| 对标 | MNOTE 方案 |
|------|-----------|
| `design/Kmind/js/0.js:719-1160``MindMap` 类,负责容器初始化、SVG 分层、大小检测、延迟渲染、多根导图 | 在 `src/components/mindmap/canvas/MindmapCanvas.tsx`(新建)中封装一个 React 组件,内部通过 `@xyflow/react``ReactFlowProvider` + `useReactFlow` 控制视图。|
### 关键设计
1. **多根模式**:允许 `props.roots` 为数组;在 BlockNote ↔ mindmap 同步时,若一个文档存在多个 mindmap,即 `mindmap_meta` 行 >1,则对每个根节点创建独立的 React Flow `Node` 子树,并在 `MindmapCanvas` 中渲染多个 root。
2. **容器重试/懒加载**:借鉴 KMind 的 `containerSizeRetryConfig`,封装 `useElementRect` hook,支持 `IntersectionObserver` 判断是否进入视窗,在进入前仅挂起渲染。
3. **SVG 分层**React Flow 默认使用单一 `svg`;需要添加自定义背景(连线)、节点容器及“其他层”(如选框、直觉按钮)。做法:通过 `ReactFlow``nodeTypes` + `edgeTypes` + 自定义 `Background`/`Controls` 组件来模拟 `lineDraw`/`nodeDraw`/`otherDraw`
4. **画布状态管理**:使用 Zustand`src/store/useMindmapStore.ts` 新建)保存 `scale`, `translate`, `activeNodes`, `multiRootMode` 等状态,方便其他模块(快捷键、TextEdit)订阅。
### 输出物
- `src/components/mindmap/canvas/MindmapCanvas.tsx`
- `src/components/mindmap/canvas/useElementRect.ts`
- `src/store/useMindmapStore.ts`
---
## 2. MindLayoutEngine(渲染管线与多布局)
| 对标 | MNOTE 方案 |
|------|-----------|
| `Render` 类(`design/Kmind/js/0.js:11753-15120`)整合布局、懒渲染、节点缓存和命令 | 拆成 `MindLayoutEngine`(纯 TS,负责布局计算)和 `MindmapRenderer`React hook,负责 diff & 渲染)两部分。|
### 关键设计
1. **数据模型**:使用 `MindmapNode`(包含 `id`, `parentId`, `children`, `data`, `layout`)与 `MindmapTree`(单根/多根)。使用 `zod` 校验。
2. **布局策略**:引入 elkjs(cjs 版本)或自己实现逻辑结构布局。第一阶段至少实现 `LOGICAL_STRUCTURE``MIND_MAP`,接口定义:
```ts
interface LayoutEngine {
name: 'logical' | 'mind' | ...;
compute(tree: MindmapTree, options: LayoutOptions): LayoutResult;
}
```
3. **节点缓存**:维护 `nodeCache: Map<string, LayoutResultNode>`,当节点数据未变化时复用位置。通过 `useMemo` + `JSON.stringify` diff 或者基于 `hash`.
4. **命令注册**:结合 `MindmapCommandBus`Zustand store + typed events),将 `INSERT_NODE` / `SET_NODE_STYLE` 等命令映射到 `MindLayoutEngine` -> `MindmapRenderer`.
5. **Generalization & multi-root**:沿用 KMind 的 `generalization` 数据结构:每个节点 `data.generalization?: { range: [start,end]; text: string }[]`,在布局时对“概要节点”作为独立 branch 处理。
### 输出物
- `src/lib/mindmap/layout/MindLayoutEngine.ts`
- `src/lib/mindmap/layout/engines/logicalStructure.ts`
- `src/lib/mindmap/layout/engines/mindMap.ts`
- `src/lib/mindmap/command/MindmapCommandBus.ts`
---
## 3. MindmapShortcutController(快捷键与命令路由)
| 对标 | MNOTE 方案 |
|------|-----------|
| `KeyCommand` `design/Kmind/js/0.js:11709-11890` | 创建 `src/components/mindmap/shortcut/MindmapShortcutController.ts`Hook 化 `keydown` 捕获、实例隔离、编辑模式白名单。|
### 关键设计
1. **多实例隔离**:用一个全域 `activeInstanceId`ref + `MindmapCanvas` `useEffect` 控制,仅当前 canvas 响应快捷键。
2. **捕获阶段阻断**:在 `document` capture 阶段阻止 `Ctrl+Z`, `Ctrl+V` 等冒泡,若不在 mindmap 内部则放行。
3. **映射**:提供 `registerShortcut(keyCombo, handler, options)` API,内部用 `Map<string, ShortcutEntry[]>`,默认注册:新增节点、删除、展开、直觉按钮等。
4. **自定义检查**:暴露 `shouldHandleEvent(e)` 回调,允许 BlockNote/其它面板禁用快捷键。
### 输出物
- `src/components/mindmap/shortcut/MindmapShortcutController.ts`
- `src/types/mindmap/shortcuts.ts`
---
## 4. TextEdit 内嵌富文本
| 对标 | MNOTE 方案 |
|------|-----------|
| Quill `history/input/keyboard` + `render/TextEdit` | 在 `src/components/mindmap/text` 下实现 `MindmapTextEditor`(挂载于节点上方)与 `useMindmapTextEdit` Hook。|
### 关键设计
1. **编辑器选择**:为了兼容 BlockNote,可采用 `@blocknote/core` 的 `InlineContent` 或 mini TipTap 实例。若沿用 Quill,需要自定义 bubble toolbar + history 模块。
2. **实时测量**:使用 `ResizeObserver` 或 canvas measure,模拟 KMind 的 `node.createTextNode` -> `getNodeRect`,在编辑时更新 `width/height` 并触发布局。
3. **粘贴清洗**:复用 KMind 的 `handleInputPasteText`、`defenseXSS`(位置 `design/Kmind/js/0.js` utils 部分),转成 TypeScript。
4. **撤销栈**:复刻 `history` 模块逻辑,处理 `undo/redo` 按键,保持与 `MindmapShortcutController` 协调。
### 输出物
- `src/components/mindmap/text/MindmapTextEditor.tsx`
- `src/components/mindmap/text/useMindmapTextEdit.ts`
- `src/lib/mindmap/text/pasteSanitizer.ts`
---
## 5. Link / Attachment 解析层
| 对标 | MNOTE 方案 |
|------|-----------|
| `checkSiyuanLinkFormatData` / `checkSiyuanPdfUrlFormatData` (`design/Kmind/js/0.js:12040-12380`) | 在 `src/lib/mindmap/parser/linkParser.ts` 中封装同功能模块,输出标准化 `MindmapLink`.|
### 关键设计
1. **类型定义**
```ts
type MindmapLink =
| { type: 'block'; blockId: string; title?: string }
| { type: 'document'; documentId: string; title?: string }
| { type: 'mindmap-node'; mindmapId: string; nodeId: string }
| { type: 'pdf'; path: string; id: string; imageUrl?: string; title?: string }
| { type: 'url'; url: string; title?: string };
```
2. **粘贴入口**`MindmapTextEditor` 在 `onPaste` 中调用 parser,将结果写入 `node.data.link` 并触发 Command `SET_NODE_HYPERLINK`。
3. **附件扩展**:在 parser 中同时识别 `siyuan://plugins/kmind-plugin?data=...`、`siyuan://blocks/`、`((id 'title'))`、PDF 标注、普通 URL。
### 输出物
- `src/lib/mindmap/parser/linkParser.ts`
- `src/types/mindmap/link.ts`
---
## 6. 调试与验证
- 单元测试:使用 Vitest 对 `MindLayoutEngine`, `linkParser`, `MindmapCommandBus` 编写测试用例(位于 `src/lib/mindmap/__tests__`)。
- Storybook/Playground:创建 `src/components/mindmap/dev/MindmapPlayground.tsx`,用于手动测试多根、快捷键、TextEdit。
- 集成测试:待 P4 同步控制器完成后,在 Playwright 场景中验证:新增节点 -> 更新 BlockNote -> 重新渲染。
---
## ChecklistS1 完成判定)
- [ ] `MindmapCanvas` 支持多根、懒渲染、画布缩放状态。
- [ ] `MindLayoutEngine` 能输出 `LOGICAL_STRUCTURE` 布局并驱动 React Flow。
- [ ] `MindmapCommandBus` + `ShortcutController` 能响应基础快捷键(Enter, Tab, Delete, Ctrl+Z)。
- [ ] `MindmapTextEditor` 可打开/编辑节点文本,支持撤销/粘贴清洗。
- [ ] `linkParser` 能识别 siyuan 链接、PDF 标注并写入节点数据。
---
## 建议的开发顺序与依赖
1. **基础设施**:搭建 `useMindmapStore`、`MindmapCommandBus`、类型定义(`MindmapNode`, `MindmapTree`, `MindmapLink`)。
2. **布局引擎**:实现 `MindLayoutEngine` + `logicalStructure` 布局,并在 Vitest 中用静态树校验输出。
3. **Canvas 集成**:创建 `MindmapCanvas`,接入 `React Flow`,将布局结果映射成节点/连线,接通 store。
4. **快捷键/命令**:实现 `MindmapShortcutController`,注册插入/删除/折叠等命令,验证命令总线。
5. **TextEdit & Link Parser**:落地 `MindmapTextEditor` 和粘贴解析,把链接写入节点数据。
6. **调试工具**:搭建 `MindmapPlayground` + Vitest/Storybook 场景,验证多根与富文本。
### 外部依赖/资产
- `@xyflow/react`React Flow 11+
- `elkjs`(或其他布局库)——生成自动布局
- `zustand`, `immer`(状态管理)
- `@tiptap/react` 或 Quill(富文本)
- `vitest`, `testing-library/react`
---
> 下一步:按照本方案拆解具体任务,在 `mindlist.md` 的 S1 项目上依次打勾,并在备注表记录进度与提交。