Feat:1.新增beforeAddHistory事件;2.新增处理base64格式存储的插件

This commit is contained in:
街角小林
2025-03-18 09:35:32 +08:00
parent 0321946b41
commit e53e41dadc
7 changed files with 110 additions and 3 deletions

View File

@@ -19,6 +19,7 @@ import RainbowLines from './src/plugins/RainbowLines.js'
import Demonstrate from './src/plugins/Demonstrate.js' import Demonstrate from './src/plugins/Demonstrate.js'
import OuterFrame from './src/plugins/OuterFrame.js' import OuterFrame from './src/plugins/OuterFrame.js'
import MindMapLayoutPro from './src/plugins/MindMapLayoutPro.js' import MindMapLayoutPro from './src/plugins/MindMapLayoutPro.js'
import NodeBase64ImageStorage from './src/plugins/NodeBase64ImageStorage.js'
import xmind from './src/parse/xmind.js' import xmind from './src/parse/xmind.js'
import markdown from './src/parse/markdown.js' import markdown from './src/parse/markdown.js'
import icons from './src/svg/icons.js' import icons from './src/svg/icons.js'
@@ -52,5 +53,6 @@ MindMap.usePlugin(MiniMap)
.usePlugin(Demonstrate) .usePlugin(Demonstrate)
.usePlugin(OuterFrame) .usePlugin(OuterFrame)
.usePlugin(MindMapLayoutPro) .usePlugin(MindMapLayoutPro)
.usePlugin(NodeBase64ImageStorage)
export default MindMap export default MindMap

View File

@@ -179,7 +179,8 @@ export const nodeDataNoStylePropList = [
'customTextWidth', 'customTextWidth',
'checkbox', 'checkbox',
'dir', 'dir',
'needUpdate'// 重新创建节点内容 'needUpdate',// 重新创建节点内容
'imgMap'
] ]
// 错误类型 // 错误类型

View File

