From 5025901e459ae49d85210573ad38fb3f3c1d9230 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期日, 25 六月 2023 18:48:54 +0800
Subject: [PATCH] 2023-06-25

---
 src/menu/components/chart/antv-X6/index.jsx |  420 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 387 insertions(+), 33 deletions(-)

diff --git a/src/menu/components/chart/antv-X6/index.jsx b/src/menu/components/chart/antv-X6/index.jsx
index 6d20b17..96e04e1 100644
--- a/src/menu/components/chart/antv-X6/index.jsx
+++ b/src/menu/components/chart/antv-X6/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Popover, Tooltip, message } from 'antd'
-import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DoubleLeftOutlined } from '@ant-design/icons'
+import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DoubleLeftOutlined, DownloadOutlined } from '@ant-design/icons'
 import { Graph, Shape } from '@antv/x6'
 import { Stencil } from '@antv/x6-plugin-stencil'
 import { Transform } from '@antv/x6-plugin-transform'
@@ -11,6 +11,7 @@
 import { Keyboard } from '@antv/x6-plugin-keyboard'
 import { Clipboard } from '@antv/x6-plugin-clipboard'
 import { History } from '@antv/x6-plugin-history'
+import { Export } from '@antv/x6-plugin-export'
 
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
@@ -87,6 +88,52 @@
     }
   }
 }
+
+Graph.registerNode(
+  'lane',
+  {
+    inherit: 'rect',
+    markup: [
+      {
+        tagName: 'rect',
+        selector: 'body',
+      },
+      {
+        tagName: 'rect',
+        selector: 'name-rect',
+      },
+      {
+        tagName: 'text',
+        selector: 'name-text',
+      },
+    ],
+    attrs: {
+      body: {
+        fill: '#FFF',
+        stroke: '#5F95FF',
+        strokeWidth: 1,
+      },
+      'name-rect': {
+        width: 200,
+        height: 30,
+        fill: '#5F95FF',
+        stroke: '#fff',
+        strokeWidth: 1,
+        x: -1,
+      },
+      'name-text': {
+        ref: 'name-rect',
+        refY: 0.5,
+        refX: 0.5,
+        textAnchor: 'middle',
+        fontWeight: 'bold',
+        fill: '#fff',
+        fontSize: 12,
+      },
+    },
+  },
+  true,
+)
 
 Graph.registerNode(
   'mk-rect',
@@ -266,7 +313,16 @@
         width: card.width || 24,
         height: 400,
         subtype: card.subtype,
-        name: card.name
+        name: card.name,
+        grid: {
+          visible: true,
+          type: 'dot',
+          args: {
+            color: '#a0a0a0',
+            thickness: 1
+          }
+        },
+        gridType: 'dot'
       }
 
       let _card = {
@@ -318,39 +374,44 @@
     }, 1000)
   }
 
