## 节点包含表格时的渲染逻辑(MindMap 前端) 本文件汇总“当节点内容中有表格时”的数据流、渲染、样式、交互与导出路径,便于快速定位问题与修改。 ### 一、总体流程 - **输入来源**: - Markdown 表格(GFM) - 已有 HTML(``) - **转换阶段**: - Markdown → HTML:解析后输出 `
`(附基础样式)。 - HTML → Markdown(需要时):优先用 Vditor 的 `html2md`;内置兜底逻辑会提取 `
` 为 GFM 格式。 - **节点渲染**: - 优先使用 `dangerouslySetInnerHTML` 将 HTML 直接写入节点 DOM。 - 若是纯文本则走普通 `topic` 文本渲染。 - **样式覆盖**: - 统一为表格设置固定布局、边框、间距、`white-space: normal` 等,避免被思维导图默认排版影响。 - **交互编辑**: - 双击含表格的节点 → 走“表格专用编辑”流程(弹出覆盖层,按 Markdown 表格编辑)。 - **图片导出(SVG)**: - 发现 `
` 时,导出使用 `foreignObject` 渲染,并内联样式与添加背景矩形,确保版式一致。 --- ### 二、数据来源与转换 - **Markdown → HTML(保留为 `
`)** - 位置:`frontend/src/components/MindMap.vue` - 逻辑:将 GFM 表格替换为 `
`,并生成 `/` 与单元格基础内联样式。 - **渲染后统一后处理** - 位置:`frontend/src/utils/markdownRenderer.js` - 逻辑:把裸 `
` 补成 `
`,并处理代码块语法高亮等。 - **HTML → Markdown(用于回填编辑器/导出)** - 位置:`frontend/src/components/MindMap.vue` - 逻辑:若缺少 Markdown 源,优先 `Vditor.html2md`;否则解析 DOM,将 `
` 转回 GFM 表格(含表头/表体)。 示例 Markdown: ```markdown | A | B | |---|---| | 1 | 2 | ``` 渲染为: ```html
... ``` --- ### 三、节点渲染优先级与更新 - **优先级**:`dangerouslySetInnerHTML` > `markdown` > `topic` 文本。 - **直接写入 DOM**:更新节点时,如果存在 `dangerouslySetInnerHTML`,直接 `nodeElement.innerHTML = dangerouslySetInnerHTML`。 - **回退渲染**:当内容不是 Markdown 时,回退渲染会先清理重复符号;若检测到 `
`,不做列表转换,直接保留表格结构。 涉及位置: - `frontend/src/components/MindMap.vue`(保存与“直接设置 HTML”) - `frontend/src/lib/mind-elixir/src/utils/dom.ts`(回退渲染与表格检测) --- ### 四、样式与布局(确保表格按网格显示) - 全局样式(保证在节点内渲染出的 `
` 有固定布局/合并边框/边框色): - `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` 含 `
`,走“表格编辑”。 - `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` 中是否含 `
`: - 含表格:使用 `foreignObject` 嵌入 HTML,计算节点尺寸,创建背景矩形,并将所需样式内联化以确保导出与画布一致;表格本身在 `foreignObject` 内按浏览器 HTML 布局渲染。 - 非表格 HTML:优先尝试原生 SVG 文本渲染;必要时退回 `foreignObject`。 --- ### 七、关键判断点一览 - 是否包含表格: - 通过检测 `''`、`'
'` 或 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`