Mardown渲染Xmind思维导图

187 阅读3分钟

核心包

使用了SimpleMindMap 这个包 image.png 该包可以实现很多思维导图功能,除核心功能外其它能力都通过插件提供,按需选择。

实现步骤

说明:

这个需求是在公司内AI助手里实现,结合AI助手流式返回的Markdown语句,将其渲染为XMind思维导图内容。具体还结合了Dify平台的智能体配置提示词等相关内容,不是重点,直接说实现步骤。

  1. 首先匹配需要转换的Markdown格式,这里约定了智能体中返回的Mardown被--xmind--开头以--xmindend--结尾,所以需要做的就是匹配接口返回中的这个Markdown代码块。 思路:通过正则匹配开头结尾,将其替换:
// 匹配 --xmind-- 和 --xmindend--
const xmindFullReg = /--xmind--([\s\S]*?)--xmindend--/g;
const xmindReg = /--xmind--([\s\S]*?)--xmindend--/;
export function useXmindMatch(msg, fn) {
	return new Promise((resolve) => {
		const match = msg.content.match(xmindFullReg);
		console.log("匹配结果:", match);
		if (match && match.length) {
			match.forEach(async (matchData) => {
				const matchArray = matchData.match(xmindReg);
				const matchContent = matchArray[1]; // 获取中间的内容
				// 替换为指定的HTML结构
				msg.content = msg.content.replace(
					matchArray[0], 
					""
				);// 匹配后直接替换为空字符串,再下面只需要抛出Markdown内容即可
				resolve(await fn(matchContent, msg));
			});
		} else {
			resolve();
		}
	});
}
  1. 接着在我们处理流式返回的onmessage方法中处理接口内容content,只需要在每次更新流式返回答案后调用上面的useXmindMatch,更新每一次渲染。实现在接口返回一次完整的Markdown内容后可以立即渲染出对应xmind导图。
useXmindMatch(this.currentAnswer, (matchXmindContent) => {
					this.handlerXmindMatch(matchXmindContent, this.currentAnswer);
				});
handlerXmindMatch(matchContent, msg) {
			// 将 XMind 数据存储到消息对象中,供后续使用
			msg.xmindData = matchContent;
		},
  1. 接着核心代码是新建一个XmindView组件,实现调用SimpleMindMap包转换为脑图视图组件。核心功能代码:直接上代码
<template>
    <div>
        <div id="mindMapContainer" ref="mindMapContainer" />
        <el-button style="margin-top: 10px;" @click="exportMindMap">
            导出Xmind
        </el-button>
    </div>
</template>

<script>
import MindMap from "simple-mind-map";
import Export from "simple-mind-map/src/plugins/Export.js";
import ExportXMind from "simple-mind-map/src/plugins/ExportXMind.js";
import markdown from "simple-mind-map/src/parse/markdown.js";

// 使用插件
MindMap.usePlugin(ExportXMind);
MindMap.usePlugin(Export);

export default {
	name: "XMindViewer",
	props: {
		xmindData: {
			type: String,
			default: ""
		}
	},
	data() {
		return {
			mindMap: null
		};
	},
	watch: {
		xmindData: {
			handler(newVal) {
				if (newVal && this.mindMap) {
					this.renderMindMap(newVal);
				}
			},
			immediate: true
		}
	},
	mounted() {
		this.initMindMap();
	},
	beforeDestroy() {
		if (this.mindMap) {
			this.mindMap.destroy();
		}
	},
	methods: {
		initMindMap() {
			if (this.$refs.mindMapContainer) {
				this.mindMap = new MindMap({
					el: this.$refs.mindMapContainer,
					data: {}
				});
                
				// 如果已经有数据,则渲染
				if (this.xmindData) {
					this.renderMindMap(this.xmindData);
				}
			}
		},
        
		renderMindMap(data) {
			try {
				// 尝试解析为 JSON
				let jsonData;
				try {
					jsonData = JSON.parse(data);
				} catch {
					// 如果不是 JSON,假设是 Markdown 格式
					jsonData = markdown.transformMarkdownTo(data);
				}
                
				if (this.mindMap) {
					this.mindMap.setData(jsonData);
				}
			} catch (error) {
				console.error("XMind 数据解析失败:", error);
			}
		},
        
		exportMindMap() {
			if (this.mindMap) {
				this.mindMap.export("xmind", "思维导图");
			}
		}
	}
};
</script>

<style lang="scss" scoped>
#mindMapContainer {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 400px;
    border: 1px solid #eee;
    border-radius: 4px;
}
</style>

核心就是要先实例化,调用包中的插件,接收后续传入的xmindData数据(格式是Markdown形式),使用包中方法transformMarkdownTo将Markdown转换为可渲染Xmind的数据,再使用setData写入即可。 4. 最后就是在我们渲染流式输出的div中,引入这个组件并使用就即可。

 <x-mind-viewer v-if="msg.xmindData" :xmind-data="msg.xmindData" class="mt-16px" />

看下效果:

20250828145200_rec_.gif

总结

实现思路就是匹配替换,抛出Markdown内容,调用工具包中的方法将其渲染。SimpleMindMap包中有很多转换方法,文档也比较详细(需要科学上网)。

包的更新迭代较快,不同版本差别多,需要考虑包版本。