-  viewrender = () => {
-    // const { card } = this.state
-
-    // if (card.plot.subtype === 'mindmap') {
-    //   this.ponitrender()
-    // } else if (card.plot.subtype === 'indentTree') {
-    //   this.indentrender()
-    // } else if (card.plot.subtype === 'kapmap') {
-      this.kapmaprender()
-    // }
-  }
-
-  kapmaprender = () => {
+  plotchange = (res) => {
     const { card } = this.state
 
-    // #region 鍒濆鍖栫敾甯�
+    if (
+      card.plot.subtype !== res.plot.subtype ||
+      card.plot.gridType !== res.plot.gridType ||
+      card.plot.backgroundColor !== res.plot.backgroundColor
+    ) {
+      let _element = document.getElementById(card.uuid + 'container')
+      if (_element) {
+        _element.innerHTML = ''
+      }
+      setTimeout(() => {
+        this.viewrender()
+      }, 50)
+    }
+
+    this.updateComponent(res)
+  }
+
+  viewrender = () => {
+    const { card } = this.state
+
+    if (card.plot.subtype === 'xflow') {
+      this.xflowrender()
+    } else if (card.plot.subtype === 'lane') {
+      this.lanerender()
+    // } else if (card.plot.subtype === 'xflow') {
+      // this.xflowrender()
+    }
+  }
+
+  xflowrender = () => {
+    const { card } = this.state
+
     const graph = new Graph({
       container: document.getElementById(card.uuid + 'container'),
-      // grid: {
-      //   visible: true,
-      //   type: 'doubleMesh',
-      //   args: [
-      //     {
-      //       color: '#eee', // 涓荤綉鏍肩嚎棰滆壊
-      //       thickness: 1   // 涓荤綉鏍肩嚎瀹藉害
-      //     },
-      //     {
-      //       color: '#ddd', // 娆$綉鏍肩嚎棰滆壊
-      //       thickness: 1,  // 娆$綉鏍肩嚎瀹藉害
-      //       factor: 4      // 涓绘缃戞牸绾块棿闅�
-      //     }
-      //   ]
-      // },
+      grid: card.plot.grid,
       scaling: {
         min: 0.5,
         max: 2
@@ -358,7 +419,7 @@
       autoResize: true,
       panning: true,
       background: {
-        color: '#ffffff'
+        color: card.plot.backgroundColor || 'transparent'
       },
       mousewheel: {
         enabled: true,
@@ -423,6 +484,7 @@
       .use(new Keyboard())
       .use(new Clipboard())
       .use(new History())
+      .use(new Export())
 
     // #region 鍒濆鍖� stencil
     const stencil = new Stencil({
@@ -596,6 +658,290 @@
     
     this.mkGraph = graph
   }
+
+  lanerender = () => {
+    const { card } = this.state
+
+    const graph = new Graph({
+      container: document.getElementById(card.uuid + 'container'),
+      grid: card.plot.grid,
+      scaling: {
+        min: 0.5,
+        max: 2
+      },
+      autoResize: true,
+      panning: true,
+      background: {
+        color: card.plot.backgroundColor || 'transparent'
+      },
+      mousewheel: {
+        enabled: true,
+        zoomAtMousePosition: true,
+        modifiers: 'ctrl'
+      },
+      connecting: {
+        router: 'manhattan',
+        connector: {
+          name: 'rounded',
+          args: {
+            radius: 8
+          }
+        },
+        anchor: 'center',
+        connectionPoint: 'anchor',
+        allowBlank: false,
+        snap: {
+          radius: 20
+        },
+        createEdge() {
+          return new Shape.Edge({
+            attrs: {
+              line: {
+                stroke: '#A2B1C3',
+                strokeWidth: 2,
+                targetMarker: {
+                  name: 'block',
+                  width: 12,
+                  height: 8
+                }
+              }
+            },
+            zIndex: 2
+          })
+        },
+        validateConnection({ targetMagnet }) {
+          return !!targetMagnet
+        }
+      },
+      highlighting: {
+        magnetAdsorbed: {
+          name: 'stroke',
+          args: {
+            attrs: {
+              fill: '#5F95FF',
+              stroke: '#5F95FF'
+            }
+          }
+        }
+      },
+      translating: {
+        restrict(cellView) {
+          const cell = cellView.cell
+          const parentId = cell.prop('parent')
+
+          if (parentId) {
+            const parentNode = graph.getCellById(parentId)
+            if (parentNode) {
+              return parentNode.getBBox().moveAndExpand({
+                x: 0,
+                y: 30,
+                width: 0,
+                height: -30,
+              })
+            }
+          }
+          return cell.getBBox()
+        }
+      }
+    })
+
+    // #region 浣跨敤鎻掍欢
+    graph
+      .use(new Transform({
+        resizing: true,
+        rotating: true
+      }))
+      .use(new Selection())
+      .use(new Snapline())
+      .use(new Keyboard())
+      .use(new Clipboard())
+      .use(new History())
+      .use(new Export())
+
+    // #region 鍒濆鍖� stencil
+    const stencil = new Stencil({
+      title: '娴佺▼鍥�',
+      target: graph,
+      stencilGraphWidth: 180,
+      stencilGraphHeight: 180,
+      groups: [
+        {
+          title: '閫氱敤鑺傜偣',
+          name: 'group1'
+        },
+        {
+          title: '鑷畾涔�',
+          name: 'group2',
+          graphHeight: 120,
+          layoutOptions: {
+            rowHeight: 70
+          }
+        }
+      ],
+      layoutOptions: {
+        columns: 2,
+        columnWidth: 80,
+        rowHeight: 55
+      }
+    })
+
+    document.getElementById(card.uuid + 'stencil').appendChild(stencil.container)
+
+    // #region 蹇嵎閿笌浜嬩欢
+    graph.bindKey(['meta+c', 'ctrl+c'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.copy(cells)
+      }
+      return false
+    })
+    graph.bindKey(['meta+x', 'ctrl+x'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.cut(cells)
+      }
+      return false
+    })
+    graph.bindKey(['meta+v', 'ctrl+v'], () => {
+      if (!graph.isClipboardEmpty()) {
+        graph.paste({ offset: 32 })
+      }
+      return false
+    })
+
+    // undo redo
+    graph.bindKey(['meta+z', 'ctrl+z'], () => {
+      if (graph.canUndo()) {
+        graph.undo()
+      }
+      return false
+    })
+    graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
+      if (graph.canRedo()) {
+        graph.redo()
+      }
+      return false
+    })
+
+    // 鍒犻櫎鍏冪礌
+    graph.bindKey(['backspace', 'delete'], () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.removeCells(cells)
+        this.selectNode = null
+        this.setState({node: null})
+      }
+    })
+
+    // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌
+    const showPorts = (ports, show) => {
+      for (let i = 0, len = ports.length; i < len; i += 1) {
+        ports[i].style.visibility = show ? 'visible' : 'hidden'
+      }
+    }
+    graph.on('node:mouseenter', () => {
+      const container = document.getElementById(card.uuid + 'container')
+      const ports = container.querySelectorAll('.x6-port-body')
+      showPorts(ports, true)
+    })
+    graph.on('node:mouseleave', () => {
+      const container = document.getElementById(card.uuid + 'container')
+      const ports = container.querySelectorAll('.x6-port-body')
+      showPorts(ports, false)
+    })
+
+    graph.on('node:click', ({ e, x, y, node, view }) => {
+      this.selectNode = node
+      
+      this.setState({node: node.store.data})
+    })
+    graph.on('edge:click', ({ e, x, y, edge, view }) => {
+      this.selectNode = edge
+      
+      this.setState({node: edge.store.data})
+
+      graph.clearTransformWidgets()
+    })
+    graph.on('blank:click', ({ e, x, y }) => {
+      this.selectNode = null
+      
+      this.setState({node: null})
+    })
+    
+    const r1 = graph.createNode({
+      shape: 'mk-rect',
+      label: '寮�濮�',
+      attrs: {
+        body: {
+          rx: 20,
+          ry: 26
+        }
+      }
+    })
+    const r2 = graph.createNode({
+      shape: 'mk-rect',
+      label: '杩囩▼'
+    })
+    const r3 = graph.createNode({
+      shape: 'mk-rect',
+      attrs: {
+        body: {
+          rx: 6,
+          ry: 6
+        }
+      },
+      label: '鍙�夎繃绋�'
+    })
+    const r4 = graph.createNode({
+      shape: 'mk-polygon',
+      attrs: {
+        body: {
+          refPoints: '0,10 10,0 20,10 10,20'
+        }
+      },
+      label: '鍐崇瓥'
+    })
+    const r5 = graph.createNode({
+      shape: 'mk-polygon',
+      attrs: {
+        body: {
+          refPoints: '10,0 40,0 30,20 0,20'
+        }
+      },
+      label: '鏁版嵁'
+    })
+    const r6 = graph.createNode({
+      shape: 'mk-circle',
+      label: '杩炴帴'
+    })
+    
+    stencil.load([r1, r2, r3, r4, r5, r6], 'group1')
+    
+    const p1 = graph.createNode({
+      shape: 'mk-ellipse',
+      label: 'ellipse'
+    })
+    const p2 = graph.createNode({
+      shape: 'mk-star',
+      label: ''
+    })
+    
+    stencil.load([p1, p2], 'group2')
+
+    let data = [{"id":"1","shape":"lane","width":200,"height":500,"position":{"x":60,"y":60},"label":"<Function>"},{"id":"2","shape":"lane","width":200,"height":500,"position":{"x":260,"y":60},"label":"<Function>"},{"id":"3","shape":"lane","width":200,"height":500,"position":{"x":460,"y":60},"label":"<Function>"},{"id":"4","shape":"lane","width":200,"height":500,"position":{"x":660,"y":60},"label":"<Function>"}]
+    let cells = []
+    data.forEach((item) => {
+      if (item.shape === 'lane-edge') {
+        cells.push(graph.createEdge(item))
+      } else {
+        cells.push(graph.createNode(item))
+      }
+    })
+    graph.resetCells(cells)
+    graph.zoomToFit({ padding: 10, maxScale: 1 })
+
+    this.mkGraph = graph
+  }
   
   setTop = () => {
     if (!this.selectNode) {
@@ -629,6 +975,11 @@
 
   save = () => {
     // let nodes = this.mkGraph.toJSON()
+  }
+
+  savePicture = () => {
+    const { card } = this.state
+    this.mkGraph.exportPNG(card.name, {padding: 20})
   }
 
   changeProps = (value, key) => {
@@ -717,7 +1068,7 @@
       <div className="menu-x6-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
         <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
-            <ChartCompileForm config={card} plotchange={this.updateComponent}/>
+            <ChartCompileForm config={card} plotchange={this.plotchange}/>
             <CopyComponent type="antvG6" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/>
@@ -738,6 +1089,9 @@
             <Tooltip title="淇濆瓨">
               <SaveOutlined onClick={this.save}/>
             </Tooltip>
+            <Tooltip title="瀵煎嚭鍥剧墖">
+              <DownloadOutlined onClick={this.savePicture}/>
+            </Tooltip>
           </div>
           <div className="right-tool">
             <Tooltip title="鏀惧ぇ">

--
Gitblit v1.8.0