Demo:支持节点链接开发中

This commit is contained in:
街角小林
2025-04-07 17:45:09 +08:00
parent 0f9ae45784
commit 697cee0b46
7 changed files with 198 additions and 71 deletions

View File

@@ -134,6 +134,9 @@
<div class="item" @click="exec('REMOVE_NOTE')" v-if="hasNote">
<span class="name">{{ $t('contextmenu.removeNote') }}</span>
</div>
<div class="item" @click="exec('LINK_NODE')">
<span class="name">链接到指定节点</span>
</div>
<div class="item" @click="exec('REMOVE_CUSTOM_STYLES')">
<span class="name">{{ $t('contextmenu.removeCustomStyles') }}</span>
</div>
@@ -478,6 +481,10 @@ export default {
case 'REMOVE_NOTE':
this.node.setNote('')
break
case 'LINK_NODE':
this.$bus.$emit('show_link_node', this.node)
this.hide()
break
case 'EXPORT_CUR_NODE_TO_PNG':
this.mindMap.export(
'png',

View File

@@ -54,6 +54,10 @@
<NodeNoteSidebar v-if="mindMap" :mindMap="mindMap"></NodeNoteSidebar>
<AiCreate v-if="mindMap && enableAi" :mindMap="mindMap"></AiCreate>
<AiChat v-if="enableAi"></AiChat>
<LinkNodeSelect
v-if="mindMap && supportNodeLink"
:mindMap="mindMap"
></LinkNodeSelect>
<div
class="dragMask"
v-if="showDragMask"
@@ -92,7 +96,7 @@ import NodeBase64ImageStorage from 'simple-mind-map/src/plugins/NodeBase64ImageS
import Themes from 'simple-mind-map-plugin-themes'
// 协同编辑插件
// import Cooperate from 'simple-mind-map/src/plugins/Cooperate.js'
// 以下插件为付费插件详情请查看开发文档。依次为手绘风格插件、标记插件、编号插件、Freemind软件格式导入导出插件、Excel软件格式导入导出插件、待办插件、节点连线流动效果插件、动量效果插件
// 以下插件为付费插件详情请查看开发文档。依次为手绘风格插件、标记插件、编号插件、Freemind软件格式导入导出插件、Excel软件格式导入导出插件、待办插件、节点连线流动效果插件、动量效果插件、向右鱼骨图插件、节点链接插件、扩展节点形状插件、扩展主题列表插件
import HandDrawnLikeStyle from 'simple-mind-map-plugin-handdrawnlikestyle'
import Notation from 'simple-mind-map-plugin-notation'
import Numbers from 'simple-mind-map-plugin-numbers'
@@ -102,9 +106,12 @@ import Checkbox from 'simple-mind-map-plugin-checkbox'
import LineFlow from 'simple-mind-map-plugin-lineflow'
import Momentum from 'simple-mind-map-plugin-momentum'
import RightFishbone from 'simple-mind-map-plugin-right-fishbone'
import NodeLink from 'simple-mind-map-plugin-node-link'
import MoreShapes from 'simple-mind-map-plugin-more-shapes'
import MoreThemes from 'simple-mind-map-plugin-more-themes'
// npm link simple-mind-map-plugin-excel simple-mind-map-plugin-freemind simple-mind-map-plugin-numbers simple-mind-map-plugin-notation simple-mind-map-plugin-handdrawnlikestyle simple-mind-map-plugin-checkbox simple-mind-map simple-mind-map-plugin-themes simple-mind-map-plugin-lineflow simple-mind-map-plugin-momentum simple-mind-map-plugin-right-fishbone simple-mind-map-plugin-more-themes simple-mind-map-plugin-more-shapes
// npm link simple-mind-map simple-mind-map-plugin-excel simple-mind-map-plugin-freemind simple-mind-map-plugin-numbers simple-mind-map-plugin-notation simple-mind-map-plugin-handdrawnlikestyle simple-mind-map-plugin-checkbox simple-mind-map-plugin-lineflow simple-mind-map-plugin-momentum simple-mind-map-plugin-right-fishbone simple-mind-map-plugin-node-link
// simple-mind-map-plugin-themes
// simple-mind-map-plugin-more-themes simple-mind-map-plugin-more-shapes
import OutlineSidebar from './OutlineSidebar.vue'
import Style from './Style.vue'
import BaseStyle from './BaseStyle.vue'
@@ -147,6 +154,7 @@ import NodeImgPlacementToolbar from './NodeImgPlacementToolbar.vue'
import NodeNoteSidebar from './NodeNoteSidebar.vue'
import AiCreate from './AiCreate.vue'
import AiChat from './AiChat.vue'
import LinkNodeSelect from './LinkNodeSelect.vue'
// 注册插件
MindMap.usePlugin(MiniMap)
@@ -168,7 +176,6 @@ MindMap.usePlugin(MiniMap)
.usePlugin(OuterFrame)
.usePlugin(MindMapLayoutPro)
.usePlugin(NodeBase64ImageStorage)
.usePlugin(RightFishbone)
// .usePlugin(Cooperate) // 协同插件
// 注册主题
@@ -209,7 +216,8 @@ export default {
NodeImgPlacementToolbar,
NodeNoteSidebar,
AiCreate,
AiChat
AiChat,
LinkNodeSelect
},
data() {
return {
@@ -235,7 +243,8 @@ export default {
isUseMomentum: state => state.localConfig.isUseMomentum,
extraTextOnExport: state => state.extraTextOnExport,
isDragOutlineTreeNode: state => state.isDragOutlineTreeNode,
enableAi: state => state.localConfig.enableAi
enableAi: state => state.localConfig.enableAi,
supportNodeLink: state => state.supportNodeLink
})
},
watch: {
@@ -703,6 +712,14 @@ export default {
this.mindMap.addPlugin(LineFlow)
this.$store.commit('setSupportLineFlow', true)
}
if (typeof RightFishbone !== 'undefined') {
this.mindMap.addPlugin(RightFishbone)
this.$store.commit('setSupportRightFishbone', true)
}
if (typeof NodeLink !== 'undefined') {
this.mindMap.addPlugin(NodeLink)
this.$store.commit('setSupportNodeLink', true)
}
if (typeof MoreShapes !== 'undefined') {
this.mindMap.addPlugin(MoreShapes)
this.$store.commit('setSupportMoreShapes', true)

View File

@@ -0,0 +1,152 @@
<template>
<el-dialog
class="nodeLinkSelectDialog"
title="链接到指定节点"
:visible.sync="dialogVisible"
:show-close="false"
append-to-body
width="400px"
>
<div class="nodeTreeWrap">
<el-tree
ref="tree"
class="outlineTree"
node-key="uid"
default-expand-all
:class="{ isDark: isDark }"
:data="treeData"
:props="defaultProps"
:highlight-current="true"
:expand-on-click-node="false"
@current-change="onCurrentChange"
>
</el-tree>
</div>
<div slot="footer" class="footer">
<el-checkbox v-model="isAddReturn" style="margin-right: auto;">是否添加反向链接</el-checkbox>
<el-button @click="cancel">{{
$t('dialog.cancel')
}}</el-button>
<el-button type="primary" @click="confirm">{{
$t('dialog.confirm')
}}</el-button>
</div>
</el-dialog>
</template>
<script>
import {
nodeRichTextToTextWithWrap,
htmlEscape
} from 'simple-mind-map/src/utils'
import { mapState } from 'vuex'
export default {
props: {
mindMap: {
type: Object
}
},
data() {
return {
dialogVisible: false,
treeData: [],
defaultProps: {
label: 'label'
},
currentNodeData: null,
node: null,
isAddReturn: false
}
},
computed: {
...mapState({
isDark: state => state.localConfig.isDark
})
},
created() {
this.$bus.$on('show_link_node', this.onShowDialog)
},
beforeDestroy() {
this.$bus.$off('show_link_node', this.onShowDialog)
},
methods: {
onShowDialog(node) {
this.node = node
let data = this.mindMap.getData()
let walk = root => {
let text = root.data.richText
? nodeRichTextToTextWithWrap(root.data.text)
: root.data.text
text = htmlEscape(text)
text = text.replace(/\n/g, '<br>')
root.label = text
root.uid = root.data.uid
if (root.children && root.children.length > 0) {
root.children.forEach(item => {
walk(item)
})
}
}
walk(data)
this.treeData = [data]
this.dialogVisible = true
},
close() {
this.dialogVisible = false
this.node = null
this.treeData = []
this.currentNodeData = null
this.isAddReturn = false
},
// 当前选中的树节点变化事件
onCurrentChange(data) {
this.currentNodeData = data
},
cancel() {
this.close()
},
confirm() {
if (!this.currentNodeData) {
this.$message.warning('请选择要链接到的节点')
return
}
if (this.currentNodeData.uid === this.node.getData('uid')) {
this.$message.warning('不能链接自己')
return
}
this.$bus.$emit(
'execCommand',
'SET_NODE_LINK',
this.node,
this.currentNodeData.uid,
this.isAddReturn
)
this.$message.success('链接成功')
this.close()
}
}
}
</script>
<style lang="less" scoped>
.nodeLinkSelectDialog {
/deep/ .el-dialog__body {
padding: 0 20px;
}
.footer {
display: flex;
align-items: center;
justify-content: space-between;
}
}
.nodeTreeWrap {
height: 400px;
overflow: auto;
}
</style>

View File

@@ -350,7 +350,8 @@ export default {
padding-right: 20px;
}
}
</style>
<style lang="less">
.outlineTree {
&.isDark {
background-color: #262a2e;

View File

@@ -362,67 +362,4 @@ export default {
padding-right: 20px;
}
}
.outlineTree {
&.isDark {
background-color: #262a2e;
.customNode {
color: #fff;
}
&.el-tree--highlight-current {
/deep/ .el-tree-node.is-current > .el-tree-node__content {
background-color: hsla(0, 0%, 100%, 0.05) !important;
}
}
/deep/ .el-tree-node__content:hover,
.el-upload-list__item:hover {
background-color: hsla(0, 0%, 100%, 0.02) !important;
}
/deep/ .el-tree-node__content {
.el-tree-node__expand-icon {
color: #fff;
&.is-leaf {
&::after {
background-color: #fff;
}
}
}
}
}
/deep/ .el-tree-node > .el-tree-node__children {
overflow: inherit;
}
/deep/ .el-tree-node__content {
height: auto;
margin: 5px 0;
.el-tree-node__expand-icon {
color: #262a2e;
&.is-leaf {
color: transparent;
position: relative;
&::after {
background-color: #262a2e;
position: absolute;
content: '';
width: 5px;
height: 5px;
border-radius: 50%;
left: 10px;
top: 50%;
transform: translateY(-50%);
}
}
}
}
}
</style>

View File

@@ -38,7 +38,9 @@ const store = new Vuex.Store({
supportCheckbox: false, // 是否支持Checkbox插件
supportLineFlow: false, // 是否支持LineFlow插件
supportMomentum: false, // 是否支持Momentum插件
supportMoreShapes: false,// 是否支持MoreShapes插件
supportRightFishbone: false, // 是否支持RightFishbone插件
supportNodeLink: false, // 是否支持NodeLink插件
supportMoreShapes: false, // 是否支持MoreShapes插件
isDragOutlineTreeNode: false, // 当前是否正在拖拽大纲树的节点
aiConfig: {
api: 'http://ark.cn-beijing.volces.com/api/v3/chat/completions',
@@ -139,6 +141,16 @@ const store = new Vuex.Store({
state.supportMomentum = data
},
// 设置是否支持RightFishbone插件
setSupportRightFishbone(state, data) {
state.supportRightFishbone = data
},
// 设置是否支持NodeLink插件
setSupportNodeLink(state, data) {
state.supportNodeLink = data
},
// 设置是否支持MoreShapes插件
setSupportMoreShapes(state, data) {
state.supportMoreShapes = data