核心包
使用了SimpleMindMap 这个包
该包可以实现很多思维导图功能,除核心功能外其它能力都通过插件提供,按需选择。
实现步骤
说明:
这个需求是在公司内AI助手里实现,结合AI助手流式返回的Markdown语句,将其渲染为XMind思维导图内容。具体还结合了Dify平台的智能体配置提示词等相关内容,不是重点,直接说实现步骤。
- 首先匹配需要转换的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();
}
});
}
- 接着在我们处理流式返回的onmessage方法中处理接口内容content,只需要在每次更新流式返回答案后调用上面的useXmindMatch,更新每一次渲染。实现在接口返回一次完整的Markdown内容后可以立即渲染出对应xmind导图。
useXmindMatch(this.currentAnswer, (matchXmindContent) => {
this.handlerXmindMatch(matchXmindContent, this.currentAnswer);
});
handlerXmindMatch(matchContent, msg) {
// 将 XMind 数据存储到消息对象中,供后续使用
msg.xmindData = matchContent;
},
- 接着核心代码是新建一个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" />
看下效果:
总结
实现思路就是匹配替换,抛出Markdown内容,调用工具包中的方法将其渲染。SimpleMindMap包中有很多转换方法,文档也比较详细(需要科学上网)。
包的更新迭代较快,不同版本差别多,需要考虑包版本。