From d1ac67834e4bd2621809a9c778714bf575f80117 Mon Sep 17 00:00:00 2001
From: wente <329538422@qq.com>
Date: 星期三, 29 十一月 2023 16:16:15 +0800
Subject: [PATCH] 流程图

---
 web/src/views/modules/flowChart/flowChartEdit.vue |  827 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 827 insertions(+), 0 deletions(-)

diff --git a/web/src/views/modules/flowChart/flowChartEdit.vue b/web/src/views/modules/flowChart/flowChartEdit.vue
new file mode 100644
index 0000000..82c17c2
--- /dev/null
+++ b/web/src/views/modules/flowChart/flowChartEdit.vue
@@ -0,0 +1,827 @@
+<template>
+  <div>
+    <el-row :gutter="[8,8]">
+      <el-col :span="3">
+        <div class="fa-card-a">
+          <div id="stencil2" :style="'height:'+ left_p + 'px'"></div>
+        </div>
+      </el-col>
+      <el-col :span="21">
+          <div class="fa-card-a">
+            <el-form :inline="true">
+              <el-form-item prop="flowId" style="margin-left:10px;width: 180px;">
+                <zt-select v-model="flowId" :datas="flowList" @change="flowChange" placeholder="宸ョ▼椤圭洰"
+                           clearable></zt-select>
+              </el-form-item>
+              <el-form-item>
+                <el-button type="primary" v-show="dataForm.id" @click="saveDiagram()">淇濆瓨</el-button>
+              </el-form-item>
+            </el-form>
+            <div id="flowChart">
+            </div>
+            <flowChartNode v-show="type === 'node'" :flowId="flowId" :id="id" :globalGridAttr="globalGridAttr"
+                           :graph="graph"/>
+            <flowChart-edge v-show="type === 'edge'" :flowId="flowId" :id="id" :globalGridAttr="globalGridAttr"
+                            :graph="graph"/>
+          </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import {Graph, Shape, Addon, Cell} from '@antv/x6';
+import ConfigNode from './ConfigNode/index.vue'
+import flowChartNode from './flowChartNode/index.vue'
+import flowChartEdge from './flowChartEdge/index.vue'
+
+export default {
+  name: "flowChart-edit",
+  components: {
+    flowChartNode,
+    ConfigNode,
+    flowChartEdge
+  },
+  data() {
+    return {
+      shape: '',
+      diagramList:[],
+      diagramName:'',
+      diagramId:'',
+      flowList: '',
+      flowId: '',
+      diagramJson: '',
+      dataForm: { // 娴佺▼鍥惧唴瀹�
+        id: null,
+        diagram: null
+      },
+      type: '',
+      id: '',
+      graph: null,
+      emptyJson: {
+        // 鑺傜偣
+        nodes: [
+          {
+            id: 'node1', // String锛屽彲閫夛紝鑺傜偣鐨勫敮涓�鏍囪瘑
+            width: 500,   // Number锛屽彲閫夛紝鑺傜偣澶у皬鐨� width 鍊�
+            height: 300,  // Number锛屽彲閫夛紝鑺傜偣澶у皬鐨� height 鍊�
+            label: '璇ユ祦绋嬪浘杩樻病鏈夐厤缃�',
+            attrs: {
+              body: {
+                strokeWidth: 0
+              },
+            }
+            //   text: {
+            //     text: '璇ラ」鐩繕鏈紪鍒剁綉缁滃浘',
+            //     // fontSize: 56,
+            //     fill: 'rgba(0,0,0,0.7)'
+            //   },
+            // },
+          }
+        ],
+      },
+      globalGridAttr: {
+        type: 'mesh',
+        size: 10,
+        color: '#e5e5e5',
+        thickness: 1,
+        colorSecond: '#d0d0d0',
+        thicknessSecond: 1,
+        factor: 4,
+        bgColor: '#e5e5e5',
+        showImage: true,
+        repeat: 'watermark',
+        angle: 30,
+        position: 'center',
+        bgSize: JSON.stringify({width: 150, height: 150}),
+        opacity: 0.1,
+
+        stroke: '#5F95FF',
+        strokeWidth: 1,
+        connector: 'normal',
+        label: '',
+
+        nodeStroke: '#5F95FF',
+        nodeStrokeWidth: 1,
+        nodeFill: '#ffffff',
+        nodeFontSize: 12,
+        nodeColor: '#080808',
+        nodeText: '',
+        nodeDate: '',
+        nodeUsers: '',
+        nodeDataDate: '',
+        nodeDataText: ''
+      },
+      isReady: false,
+      curCel: Cell,
+      left_p: document.documentElement.clientHeight -220,
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 8,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 8,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 8,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 8,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+          },
+          {
+            group: 'right',
+          },
+          {
+            group: 'bottom',
+          },
+          {
+            group: 'left',
+          },
+        ],
+      }
+    }
+  },
+  watch: {
+  },
+  methods: {
+    async getFlowList() {
+      let res = await this.$http.get(`/WfDef/getFlowList`)
+      this.flowList = res.data
+      console.log(this.flowList,'this.flowList')
+      for (let i = 0; i < this.flowList.length; i++) {
+        if (this.flowList[i] && this.flowList[i].id) {
+          this.flowId = this.flowList[i].id
+          console.log(this.flowId, 'this.flowId 6789')
+          break
+        }
+      }
+      this.flowChange(this.flowId)
+    },
+    flowChange() {
+      this.dataForm.id = this.flowId
+      // this.flowId = this.dataForm.id
+      console.log(this.flowId,'this.flowId')
+      this.getDiagram()
+    },
+    async getDiagram() {
+      let res = await this.$http.get(`/WfDef/${this.flowId}`)
+      if (res.data !== null) {
+        this.dataForm = res.data
+        if (res.data.diagram != null && res.data.diagram != '')
+          this.diagramJson = JSON.parse(this.dataForm.diagram)
+        else
+          this.diagramJson = this.emptyJson
+        console.log(this.diagramJson, 'this.Diagram json')
+        this.graph.fromJSON(this.diagramJson)
+        this.graph.centerContent()
+        this.graph.zoomToFit()
+        // this.graph.freeze('flowChart')
+      } else {
+        this.dataForm.id = null
+/*        this.graph.fromJSON(this.emptyJson)
+        this.graph.centerContent()
+        this.graph.zoomToFit()
+        this.graph.freeze()*/
+      }
+    },
+    init1() {
+      // console.log(document.documentElement.clientWidth, 'document.documentElement.clientWidth')
+      // console.log(document.documentElement.clientHeight, 'document.documentElement.clientHeight')
+      this.graph = new Graph({
+        container: document.getElementById('flowChart'),
+        width: document.documentElement.clientWidth,
+        height: document.documentElement.clientHeight - 240,
+        // async: true,
+        grid: {
+          visible: true,
+        },
+        onToolItemCreated({ tool }) {
+          const handle = tool
+          const options = handle.options
+          if (options && options.index % 2 === 1) {
+            tool.setAttrs({ fill: 'red' })
+          }
+        },
+        autoResize: true,
+        history: true,
+        panning: {
+          enabled: false,
+        },
+        scroller: {
+          enabled: true,
+          pageVisible: true,
+          pageBreak: true,
+          pannable: true,
+        },
+        mousewheel: {
+          enabled: true,
+          zoomAtMousePosition: true,
+          modifiers: 'ctrl',
+          minScale: 0.5,
+          maxScale: 2,
+        },
+        connecting: {
+          router: { name: 'manhattan' },
+          connector: { name: 'rounded' },
+          // anchor: 'center',
+          connectionPoint: 'anchor',
+          allowBlank: false,
+          createEdge() {
+            return new Shape.Edge({
+              attrs: {
+                line: {
+                  stroke: '#A2B1C3',
+                  strokeWidth: 2,
+                  targetMarker: 'classic'
+                }
+              },
+              tools: {
+                name: 'segments',
+                args: {
+                  snapRadius: 20,
+                  attrs: {
+                    fill: '#444',
+                  },
+                },
+              },
+              zIndex: 0,
+            })
+          },
+          validateConnection({targetMagnet}) {
+            return !!targetMagnet
+          },
+        },
+        highlighting: {
+          magnetAdsorbed: {
+            name: 'stroke',
+            args: {
+              attrs: {
+                fill: '#5F95FF',
+                stroke: '#5F95FF',
+              },
+            },
+          },
+        },
+        resizing: {
+          enabled:true,
+          restricted:true
+        },
+        rotating: true,
+        selecting: {
+          enabled: true,
+          rubberband: true,
+          rubberEdge: true,
+          showNodeSelectionBox: true,
+        },
+        snapline: true,
+        keyboard: true,
+        clipboard: true,
+      })
+      // graph.fromJSON(
+      //   {nodes:nodes,
+      //     edges:edges}
+      // )
+      this.graph.centerContent()
+      const stencil = new Addon.Stencil({
+        title: '',
+        target: this.graph,
+        stencilGraphWidth: 200,
+        stencilGraphHeight: 480,
+        // collapsable: true,
+        groups: [
+          {
+            title: '鍥惧厓',
+            name: 'group1',
+          }
+        ],
+        layoutOptions: {
+          columns: 1,
+          columnWidth: 120,
+          // rowHeight: 75,
+        },
+      })
+      document.getElementById('stencil2').appendChild(stencil.container)
+
+      Graph.registerNode(
+        'custom-polygon',
+        {
+          inherit: 'polygon',
+          width: 86,
+          height: 56,
+          attrs: {
+            body: {
+              strokeWidth: 1,
+              stroke: '#5F95FF',
+              fill: '#EFF4FF',
+            },
+            // title:{
+            //   text:'',
+            //   refX: 40,
+            //   refY: 38,
+            //   fontSize: 14,
+            //   fill: '#262626',
+            //   'text-anchor': 'start',
+            // },
+            text: {
+              // refX: 40,
+              // refY: 14,
+              fontSize: 14,
+              fill: '#262626',
+              // 'text-anchor': 'start',
+            },
+          },
+          // markup: [
+          //   {
+          //     tagName: 'polygon',
+          //     selector: 'body',
+          //   },
+          //   {
+          //     tagName: 'text',
+          //     selector: 'title',
+          //   },
+          //   {
+          //     tagName: 'text',
+          //     selector: 'text',
+          //   },
+          // ],
+          ports: {
+            ...this.ports
+            // items: [
+            //   {
+            //     group: 'top',
+            //   },
+            //   {
+            //     group: 'bottom',
+            //   },
+            // ],
+          },
+        },
+        true,
+      )
+
+      Graph.registerNode(
+        'custom-circle',
+        {
+          inherit: 'ellipse',
+          width: 86,
+          height: 56,
+          data: {
+            dataId: '',
+            finishDate: ''
+          },
+          attrs: {
+            body: {
+              strokeWidth: 1,
+              stroke: '#5F95FF',
+              fill: '#EFF4FF',
+            },
+            title: {
+              text: '',
+              fontSize: 14,
+              fill: '#262626',
+              refX: 0.5,
+              refY: '100%',
+              refY2: 4,
+              textAnchor: 'middle',
+              textVerticalAnchor: 'top',
+            },
+            text: {
+              fontSize: 14,
+              fill: '#262626',
+              refX: 0.5,
+              refY: 0.5,
+              textAnchor: 'middle',
+              textVerticalAnchor: 'middle',
+            },
+          },
+          markup: [
+            {
+              tagName: 'ellipse',
+              selector: 'body',
+            },
+            {
+              tagName: 'text',
+              selector: 'title',
+            },
+            {
+              tagName: 'text',
+              selector: 'text',
+            },
+          ],
+          ports: {...this.ports},
+        },
+        true,
+      )
+      const r6 = this.graph.createNode({
+        shape: 'text-block',
+        label: '鍙�夎繃绋�',
+        width: 86,
+        height: 56,
+        data: {
+          stepMarker:''
+        },
+        attrs: {
+          body: {
+            strokeWidth: 1,
+            stroke: '#5F95FF',
+            fill: '#EFF4FF',
+            rx: 6,
+            ry: 6
+          },
+          text: {
+            text: '鍙�夎繃绋�',
+            fontSize: 14,
+            fill: '#262626',
+            refX: '0',
+            refY: -0.5,
+            refY2: '0',
+            textAnchor: 'middle',
+            textVerticalAnchor: 'middle',
+          },
+        },
+        markup: [
+          {
+            tagName: 'rect',
+            selector: 'body',
+          },
+          {
+            tagName: 'text',
+            selector: 'text',
+          },
+        ],
+        ports: {...this.ports},
+      })
+      const r4 = this.graph.createNode({
+        shape: 'custom-polygon',
+        data: {
+          stepMarker:''
+        },
+        attrs: {
+          body: {
+            refPoints: '0,10 10,0 20,10 10,20',
+          },
+        },
+        label: '鍐崇瓥',
+      })
+      const r5 = this.graph.createNode({
+        shape: 'custom-circle',
+        data: {
+          stepMarker:''
+        },
+        label: '闃舵',
+      })
+      stencil.load([r4, r5,r6], 'group1')
+
+      this.graph.bindKey(['meta+c', 'ctrl+c'], () => {
+        const cells = this.graph.getSelectedCells()
+        if (cells.length) {
+          this.graph.copy(cells)
+        }
+        return false
+      })
+
+      this.graph.bindKey(['meta+x', 'ctrl+x'], () => {
+        const cells = this.graph.getSelectedCells()
+        if (cells.length) {
+          this.graph.cut(cells)
+        }
+        return false
+      })
+
+      this.graph.bindKey(['meta+v', 'ctrl+v'], () => {
+        if (!this.graph.isClipboardEmpty()) {
+          const cells = this.graph.paste({offset: 32})
+          this.graph.cleanSelection()
+          this.graph.select(cells)
+        }
+        return false
+      })
+//undo redo
+      this.graph.bindKey(['meta+z', 'ctrl+z'], () => {
+        if (this.graph.history.canUndo()) {
+          this.graph.history.undo()
+        }
+        return false
+      })
+
+      this.graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
+        if (this.graph.history.canRedo()) {
+          this.graph.history.redo()
+        }
+        return false
+      })
+
+// select all
+      this.graph.bindKey(['meta+a', 'ctrl+a'], () => {
+        const nodes = this.graph.getNodes()
+        if (nodes) {
+          this.graph.select(nodes)
+        }
+      })
+//delete
+      this.graph.bindKey('delete', () => {
+        const cells = this.graph.getSelectedCells()
+        if (cells.length) {
+          this.graph.removeCells(cells)
+        }
+      })
+// zoom
+      this.graph.bindKey(['ctrl+1', 'meta+1'], () => {
+        const zoom = this.graph.zoom()
+        if (zoom < 1.5) {
+          this.graph.zoom(0.1)
+        }
+      })
+
+      this.graph.bindKey(['ctrl+2', 'meta+2'], () => {
+        const zoom = this.graph.zoom()
+        if (zoom > 0.5) {
+          this.graph.zoom(-0.1)
+        }
+      })
+
+      this.graph.on('blank:click', ({cell}) => {
+        this.reset()
+        this.type = 'grid'
+        // this.id = cell.id
+      })
+
+      this.graph.on('cell:click', ({cell}) => {
+        // this.type.value = cell.isNode() ? "node" : "edge"
+        this.type = cell.isNode() ? "node" : "edge"
+        this.shape = cell.shape
+        this.id = cell.id
+        // this.nodeOpt(this.id, this.globalGridAttr)
+      })
+      //鍗曞嚮杈硅妭鐐�
+      this.graph.on('edge:click', ({edge}) => {
+        this.reset()
+        edge.attr('line/stroke', 'orange')
+        edge.prop('labels/0', {
+          attrs: {
+            body: {
+              stroke: 'orange',
+            },
+          },
+        })
+      })
+      // 鍗曞嚮node鑺傜偣
+      this.graph.on('node:click', ({node}) => {
+        this.reset()
+        node.attr('line/stroke', 'orange')
+        node.prop('labels/0', {
+          attrs: {
+            body: {
+              stroke: 'orange',
+            },
+          },
+        })
+      })
+      // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌
+      this.graph.on('node:delete', ({view, e}) => {
+        e.stopPropagation()
+        view.cell.remove()
+      })
+
+      this.graph.on('node:customevent', ({name, view, e}) => {
+        if (name === 'node:delete') {
+          e.stopPropagation()
+          view.cell.remove()
+        }
+      })
+      // 鍙屽嚮缂栬緫
+      this.graph.on('cell:dblclick', ({cell, e}) => {
+        const isNode = cell.isNode()
+        const name = cell.isNode() ? 'node-editor' : 'edge-editor'
+        cell.removeTool(name)
+        cell.addTools({
+          name,
+          args: {
+            event: e,
+            attrs: {
+              backgroundColor: isNode ? '#EFF4FF' : '#FFF',
+              text: {
+                fontSize: 16,
+                fill: '#262626',
+              },
+            },
+          },
+        })
+      })
+
+      this.graph.on('node:mouseenter', ({node}) => {
+        const flowChart = document.getElementById('flowChart')
+        const ports = flowChart.querySelectorAll(
+          '.x6-port-body',
+        )
+        this.showPorts(ports, true)
+      })
+
+      this.graph.on('node:mouseleave', ({node}) => {
+        // if (node.hasTool('button-remove')) {
+        //   node.removeTool('button-remove')
+        // }
+        const flowChart = document.getElementById('flowChart')
+        const ports = flowChart.querySelectorAll(
+          '.x6-port-body',
+        )
+        this.showPorts(ports, false)
+      })
+
+      this.graph.on('edge:mouseenter', ({cell}) => {
+        cell.addTools([
+          {
+            name: 'source-arrowhead',
+          },
+          {
+            name: 'target-arrowhead',
+            args: {
+              attrs: {
+                fill: 'red',
+              },
+            },
+          },
+        ])
+        cell.addTools(
+          [
+            {
+              name: 'segments',
+              args: {snapRadius: 20, attrs: {fill: '#444'}}
+            }
+          ]
+        )
+      })
+
+      this.graph.on('edge:mouseleave', ({cell}) => {
+        cell.removeTools()
+      })
+    },
+    reset() {
+      this.graph.drawBackground({color: '#fff'})
+      const nodes = this.graph.getNodes()
+      const edges = this.graph.getEdges()
+      nodes.forEach((node) => {
+        node.attr('body/stroke', '#5F95FF')
+      })
+      edges.forEach((edge) => {
+        edge.attr('line/stroke', '#5F95FF')
+        edge.prop('labels/0', {
+          attrs: {
+            body: {
+              stroke: '#5F95FF',
+            },
+          },
+        })
+      })
+    },
+    showPorts(ports, show) {
+      for (let i = 0, len = ports.length; i < len; i = i + 1) {
+        ports[i].style.visibility = show ? "visible" : "hidden"
+      }
+    },
+    nodeOpt(id, globalGridAttr) {
+      this.curCel = null
+      if (id) {
+        let cell = this.graph.getCellById(id)
+        // console.log(cell, 'let cell 123456')
+        if (!cell || !cell.isNode()) {
+          return
+        }
+        this.curCel = cell
+        globalGridAttr.nodeStroke = cell.attr('body/stroke')
+        globalGridAttr.nodeStrokeWidth = cell.attr('body/strokeWidth')
+        globalGridAttr.nodeFill = cell.attr('body/fill')
+        globalGridAttr.nodeFontSize = cell.attr('text/fontSize')
+        globalGridAttr.nodeFontSize = cell.attr('title/fontSize')
+        globalGridAttr.nodeColor = cell.attr('text/fill')
+        globalGridAttr.nodeColor = cell.attr('title/fill')
+        // globalGridAttr.nodeColor = cell.attr('label/text/fill')
+        // globalGridAttr.nodeColor = cell.attr('label/title/fill')
+        globalGridAttr.nodeUsers = cell.attr('approve/users')
+        globalGridAttr.nodeText = cell.attr('text/text')
+        globalGridAttr.nodeDate = cell.attr('title/text')
+        // let data={
+        //   dataId:this.flowId,
+        //   finishDate: globalGridAttr.nodeDate,
+        // }
+        // cell.setData(data)
+        // console.log( cell.getData(),' cell.getData() 909')
+      }
+      return this.curCel;
+    },
+    async saveDiagram() {
+      console.log(JSON.stringify(this.graph.toJSON()), 'graph.toJSON()')
+      this.dataForm.diagram = JSON.stringify(this.graph.toJSON())
+      console.log(this.dataForm, 'dataFrom')
+      await this.$http[this.dataForm.id === null ? 'post' : 'put'](`/WfDef`, this.dataForm).then(async res => {
+        if (res.msg === 'success') {
+          this.$alert('淇濆瓨鎴愬姛', '鎻愮ず', {
+            confirmButtonText: '纭畾'
+          })
+        }
+      })
+    }
+  },
+  mounted() {
+    this.getFlowList()
+    this.init1()
+    // this.nodeOpt(this.id, this.globalGridAttr)
+    // let data={
+    //     dataId: this.flowId,
+    //     finishDate: this.date
+    // }
+    // this.curCel.setData(data)
+    // if(this.dataForm) {
+    //   this.graph.fromJSON(this.diagramJson)
+    // }
+    this.type = 'grid'
+  }
+}
+</script>
+
+<style>
+#flowChart {
+  display: flex;
+  border: 1px solid #dfe3e8;
+  width: 100% !important;
+}
+
+.x6-graph-scroller.x6-graph-scroller-pannable {
+  width: 100% !important;
+}
+
+#stencil2 {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  border-right: 1px solid #dfe3e8;
+}
+
+.x6-widget-stencil {
+  position: relative;
+  height: 100%;
+}
+
+.x6-widget-stencil-content {
+  position: relative;
+  height: 100%;
+}
+.x6-graph-scroller.x6-graph-scroller-paged.x6-graph-scroller-pannable{
+  box-shadow:1px 1px 3px #606266;
+  border-radius: 10px;
+}
+</style>

--
Gitblit v1.9.1