@@ -106,6 +106,7 @@ class Command {
if (this.mindMap.opt.readonly || this.isPause) { if (this.mindMap.opt.readonly || this.isPause) {
return return
} }
this.mindMap.emit('beforeAddHistory')
const lastData = const lastData =
this.history.length > 0 ? this.history[this.activeHistoryIndex] : null this.history.length > 0 ? this.history[this.activeHistoryIndex] : null
const data = this.getCopyData() const data = this.getCopyData()

View File

@@ -34,10 +34,11 @@ const defaultTagStyle = {
// 创建图片节点 // 创建图片节点
function createImgNode() { function createImgNode() {
const img = this.getData('image') let img = this.getData('image')
if (!img) { if (!img) {
return return
} }
img = (this.mindMap.renderer.renderTree.data.imgMap || {})[img] || img
const imgSize = this.getImgShowSize() const imgSize = this.getImgShowSize()
const node = new SVGImage().load(img).size(...imgSize) const node = new SVGImage().load(img).size(...imgSize)
// 如果指定了加载失败显示的图片,那么加载一下图片检测是否失败 // 如果指定了加载失败显示的图片,那么加载一下图片检测是否失败

View File

@@ -0,0 +1,100 @@
import { walk, createUid } from '../utils/index'
// 修改base64格式的节点图片在数据中的存储方式
// 将base64格式的图片以key-map的形式存储在根节点的imgMap字段里其他节点只保存key避免不同的节点引用相同的图片重复存储的问题普通url格式的图片不处理
class NodeBase64ImageStorage {
constructor(opt) {
this.opt = opt
this.mindMap = opt.mindMap
this.bindEvent()
}
bindEvent() {
this.onBeforeAddHistory = this.onBeforeAddHistory.bind(this)
this.mindMap.on('beforeAddHistory', this.onBeforeAddHistory)
}
unBindEvent() {
this.mindMap.off('beforeAddHistory', this.onBeforeAddHistory)
}
isBase64ImgUrl(url) {
return /^data:/.test(url)
}
isImageKey(url) {
return /^smm_img_key_/.test(url)
}
createImageKey() {
return 'smm_img_key_' + createUid()
}
onBeforeAddHistory() {
const renderTree = this.mindMap.renderer.renderTree
if (!renderTree) return
let imgMap = renderTree.data.imgMap
if (!imgMap) {
imgMap = renderTree.data.imgMap = {}
}
const useIds = []
const getImgIds = () => {
return Object.keys(imgMap)
}
const getImgId = image => {
return getImgIds().find(id => {
return imgMap[id] === image
})
}
walk(renderTree, null, node => {
const image = node.data.image
if (image) {
// 如果是base64图片url
if (this.isBase64ImgUrl(image)) {
// 检查该图片是否已存在
const hasId = getImgId(image)
if (hasId) {
// 已存在则直接使用现有的key
useIds.push(hasId)
node.data.image = hasId
} else {
// 不存在则生成key并存储
const newId = this.createImageKey()
node.data.image = newId
imgMap[newId] = image
useIds.push(newId)
}
} else if (this.isImageKey(image)) {
// 如果是key那么收集一下
if (getImgIds().includes(image)) {
useIds.push(image)
}
}
}
})
// 删除已无节点引用的图片
getImgIds().forEach(id => {
if (!useIds.includes(id)) {
delete imgMap[id]
}
})
}
// 插件被移除前做的事情
beforePluginRemove() {
this.unBindEvent()
}
// 插件被卸载前做的事情
beforePluginDestroy() {
this.unBindEvent()
}
}
NodeBase64ImageStorage.instanceName = 'nodeBase64ImageStorage'
export default NodeBase64ImageStorage

View File

@@ -87,6 +87,7 @@ import RainbowLines from 'simple-mind-map/src/plugins/RainbowLines.js'
import Demonstrate from 'simple-mind-map/src/plugins/Demonstrate.js' import Demonstrate from 'simple-mind-map/src/plugins/Demonstrate.js'
import OuterFrame from 'simple-mind-map/src/plugins/OuterFrame.js' import OuterFrame from 'simple-mind-map/src/plugins/OuterFrame.js'
import MindMapLayoutPro from 'simple-mind-map/src/plugins/MindMapLayoutPro.js' import MindMapLayoutPro from 'simple-mind-map/src/plugins/MindMapLayoutPro.js'
import NodeBase64ImageStorage from 'simple-mind-map/src/plugins/NodeBase64ImageStorage.js'
import Themes from 'simple-mind-map-plugin-themes' import Themes from 'simple-mind-map-plugin-themes'
// 协同编辑插件 // 协同编辑插件
// import Cooperate from 'simple-mind-map/src/plugins/Cooperate.js' // import Cooperate from 'simple-mind-map/src/plugins/Cooperate.js'
@@ -161,6 +162,7 @@ MindMap.usePlugin(MiniMap)
.usePlugin(Demonstrate) .usePlugin(Demonstrate)
.usePlugin(OuterFrame) .usePlugin(OuterFrame)
.usePlugin(MindMapLayoutPro) .usePlugin(MindMapLayoutPro)
.usePlugin(NodeBase64ImageStorage)
// .usePlugin(Cooperate) // 协同插件 // .usePlugin(Cooperate) // 协同插件
// 注册主题 // 注册主题

View File

@@ -3,7 +3,7 @@
class="nodeImageDialog" class="nodeImageDialog"
:title="$t('nodeImage.title')" :title="$t('nodeImage.title')"
:visible.sync="dialogVisible" :visible.sync="dialogVisible"
:width="isMobile ? '90%' : '50%'" :width="isMobile ? '90%' : '600px'"
:top="isMobile ? '20px' : '15vh'" :top="isMobile ? '20px' : '15vh'"
> >
<div class="title">方式一</div> <div class="title">方式一</div>