Merge branch 'feature' of https://github.com/wanglin2/mind-map into feature

This commit is contained in:
街角小林
2025-02-11 17:31:01 +08:00
9 changed files with 79 additions and 9 deletions

3
.gitignore vendored
View File

@@ -2,4 +2,5 @@ node_modules
.DS_Store
dist_electron
simple-mind-map/dist
simple-mind-map/types
simple-mind-map/types
utools/dist

View File

@@ -20,7 +20,8 @@ import {
isUndef,
handleGetSvgDataExtraContent,
getNodeTreeBoundingRect,
mergeTheme
mergeTheme,
createUidForAppointNodes
} from './src/utils'
import defaultTheme, {
checkIsNodeSizeIndependenceConfig
@@ -149,6 +150,8 @@ class MindMap {
if (data.data && !data.data.expand) {
data.data.expand = true
}
// 给没有uid的节点添加uid
createUidForAppointNodes([data], false, null, true)
return data
}
@@ -395,6 +398,7 @@ class MindMap {
// 更新画布数据,如果新的数据是在当前画布节点数据基础上增删改查后形成的,那么可以使用该方法来更新画布数据
updateData(data) {
data = this.handleData(data)
this.emit('before_update_data', data)
this.renderer.setData(data)
this.render()
@@ -583,7 +587,7 @@ class MindMap {
this.watermark.isInExport = false
}
// 添加必要的样式
[this.joinCss(), ...cssTextList].forEach(s => {
;[this.joinCss(), ...cssTextList].forEach(s => {
clone.add(SVG(`<style>${s}</style>`))
})
// 附加内容

View File

@@ -302,6 +302,25 @@ export const defaultOpt = {
},
// 自定义快捷创建子节点按钮的点击操作,
customQuickCreateChildBtnClick: null,
// 添加自定义的节点内容
// 可传递一个对象,格式如下:
/*
{
// 返回要添加的DOM元素详细
create: (node) => {
return {
el, // DOM节点
width: 20, // 宽高
height: 20
}
},
// 处理生成的@svgdotjs/svg.js库的ForeignObject节点实例可以设置其在节点内的位置
handle: ({ content, element, node }) => {
}
}
*/
addCustomContentToNode: null,
// 【Select插件】
// 多选节点时鼠标移动到边缘时的画布移动偏移量

View File

@@ -99,6 +99,7 @@ class MindMapNode {
this._generalizationList = []
this._unVisibleRectRegionNode = null
this._isMouseenter = false
this._customContentAddToNodeAdd = null
// 尺寸信息
this._rectInfo = {
textContentWidth: 0,
@@ -216,7 +217,8 @@ class MindMapNode {
isUseCustomNodeContent,
customCreateNodeContent,
createNodePrefixContent,
createNodePostfixContent
createNodePostfixContent,
addCustomContentToNode
} = this.mindMap.opt
// 需要创建的内容类型
const typeList = [
@@ -289,6 +291,15 @@ class MindMapNode {
addXmlns(this._postfixData.el)
}
}
if (
addCustomContentToNode &&
typeof addCustomContentToNode.create === 'function'
) {
this._customContentAddToNodeAdd = addCustomContentToNode.create(this)
if (this._customContentAddToNodeAdd && this._customContentAddToNodeAdd.el) {
addXmlns(this._customContentAddToNodeAdd.el)
}
}
}
// 计算节点的宽高

View File

@@ -177,7 +177,8 @@ function layout() {
const {
hoverRectPadding,
openRealtimeRenderOnNodeTextEdit,
textContentMargin
textContentMargin,
addCustomContentToNode
} = this.mindMap.opt
// 避免编辑过程中展开收起按钮闪烁的问题
if (openRealtimeRenderOnNodeTextEdit && this._expandBtn) {
@@ -428,6 +429,22 @@ function layout() {
}
textContentNested.translate(translateX, translateY)
addHoverNode()
if (this._customContentAddToNodeAdd && this._customContentAddToNodeAdd.el) {
const foreignObject = createForeignObjectNode(
this._customContentAddToNodeAdd
)
this.group.add(foreignObject)
if (
addCustomContentToNode &&
typeof addCustomContentToNode.handle === 'function'
) {
addCustomContentToNode.handle({
content: this._customContentAddToNodeAdd,
element: foreignObject,
node: this
})
}
}
this.mindMap.emit('node_layout_end', this)
}

View File

@@ -2,13 +2,14 @@ import btnsSvg from '../../../svg/btns'
import { SVG, Circle, G } from '@svgdotjs/svg.js'
function initQuickCreateChildBtn() {
if (this.isGeneralization) return
this._quickCreateChildBtn = null
this._showQuickCreateChildBtn = false
}
// 显示按钮
function showQuickCreateChildBtn() {
if (this.getChildrenLength() > 0) return
if (this.isGeneralization || this.getChildrenLength() > 0) return
// 创建按钮
if (this._quickCreateChildBtn) {
this.group.add(this._quickCreateChildBtn)
@@ -63,6 +64,7 @@ function showQuickCreateChildBtn() {
// 移除按钮
function removeQuickCreateChildBtn() {
if (this.isGeneralization) return
if (this._quickCreateChildBtn && this._showQuickCreateChildBtn) {
this._quickCreateChildBtn.remove()
this._showQuickCreateChildBtn = false
@@ -71,6 +73,7 @@ function removeQuickCreateChildBtn() {
// 隐藏按钮
function hideQuickCreateChildBtn() {
if (this.isGeneralization) return
const { isActive } = this.getData()
if (!isActive) {
this.removeQuickCreateChildBtn()

View File

@@ -182,6 +182,10 @@ class Search {
const uid = this.isNodeInstance(currentNode)
? currentNode.getData('uid')
: currentNode.data.uid
if (!uid) {
callback()
return
}
const targetNode = this.mindMap.renderer.findNodeByUid(uid)
this.mindMap.execCommand('GO_TARGET_NODE', uid, node => {
if (!this.isNodeInstance(currentNode)) {

View File

@@ -508,7 +508,7 @@ export const loadImage = imgFile => {
// 移除字符串中的html实体
export const removeHTMLEntities = str => {
[['&nbsp;', '&#160;']].forEach(item => {
;[['&nbsp;', '&#160;']].forEach(item => {
str = str.replace(new RegExp(item[0], 'g'), item[1])
})
return str
@@ -1002,7 +1002,8 @@ export const addDataToAppointNodes = (appointNodes, data = {}) => {
export const createUidForAppointNodes = (
appointNodes,
createNewId = false,
handle = null
handle = null,
handleGeneralization = false
) => {
const walk = list => {
list.forEach(node => {
@@ -1012,6 +1013,14 @@ export const createUidForAppointNodes = (
if (createNewId || isUndef(node.data.uid)) {
node.data.uid = createUid()
}
if (handleGeneralization) {
const generalizationList = formatGetNodeGeneralization(node.data)
generalizationList.forEach(gNode => {
if (createNewId || isUndef(gNode.uid)) {
gNode.uid = createUid()
}
})
}
handle && handle(node)
if (node.children && node.children.length > 0) {
walk(node.children)
@@ -1060,7 +1069,7 @@ export const generateColorByContent = str => {
// html转义
export const htmlEscape = str => {
[
;[
['&', '&amp;'],
['<', '&lt;'],
['>', '&gt;']

View File

@@ -125,6 +125,7 @@ export default {
)
this.mindMap.keyCommand.addShortcut('Control+f', this.showSearch)
window.addEventListener('resize', this.setSearchResultListHeight)
this.$bus.$on('setData', this.close)
},
mounted() {
this.setSearchResultListHeight()
@@ -141,6 +142,7 @@ export default {
)
this.mindMap.keyCommand.removeShortcut('Control+f', this.showSearch)
window.removeEventListener('resize', this.setSearchResultListHeight)
this.$bus.$off('setData', this.close)
},
methods: {
isUndef,