112 lines
5.3 KiB
Markdown
112 lines
5.3 KiB
Markdown
## 节点包含表格时的渲染逻辑(MindMap 前端)
|
||
|
||
本文件汇总“当节点内容中有表格时”的数据流、渲染、样式、交互与导出路径,便于快速定位问题与修改。
|
||
|
||
### 一、总体流程
|
||
- **输入来源**:
|
||
- Markdown 表格(GFM)
|
||
- 已有 HTML(`<table>`)
|
||
- **转换阶段**:
|
||
- Markdown → HTML:解析后输出 `<table class="markdown-table">`(附基础样式)。
|
||
- HTML → Markdown(需要时):优先用 Vditor 的 `html2md`;内置兜底逻辑会提取 `<table>` 为 GFM 格式。
|
||
- **节点渲染**:
|
||
- 优先使用 `dangerouslySetInnerHTML` 将 HTML 直接写入节点 DOM。
|
||
- 若是纯文本则走普通 `topic` 文本渲染。
|
||
- **样式覆盖**:
|
||
- 统一为表格设置固定布局、边框、间距、`white-space: normal` 等,避免被思维导图默认排版影响。
|
||
- **交互编辑**:
|
||
- 双击含表格的节点 → 走“表格专用编辑”流程(弹出覆盖层,按 Markdown 表格编辑)。
|
||
- **图片导出(SVG)**:
|
||
- 发现 `<table>` 时,导出使用 `foreignObject` 渲染,并内联样式与添加背景矩形,确保版式一致。
|
||
|
||
---
|
||
|
||
### 二、数据来源与转换
|
||
- **Markdown → HTML(保留为 `<table>`)**
|
||
- 位置:`frontend/src/components/MindMap.vue`
|
||
- 逻辑:将 GFM 表格替换为 `<table class="markdown-table">`,并生成 `<thead>/<tbody>` 与单元格基础内联样式。
|
||
- **渲染后统一后处理**
|
||
- 位置:`frontend/src/utils/markdownRenderer.js`
|
||
- 逻辑:把裸 `<table>` 补成 `<table class="markdown-table">`,并处理代码块语法高亮等。
|
||
- **HTML → Markdown(用于回填编辑器/导出)**
|
||
- 位置:`frontend/src/components/MindMap.vue`
|
||
- 逻辑:若缺少 Markdown 源,优先 `Vditor.html2md`;否则解析 DOM,将 `<table>` 转回 GFM 表格(含表头/表体)。
|
||
|
||
示例 Markdown:
|
||
```markdown
|
||
| A | B |
|
||
|---|---|
|
||
| 1 | 2 |
|
||
```
|
||
渲染为:
|
||
```html
|
||
<table class="markdown-table">...
|
||
```
|
||
|
||
---
|
||
|
||
### 三、节点渲染优先级与更新
|
||
- **优先级**:`dangerouslySetInnerHTML` > `markdown` > `topic` 文本。
|
||
- **直接写入 DOM**:更新节点时,如果存在 `dangerouslySetInnerHTML`,直接 `nodeElement.innerHTML = dangerouslySetInnerHTML`。
|
||
- **回退渲染**:当内容不是 Markdown 时,回退渲染会先清理重复符号;若检测到 `<table>`,不做列表转换,直接保留表格结构。
|
||
|
||
涉及位置:
|
||
- `frontend/src/components/MindMap.vue`(保存与“直接设置 HTML”)
|
||
- `frontend/src/lib/mind-elixir/src/utils/dom.ts`(回退渲染与表格检测)
|
||
|
||
---
|
||
|
||
### 四、样式与布局(确保表格按网格显示)
|
||
- 全局样式(保证在节点内渲染出的 `<table>` 有固定布局/合并边框/边框色):
|
||
- `frontend/src/App.vue` 中对 `.mind-elixir .map-container .topic table` 的规则。
|
||
- 组件内样式(覆盖思维导图的 `white-space`、`display`):
|
||
- `frontend/src/components/MindMap.vue` 中 `.topic .topic-text.markdown-content table` 及 `th/td/tr` 规则。
|
||
- 统一 `th/td` 的内边距、边框与交互高亮,避免被默认 inline 布局破坏行列结构。
|
||
|
||
---
|
||
|
||
### 五、交互:双击进入表格编辑
|
||
- 位置:
|
||
- `frontend/src/lib/mind-elixir/src/mouse.ts`:双击节点时若 `innerHTML` 含 `<table>`,走“表格编辑”。
|
||
- `frontend/src/lib/mind-elixir/src/nodeOperation.ts`:`beginEdit` 内部判断表格后调用 `editTableNode`。
|
||
- 编辑方式:
|
||
- `editTableNode` 弹出覆盖层,编辑 Markdown 表格源(包含 HTML↔Markdown 的转换工具)。
|
||
|
||
---
|
||
|
||
### 六、导出图片(SVG)中的表格渲染
|
||
- 位置:`frontend/src/lib/mind-elixir/src/plugin/exportImage.ts`
|
||
- 检测 `dangerouslySetInnerHTML` 中是否含 `<table>`:
|
||
- 含表格:使用 `foreignObject` 嵌入 HTML,计算节点尺寸,创建背景矩形,并将所需样式内联化以确保导出与画布一致;表格本身在 `foreignObject` 内按浏览器 HTML 布局渲染。
|
||
- 非表格 HTML:优先尝试原生 SVG 文本渲染;必要时退回 `foreignObject`。
|
||
|
||
---
|
||
|
||
### 七、关键判断点一览
|
||
- 是否包含表格:
|
||
- 通过检测 `'<table'`、`'<td>'`、`'<th>'` 或 Markdown 中的 `|` 来作出路径选择(如走表格编辑、使用 `foreignObject` 导出等)。
|
||
- 渲染选择:
|
||
- 有 `dangerouslySetInnerHTML` → 直接注入 HTML;
|
||
- 否则尝试 `markdown` → `marked/自定义解析`;
|
||
- 最后回退到纯文本 `topic`。
|
||
|
||
---
|
||
|
||
### 八、常见问题与建议
|
||
- 若表格在节点中“挤成一行”或“行列错乱”,优先检查是否有样式覆盖了:
|
||
- `display: table-*`、`white-space: normal !important`、`table-layout: fixed`、`border-collapse: collapse` 是否生效。
|
||
- 导出图片中表格错位:确认 `foreignObject` 是否被禁用、样式是否已内联、节点尺寸计算是否准确。
|
||
- 需要统一风格时,优先改 `.markdown-table` 与 `.topic .topic-text.markdown-content table` 相关样式。
|
||
|
||
---
|
||
|
||
### 相关文件清单(便于跳转)
|
||
- `frontend/src/components/MindMap.vue`
|
||
- `frontend/src/utils/markdownRenderer.js`
|
||
- `frontend/src/lib/mind-elixir/src/utils/dom.ts`
|
||
- `frontend/src/lib/mind-elixir/src/mouse.ts`
|
||
- `frontend/src/lib/mind-elixir/src/nodeOperation.ts`
|
||
- `frontend/src/lib/mind-elixir/src/plugin/exportImage.ts`
|
||
- `frontend/src/App.vue`
|
||
|