/** * 思维导图插件组件 * 使用 markmap 从 Markdown 文本渲染交互式 SVG 思维导图 */ import { useState, useRef, useEffect, useCallback } from 'react'; import { Button, Empty, Typography, Modal } from 'antd'; import { ExpandOutlined, DownloadOutlined } from '@ant-design/icons'; const { Text } = Typography; const MindmapViewer = ({ markdown = '' }) => { const svgRef = useRef(null); const markmapRef = useRef(null); const [fullscreen, setFullscreen] = useState(false); const [hasContent, setHasContent] = useState(false); const renderMap = useCallback(async (svgEl, md) => { if (!svgEl || !md) return; try { // 动态导入 markmap(避免 SSR 问题) const { Transformer } = await import('markmap-lib'); const { Markmap } = await import('markmap-view'); const transformer = new Transformer(); const { root } = transformer.transform(md); // 清除旧内容 svgEl.innerHTML = ''; // 渲染 markmapRef.current = Markmap.create(svgEl, { autoFit: true, duration: 300, maxWidth: 300, }, root); setHasContent(true); } catch (e) { console.error('Markmap 渲染失败:', e); } }, []); useEffect(() => { if (markdown && svgRef.current) { renderMap(svgRef.current, markdown); } }, [markdown, renderMap]); const handleExport = () => { if (!svgRef.current) return; const svgData = new XMLSerializer().serializeToString(svgRef.current); const blob = new Blob([svgData], { type: 'image/svg+xml' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'mindmap.svg'; a.click(); URL.revokeObjectURL(url); }; return (