import { Graph, Cell, Node, Path } from '@antv/x6' import { getTextSize, getTextWidth } from "./measure.js" import Hierarchy from '@antv/hierarchy' export default { data() { return { mindMapDataCurrent:{}, positionCurrent:{}, addTypeCurrent:'', styleConfig:{}, mindmapAssistData:{ mindmapDataUse:[], deletedMindmapData:[],// 用于撤销删除,恢复删除掉的数据 mindmapDataRecoverUse:[],//用于 重做时 恢复思维导图数据 }, childNodeSizes:[],//数据节点内部内容宽度数组 linkLists:[], //link列表 childNodeCells:[],//存放所有child子数据节点 } }, mounted() { }, created() { this.styleConfig=this.$store.state.sand.styleConfig // 中心主题 Graph.registerNode( 'mindmap-topic', { inherit: 'rect', markup: [ { tagName: 'rect', selector: 'body', }, { tagName: 'image', selector: 'leftImg', }, { tagName: 'image', selector: 'rightImg', }, { tagName: 'text', selector: 'text', }, ], attrs: { body: { rx: 6, ry: 6, strokeWidth: 1, width:100, height:50 }, leftImg: { ref: 'body', refX: -16, refY: '50%', refY2: -8, width: 16, height: 16, 'xlink:href':require('@/assets/img/icons/add_blue_new.png'), event: 'add:topic:left', class: 'left-topic-image', }, rightImg: { ref: 'body', refX: '100%', refY: '50%', refY2: -8, width: 16, height: 16, 'xlink:href':require('@/assets/img/icons/add_blue_new.png'), event: 'add:topic:right', class: 'right-topic-image', }, text: { fontSize: 14, fill: this.$store.state.sand.styleConfig.color, textWrap:{ width:-10 } } }, }, true, ) // 左分支主题 Graph.registerNode( 'mindmap-topic-left', { inherit: 'rect', markup: [ { tagName: 'rect', selector: 'body', }, { tagName: 'image', selector: 'leftImg', }, { tagName: 'image', selector: 'rightImg', }, { tagName: 'text', selector: 'text', }, ], attrs: { body: { rx: 6, ry: 6, strokeWidth: 1, width:100, height:50 }, leftImg: { ref: 'body', refX: -16, refY: '50%', refY2: -8, width: 16, height: 16, 'xlink:href':require('@/assets/img/icons/add_blue_new.png'), event: 'add:topic:left', class: 'left-topic-image', }, text: { fontSize: 14, fill: this.$store.state.sand.styleConfig.color, textWrap:{ width:-10 } } }, }, true, ) // 右分支主题 Graph.registerNode( 'mindmap-topic-right', { inherit: 'rect', markup: [ { tagName: 'rect', selector: 'body', }, { tagName: 'image', selector: 'leftImg', }, { tagName: 'image', selector: 'rightImg', }, { tagName: 'text', selector: 'text', }, ], attrs: { body: { rx: 6, ry: 6, strokeWidth: 1, width:100, height:50 }, rightImg: { ref: 'body', refX: '100%', refY: '50%', refY2: -8, width: 16, height: 16, 'xlink:href':require('@/assets/img/icons/add_blue_new.png'), event: 'add:topic:right', class: 'right-topic-image', }, text: { fontSize: 14, fill:this.$store.state.sand.styleConfig.color, textWrap:{ width:-10 } } }, }, true, ) //数据节点标题 Graph.registerNode( 'mindmap-child-datanode-title', { inherit: 'rect', markup: [ { tagName: 'rect', selector: 'body', }, { tagName: 'text', selector: 'text', }, ], attrs: { body: { rx: 4, ry: 4, width:132, height:28, fill:'#0052D9', strokeWidth: 1, class: 'mindmap-child-datanode-title', }, text: { fontSize: 14, fill: '#fff', textWrap:{ width:-10 }, class: 'mindmap-child-datanode-title-text', } }, } ) //数据子框节点 Graph.registerNode( 'mindmap-child-background-datanode', { inherit: 'rect', markup: [ { tagName: 'rect', selector: 'body', }, { tagName: 'text', selector: 'text', }, ], attrs: { body: { strokeWidth: 1, width:110, height:66 }, }, }, true, ); //数据子节点 Graph.registerNode( 'mindmap-child-datanode', { inherit: 'rect', markup: [ { tagName: 'rect', selector: 'body', }, { tagName: 'text', selector: 'text', }, ], attrs: { body: { rx: 6, ry: 6, strokeWidth: 1, width:110, height:66 }, text: { fontSize: 14, fill:this.$store.state.sand.styleConfig.color, textWrap:{ width:-10 } } }, }, true, ); //数据子内部节点 Graph.registerNode( 'mindmap-grandchild-datanode', { inherit: 'rect', markup: [ { tagName: 'rect', selector: 'body', }, { tagName: "text", selector: "text", }, { tagName: "text", selector: "value", }, ], attrs: { body: { width:110, height:66, }, text: { fontSize: 14, }, value:{ fontSize: 14, }, }, }, true, ); // 连接器 Graph.registerConnector( 'mindmap', (sourcePoint, targetPoint, routerPoints, options) => { const midX = sourcePoint.x + 10 // const midY = sourcePoint.y const ctrX = (targetPoint.x - midX) / 5 + midX const ctrY = targetPoint.y const pathData = ` M ${sourcePoint.x} ${sourcePoint.y} Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y} ` return options.raw ? Path.parse(pathData) : pathData }, true, ) // 边 Graph.registerEdge( 'mindmap-edge', { inherit: 'edge', connector: { name: 'mindmap', }, attrs: { line: { targetMarker: false, strokeWidth: 2, }, }, zIndex: 0, }, true, ) }, methods: { setGraph(){ // 添加左边节点 this.graph.on('add:topic:left', ({ node }) => { if(this.operationType=='view') return const { id } = node this.setCurrent(id) const type = node.prop('type') if (this.addChildNode(id, type,'left')) { this.mindMapRender() } }) // 添加右边节点 this.graph.on('add:topic:right', ({ node }) => { if(this.operationType=='view') return const { id } = node this.setCurrent(id) const type = node.prop('type') if (this.addChildNode(id, type,'right')) { this.mindMapRender() } }) // 改变大小 - 更新数据源 this.graph.on('node:change:size', (args) => { if(this.operationType=='view') return if(args.node.shape.indexOf('mindmap')!==-1){ let ids = args.node.id.split('-') let mindmapDataIndex = this.mindmapAssistData.mindmapDataUse.findIndex(mindmap => mindmap.mindmapData.id == ids[0]) let mindMapDataCurrent = this.mindmapAssistData.mindmapDataUse[mindmapDataIndex]?this.mindmapAssistData.mindmapDataUse[mindmapDataIndex].mindmapData:{} let findId = ids[0] for (let i = 1; i < ids.length; i++) { const element = ids[i]; findId = findId+'-'+element mindMapDataCurrent=mindMapDataCurrent.children.find(it => it.id==findId) } mindMapDataCurrent.width = args.node.size().width mindMapDataCurrent.height = args.node.size().height } }) // 改变位置 - 更新数据源 this.graph.on('node:change:position', (args) => { if(this.operationType=='view') return if(args.node.shape.indexOf('mindmap')!==-1 && Number(args.node.id)){ let index = this.mindmapAssistData.mindmapDataUse.findIndex(it =>it.mindmapData.id == args.node.id) if(index!=-1){ this.mindmapAssistData.mindmapDataUse[index].position = args.current } } }) // tab 键添加节点-右边的 - 更新数据源 this.graph.bindKey('tab', (e) => { if(this.operationType=='view') return e.preventDefault() const selectedNodes = this.graph.getSelectedCells().filter((item) => { return item.shape.indexOf('mindmap')!=-1 && item.isNode() }) if (selectedNodes.length) { const node = selectedNodes[0] this.setCurrent(node.id) let type = node.prop('type') let direction = node.shape.indexOf('left')!=-1?'left':'right' if (this.addChildNode(node.id, type,direction)) { this.mindMapRender() } } }) // 撤销 - 入栈 this.graph.history.on('undo', (args) => { let mindmapNodes=args.cmds.filter(it => it.data.props && it.data.props.shape.indexOf('mindmap')!=-1 && it.data.node) if(!(mindmapNodes && mindmapNodes.length>0)) return let mindmapUndoType=mindmapNodes[0].event if(mindmapUndoType=="cell:added"){ this.mindmapDeleteRecordPush(mindmapNodes) }else if(mindmapUndoType=="cell:removed"){ this.mindmapAddRecordPush() } }) // 重做,出栈 this.graph.history.on('redo', (args) => { let mindmapNodes=args.cmds.filter(it => it.data.props && it.data.props.shape.indexOf('mindmap')!=-1 && it.data.node) if(!(mindmapNodes && mindmapNodes.length>0)) return this.mindmapRecover() }) }, // 生成思维导图初始化数据 generateMindmapData(position,addType){ let beId=this.mindmapAssistData.mindmapDataUse.length>0? parseInt(this.mindmapAssistData.mindmapDataUse[this.mindmapAssistData.mindmapDataUse.length-1].mindmapData.id)+1+'':'1' let mindmapData={ id: beId, type: 'topic', label: this.$t('SandboxManage.SandFlow.center_theme')||'中心主题', width: 160, height: 50, direction:'double', children: [ { id: beId+'-1', type: 'topic-branch', label: this.$t('SandboxManage.SandFlow.branch_topic')+'1', width: 100, height: 40, direction:'left', children: [ { id: beId+'-1-1', type: 'topic-child', label: this.$t('SandboxManage.SandFlow.sub_topic')+'1', width: 60, height: 30, direction:'left', }, { id: beId+'-1-2', type: 'topic-child', label: this.$t('SandboxManage.SandFlow.sub_topic')+'2', width: 60, height: 30, direction:'left', }, ], }, { id: beId+'-2', type: 'topic-branch', label: this.$t('SandboxManage.SandFlow.branch_topic')+'2', width: 100, height: 40, direction:'right', }, ], } this.mindmapAssistData.mindmapDataUse.push({mindmapData,position,addType}) }, // 通过id设置当前操作的思维导图 setCurrent(id){ let rootId = id.split('-')[0] let index = this.mindmapAssistData.mindmapDataUse.findIndex(it =>it.mindmapData.id == rootId) this.mindMapDataCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].mindmapData:{} this.positionCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].position:{x:0,y:0} this.addTypeCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].addType:'singleMindmap' }, mindMapRender(i){ this.graph.startBatch('renderMindmap') let mindMapType = i || i==0?this.mindmapAssistData.mindmapDataUse[i].addType:this.addTypeCurrent this.mindMapDataCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].mindmapData:this.mindMapDataCurrent this.positionCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].position:this.positionCurrent const result = Hierarchy.mindmap(this.mindMapDataCurrent, { direction: 'H', getHeight(d) { return d.height }, getWidth(d) { return d.width }, getHGap() { return 40 }, getVGap() { return 20 }, getSide: (d) => { return mindMapType.indexOf('double') != -1?d.data.direction || 'left':'right' } }) const cells = [] let xGap = this.positionCurrent?this.positionCurrent.x-result.x:0 let yGap = this.positionCurrent?this.positionCurrent.y-result.y:0 const traverse = (hierarchyItem) => { if (hierarchyItem) { const { data, children } = hierarchyItem let mindmapDirection = mindMapType.indexOf('double') != -1?data.direction:'right' let currentCell=this.graph.getCellById(data.id) if(!currentCell){ // 没有 新增 cells.push( this.graph.createNode({ id: data.id, shape:mindmapDirection=='right'?'mindmap-topic-right':mindmapDirection=='left'?'mindmap-topic-left':'mindmap-topic', x: xGap+hierarchyItem.x, y: yGap+hierarchyItem.y, width: data.width, height: data.height, label: data.label, type: data.type, attrs:{ body: { stroke: this.$store.state.sand.styleConfig.borderColor, fill: this.$store.state.sand.styleConfig.backgroundColor }, text:{ fill:this.$store.state.sand.styleConfig.color } }, }), ) }else{ // 有,更新下位置信息 currentCell.position(xGap+hierarchyItem.x,yGap+hierarchyItem.y); if(currentCell.shape == 'mindmap-child-background-datanode' && currentCell.getChildren().length > 0){ let titleNodeSize = this.getTitleNodeSize(currentCell.data.Name,currentCell.size().width); let childDataNode = currentCell.getChildren()[0]; childDataNode.position(xGap+hierarchyItem.x,yGap+hierarchyItem.y + titleNodeSize.height) let childrens = childDataNode.getChildren() || []; let cs = _.cloneDeep(childrens) cs.sort((a, b) => { if (a.shape === 'mindmap-child-datanode-title') return 1; if (b.shape === 'mindmap-child-datanode-title') return -1; return 0; }); cs.map((v,i)=>{ if(v.shape == 'mindmap-grandchild-datanode'){ let m = i % 3; let w = m == 0 ? 0 : (m == 1 ? cs[0].size().width : cs[0].size().width + cs[1].size().width); v.position(xGap+hierarchyItem.x + (m + 1) * 10 + w , yGap+hierarchyItem.y + Math.floor(i / 3) * 66 + titleNodeSize.height); } else { v.position(xGap+hierarchyItem.x , yGap+hierarchyItem.y); } }) } } if (children) { children.forEach((item) => { const { id, data } = item let mindmapChildDirection = mindMapType.indexOf('double') != -1?data.direction:'right' let currentEdge=this.graph.getCellById(data.id) if(!currentEdge){ cells.push( this.graph.createEdge({ shape: 'mindmap-edge', attrs:{ line:{ stroke:this.$store.state.sand.styleConfig.lineColor } }, source: { cell: hierarchyItem.id, anchor: { name: 'center', args: { dx: mindmapChildDirection=='right'?'25%':mindmapChildDirection=='left'?'-25%':0, }, }, }, target: { cell: id, anchor: { name: mindmapChildDirection =='left'?'right':'left', }, }, }), ) } traverse(item) }) } } } traverse(result) // 排下序,把边放最后面 不然 边 会找不到 节点 let sortCells = cells.sort(cell => cell.shape.indexOf('edge')) this.graph.addCell(sortCells) this.graph.stopBatch('renderMindmap') }, findItem(obj,id){ if (obj.id === id) { return { parent: null, node: obj, } } const { children } = obj if (children) { for (let i = 0, len = children.length; i < len; i++) { const res = this.findItem(children[i], id) if (res) { return { parent: res.parent || obj, node: res.node, } } } } return null }, addChildNode (id, type,direction='left'){ // 重做不了 清空重做栈 this.mindmapAssistData.mindmapDataRecoverUse = [] const res = this.findItem(this.mindMapDataCurrent, id) const dataItem = res && res.node if (dataItem) { let item = null let addId ='1' if(dataItem.children && dataItem.children.length>0){ let ids = dataItem.children[dataItem.children.length-1].id.split('-') addId = parseInt(ids[ids.length-1])+1+'' } if (type === 'topic') { item = { id: `${id}-${addId}`, type: 'topic-branch', label: `分支主题${addId}`, width: 100, height: 40, direction } } else if (type === 'topic-branch' || type=='topic-child') { item = { id: `${id}-${addId}`, type: 'topic-child', label: `子主题${addId}`, width: 60, height: 30, direction } } if (item) { if (dataItem.children) { dataItem.children.push(item) } else { dataItem.children = [item] } return item } } return null }, //添加数据节点 handleGetDataNodeWidth(list,widthIndex){ let arr = [[],[],[]]; //按列分组,获取当前列的内容的最大长度作为该列的最大长度 list.map((item,index)=>{ arr[index % 3].push(item) }); let widthArr = []; arr.map((arrs,arrsIndex)=>{ let widths = []; arrs.map(item=>{ widths.push(getTextWidth(item.label,'Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif',14) || 0); widths.push(getTextWidth(item.value,'Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif',14) || 0); }) let max = widths.length > 0 ? Math.max.apply(null,widths) : 0; if(max) widthArr[arrsIndex] = max > 106 ? max : 106; }); this.childNodeSizes[widthIndex] = widthArr || []; let sum = widthArr.reduce((accumulator, current) => { return accumulator + current; },0); sum += list.filter(_=>_).length >= 3 ? 40 : (20 + 10*(list.length - 1)); return sum; }, getDataNodeSize(data,index){ const list = data.calculationMethod; let height = Math.ceil(list.length / 3) * 66; let width = this.handleGetDataNodeWidth(list,index); return { height:height || 66, width:width || 50, } }, getTitleNodeSize(name,width){ let nameWidth = getTextWidth(name,'Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif',14) + 10; let titleWidth = nameWidth < width ? nameWidth : width; titleWidth = titleWidth < 126 ? 126 : titleWidth; let h = getTextSize(name,titleWidth,14,'Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif'); h.height = h.height < 30 ? 30 : h.height; return h }, addMindmapDataNodes(id,list,direction){ // 重做不了 清空重做栈 this.mindmapAssistData.mindmapDataRecoverUse = [] const res = this.findItem(this.mindMapDataCurrent, id); const dataItem = res && res.node; if(dataItem.children && dataItem.children.length > 0){ //将原数据清空 const types = ['mindmap-child-background','datanode-title','datanode-grandchild','datanode-child'] dataItem.children = dataItem.children.filter(_=>!types.includes(_.type)) } this.linkLists = []; this.childNodeSizes = []; this.childNodeCells = []; if (dataItem) { list.map((_,index)=>{ let item = null let addId ='1' if(dataItem.children && dataItem.children.length>0){ let ids = dataItem.children[dataItem.children.length-1].id.split('-') addId = parseInt(ids[ids.length-1])+1+'' }; let h = {height:30,width:200}; let titleH = {height:0,width:0} if(!_.calculationMethod || !_.calculationMethod.length){ h = getTextSize(_.Name,200,14,'Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif'); h.height = h.height < 30 ? 30 : h.height; } else { h = this.getDataNodeSize(_,index); titleH = this.getTitleNodeSize(_.Name,h.width); } item = { id: `${id}-${addId}`, type: !_.calculationMethod || !_.calculationMethod.length ? 'datanode-title' : 'mindmap-child-background', label: !_.calculationMethod || !_.calculationMethod.length ? _.Name : '', width: h.width, height: h.height + titleH.height, direction:direction, data:_, } this.linkLists.push(item); if (item) { if (dataItem.children) { dataItem.children.push(item) } else { dataItem.children = [item] } this.mindMapDataRender(); if(this.childNodeCells.length == list.length){ //添加完成 const select_cell = this.graph.getSelectedCells()[0]; select_cell.setChildren(this.childNodeCells) } } }) } }, mindMapDataRender(i){ //添加数据节点的渲染 this.graph.startBatch('renderMindmap') let mindMapType = i || i==0?this.mindmapAssistData.mindmapDataUse[i].addType:this.addTypeCurrent this.mindMapDataCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].mindmapData:this.mindMapDataCurrent this.positionCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].position:this.positionCurrent const result = Hierarchy.mindmap(this.mindMapDataCurrent, { direction: 'H', getHeight(d) { return d.height }, getWidth(d) { return d.width }, getHGap() { return 40 }, getVGap() { return 20 }, getSide: (d) => { return mindMapType.indexOf('double') != -1?d.data.direction || 'left':'right' } }) const cells = []; let xGap = this.positionCurrent?this.positionCurrent.x-result.x:0 let yGap = this.positionCurrent?this.positionCurrent.y-result.y:0 const traverse = (hierarchyItem) => { if (hierarchyItem) { const { data, children } = hierarchyItem let mindmapDirection = mindMapType.indexOf('double') != -1?data.direction:'right' let currentCell=this.graph.getCellById(data.id) const shapesObject = { 'datanode-title':'mindmap-child-datanode-title', 'datanode-child':'mindmap-child-datanode', 'datanode-grandchild':'mindmap-grandchild-datanode', 'mindmap-child-background':'mindmap-child-background-datanode' } if(!currentCell){ // 没有 新增 const wrapNode = this.graph.createNode({ id: data.id, shape:shapesObject[data.type], x: xGap+hierarchyItem.x, y: yGap+hierarchyItem.y, width: data.width, height: data.height, label: data.label, type: data.type, attrs:{ body: { stroke: data.type == 'datanode-title' ? '#0052D9' : 'transparent', fill: data.type == 'datanode-title' ? '#0052D9' : 'transparent', }, text:{ fill:data.type == 'datanode-title' ? '#FFFFFF' : 'transparent', } }, data:data.data, }) cells.push(wrapNode); if(data.type == 'mindmap-child-background' || data.type == 'datanode-title') this.childNodeCells.push(wrapNode); let titleNodeSize = this.getTitleNodeSize(data.data.Name,data.width); let currentNode = null; if(data.type == 'mindmap-child-background'){ currentNode = this.graph.createNode({ id: `${data.id}+0` , shape:'mindmap-child-datanode', x: xGap+hierarchyItem.x, y: yGap+hierarchyItem.y + titleNodeSize.height, width: data.width, height: data.height - titleNodeSize.height, label: '', type:'datanode-child', attrs:{ body: { stroke: this.$store.state.sand.styleConfig.borderColor, fill: this.$store.state.sand.styleConfig.backgroundColor, 'pointer-events': 'none', }, text:{ fill:this.$store.state.sand.styleConfig.color, 'pointer-events': 'none', } }, data:data.data, }) cells.push(currentNode); wrapNode.setChildren([currentNode]) } let titleNode = null; if(data.data && data.data.detailParams && data.data.detailParams.id && data.data && data.data.calculationMethod && data.data.calculationMethod.length > 0){ titleNode = this.graph.createNode({ id: `${data.id}-0`, shape:'mindmap-child-datanode-title', x: xGap+hierarchyItem.x, y: yGap+hierarchyItem.y, width: titleNodeSize.width, height: titleNodeSize.height, label: data.data.Name, type: 'datanode-title', attrs:{ body: { stroke: '#0052D9', fill: '#0052D9' }, text:{ fill:'#FFFFFF' } }, data:data.data, }); cells.push(titleNode); } // 处理内部数据节点 if(data.data && data.data.calculationMethod && data.data.calculationMethod.length > 0){ let cNodes = data.data.calculationMethod.map((v,i)=>{ let linkIndex = this.linkLists.findIndex(x=>x.id == data.id); let widthArr = this.childNodeSizes[linkIndex] ? this.childNodeSizes[linkIndex] : []; let m = i % 3; let w = m == 0 ? 0 : (m == 1 ? widthArr[0] : widthArr[0] + widthArr[1]) let innerNode = this.graph.createNode({ id: `${data.id}-${i + 1}`, shape:'mindmap-grandchild-datanode', x: xGap+hierarchyItem.x + (m + 1) * 10 + w, y: yGap+hierarchyItem.y + titleNodeSize.height + Math.floor(i / 3) * 66, width: widthArr[m], height: 66, type: 'datanode-grandchild', attrs:{ body:{ stroke: '', strokeWidth: 0, fill: 'transparent', 'pointer-events': 'none', }, text:{ fill:this.$store.state.sand.styleConfig.color, text:v.label, refWidth:1, refY: 10, textVerticalAnchor:'top', 'pointer-events': 'none', }, value:{ fill:this.$store.state.sand.styleConfig.color, text:v.value, refWidth:1, refX:"50%", refY: '100%', refY2:-10, textVerticalAnchor:'bottom', 'text-anchor':'middle', 'pointer-events': 'none', }, }, data:v, }); cells.push(innerNode); return innerNode }) currentNode.setChildren(titleNode ? [...cNodes,titleNode] : cNodes) } }else{ // 有,更新下位置信息 currentCell.position(xGap+hierarchyItem.x,yGap+hierarchyItem.y); if(currentCell.shape == 'mindmap-child-background-datanode' && currentCell.getChildren().length > 0){ let titleNodeSize = this.getTitleNodeSize(currentCell.data.Name,currentCell.size().width); let childDataNode = currentCell.getChildren()[0]; childDataNode.position(xGap+hierarchyItem.x,yGap+hierarchyItem.y + titleNodeSize.height) let childrens = childDataNode.getChildren() || []; let cs = _.cloneDeep(childrens) cs.sort((a, b) => { if (a.shape === 'mindmap-child-datanode-title') return 1; if (b.shape === 'mindmap-child-datanode-title') return -1; return 0; }); cs.map((v,i)=>{ if(v.shape == 'mindmap-grandchild-datanode'){ let m = i % 3; let w = m == 0 ? 0 : (m == 1 ? cs[0].size().width : cs[0].size().width + cs[1].size().width); v.position(xGap+hierarchyItem.x + (m + 1) * 10 + w , yGap+hierarchyItem.y + Math.floor(i / 3) * 66 + titleNodeSize.height); } else { v.position(xGap+hierarchyItem.x , yGap+hierarchyItem.y); } }) } } if (children) { children.forEach((item) => { const { id, data } = item let mindmapChildDirection = mindMapType.indexOf('double') != -1?data.direction:'right' let currentEdge=this.graph.getCellById(data.id) if(!currentEdge){ cells.push( this.graph.createEdge({ shape: 'mindmap-edge', attrs:{ line:{ stroke:this.$store.state.sand.styleConfig.lineColor } }, source: { cell: hierarchyItem.id, anchor: { name: 'center', args: { dx: mindmapChildDirection=='right'?'25%':mindmapChildDirection=='left'?'-25%':0, }, }, }, target: { cell: id, anchor: { name: mindmapChildDirection =='left'?'right':'left', }, }, }), ) } traverse(item) }) } } } traverse(result) // 排下序,把边放最后面 不然 边 会找不到 节点 let sortCells = cells.sort(cell => cell.shape.indexOf('edge')) let cells_result = sortCells.sort(cell => cell.shape.indexOf('mindmap-grandchild-datanode')); this.graph.addCell(cells_result) this.graph.stopBatch('renderMindmap') }, getMindmapDataUse(){ return this.mindmapAssistData }, mindmapDeleteRecordPush(mindmapNodes){ let shouldOperations=[] this.mindmapAssistData.mindmapDataUse.map((item,index)=>{ let levelIds = mindmapNodes.filter(mindMap => mindMap.data.id.startsWith(item.mindmapData.id)).map(mindMap => mindMap.data.id) if(!(levelIds && levelIds.length>0)) return let mindMapIds=[...levelIds] for (let i = 0; i < levelIds.length; i++) { const element = levelIds[i] mindMapIds=mindMapIds.filter( id => id.indexOf(element) !=0 || id==element) } shouldOperations.push(mindMapIds) }) // 入栈 if(!this.canRedo){ this.mindmapAssistData.mindmapDataRecoverUse=[JSON.stringify(this.mindmapAssistData.mindmapDataUse)] }else{ this.mindmapAssistData.mindmapDataRecoverUse.push(JSON.stringify(this.mindmapAssistData.mindmapDataUse)) } shouldOperations.map(it =>{ it.map(it1 =>{ this.deleteMindmapData(it1,this.mindmapAssistData.mindmapDataUse) }) }) }, mindmapAddRecordPush(){ // 入栈 if(!this.canRedo){ this.mindmapAssistData.mindmapDataRecoverUse=[JSON.stringify(this.mindmapAssistData.mindmapDataUse)] }else{ this.mindmapAssistData.mindmapDataRecoverUse.push(JSON.stringify(this.mindmapAssistData.mindmapDataUse)) } let recoverDeletedData=this.mindmapAssistData.deletedMindmapData.pop() if(recoverDeletedData && recoverDeletedData.length>0){ // 添加 recoverDeletedData.map(it =>{ it.map(it1 =>{ this.addMindmapData(it1,this.mindmapAssistData.mindmapDataUse) }) }) } }, deleteMindmapData(id,data){ let ids = id.split('-') let mindmapDataIndex = data.findIndex(mindmap => mindmap.mindmapData.id == ids[0]) if(ids.length==1){ data.splice(mindmapDataIndex,1) return } let mindmapData = data[mindmapDataIndex].mindmapData let findId = ids[0] for (let i = 1; i < ids.length-1; i++) { const element = ids[i]; findId = findId+'-'+element mindmapData=mindmapData.children.find(it => it.id==findId) } let endId = ids[ids.length-1] let endIndex = mindmapData.children.findIndex(it => it.id == findId+'-'+endId) mindmapData.children.splice(endIndex,1) }, addMindmapData(item,data){ let isRoot = item.mindmapData?true:false let id = isRoot?item.mindmapData.id:item.id if(isRoot){ // 恢复根节点 let mindmapDataIndexRoot=data.length for (let i = 0; i < data.length-1; i++) { const element = data[i]; if((+id) < (+element.mindmapData.id)){ mindmapDataIndexRoot=0 break }else if((+id) > (+element.mindmapData.id) && (+id) < (+data[i+1].mindmapData.id)){ mindmapDataIndexRoot=i+1 break } } data.splice(mindmapDataIndexRoot,0,item) return } let ids = id.split('-') let mindmapDataIndex = data.findIndex(mindmap => { return mindmap.mindmapData.id == ids[0] }) let mindmapData = data[mindmapDataIndex].mindmapData let findId = ids[0] for (let i = 1; i < ids.length-1; i++) { const element = ids[i]; findId = findId+'-'+element mindmapData=mindmapData.children.find(it => it.id==findId) } let endId = ids[ids.length-1] let endIndex = mindmapData.children.length if(mindmapData.children.length==1){ // 只有一个 let prevIdx = mindmapData.children[0].id.substring(mindmapData.children[0].id.lastIndexOf('-')+1) if((+endId) < (+prevIdx)){ endIndex=0 }else{ endIndex=1 } }else{ for (let i = 0; i < mindmapData.children.length-1; i++) { // 两个及以上 const element = mindmapData.children[i]; let prevIdx = element.id.substring(element.id.lastIndexOf('-')+1) let nextIdx = mindmapData.children[i+1].id.substring(mindmapData.children[i+1].id.lastIndexOf('-')+1) // 找到对应位置,前提 id是按顺序的 if((+endId) < (+prevIdx)){ endIndex=0 break }else if((+endId) > (+prevIdx) && (+endId) < (+nextIdx)){ endIndex=i+1 break } } } mindmapData.children.splice(endIndex,0,item) }, mindmapRecover(){ // 重做添加时 恢复数据指针前进 let recoverData = this.mindmapAssistData.mindmapDataRecoverUse.pop() if(recoverData) this.mindmapAssistData.mindmapDataUse=JSON.parse(recoverData) }, }, }