Sfoglia il codice sorgente

连接桩布局方法

CzRger 2 mesi fa
parent
commit
c4c8eedf72

+ 7 - 11
src/views/workflow/chart/index.vue

@@ -17,6 +17,7 @@ import WorkflowNode from "@/views/workflow/nodes/index.vue";
 import {merge} from "lodash";
 import {handleEdge, handleNode} from "@/views/workflow/handle";
 
+const workflowFuncInject = inject('workflowFunc', {} as WorkflowFunc)
 register({
   shape: 'workflow-node',
   component: WorkflowNode,
@@ -51,17 +52,13 @@ Graph.registerPortLayout('end', (portsPositionArgs, elemBBox) => {
 Graph.registerPortLayout('more', (portsPositionArgs, elemBBox) => {
   return portsPositionArgs.map((_, index) => {
     nextTick(() => {
-      const dom = document.getElementById(_.portId)
-      if (dom) {
-        const node = state.graph.getCellById(_.nodeId)
-        node.portProp(_.portId, ['args', 'dy'], dom.offsetTop + 17)
-        if (edgeTimer) {
-          clearTimeout(edgeTimer)
-        }
-        edgeTimer = setTimeout(() => {
-          initEdges()
-        }, 100)
+      workflowFuncInject.layoutPort(_.nodeId, _.portId)
+      if (edgeTimer) {
+        clearTimeout(edgeTimer)
       }
+      edgeTimer = setTimeout(() => {
+        initEdges()
+      }, 100)
     })
     return {
       position: {
@@ -82,7 +79,6 @@ const state: any = reactive({
   isInitEdges: false
 })
 const ref_chart = ref()
-const workflowFuncInject = inject('workflowFunc', {} as WorkflowFunc)
 const initChart = () => {
   state.graph = new Graph({
     container: ref_chart.value,

+ 0 - 4
src/views/workflow/chart/node-add.vue

@@ -43,7 +43,6 @@ const state: any = reactive({})
 const onAddNode = (type) => {
   const node = getNodeDefault(type)
   const sons = props.graph.getSuccessors(props.node, {breadthFirst: true, deep: false, distance: 1}).filter(v => v.data.edgeSource === props.port.id)
-  console.log(sons)
   const diff = 100
   let X = 0
   let Y = 0
@@ -69,15 +68,12 @@ const onAddNode = (type) => {
     source: props.port.args.nodeId,
     port: '',
   }
-  console.log(props.port)
   if (props.port.args.type === 'more') {
     edge.port = props.port.id
     node.data.edgeSource = props.port.id
   } else {
     node.data.edgeSource = `${props.node.id}_end`
   }
-  console.log(node)
-  console.log(edge)
   props.graph.addNode(handleNode(node))
   props.graph.addEdge(handleEdge(edge))
 }

+ 33 - 3
src/views/workflow/index.vue

@@ -3,7 +3,7 @@
     <TeleportContainer/>
     <el-button style="position: absolute; top: 0;left: 0; z-index: 2" type="primary" @click="getJsonData">保存配置</el-button>
     <div class="workflow-chart">
-      <workflowChart :data="state.workflowData" ref="ref_workflow" @init="graph => graphRef = graph"/>
+      <workflowChart :data="state.workflowData" ref="ref_workflow" @init="graph => state.graph = graph"/>
     </div>
     <workflowPanel v-model:show="state.showPanel" :node="state.currentNode"/>
   </div>
@@ -27,19 +27,49 @@ const state: any = reactive({
   currentNode: null,
   graph: null
 })
-const graphRef = ref(null)
 const ref_workflow = ref()
 provide('workflowFunc', <WorkflowFunc>{
   nodeClick: (node) => {
     state.currentNode = node
     state.showPanel = true
+  },
+  layoutPort: (nodeId: string, portId: string) => {
+    const dom = document.getElementById(portId)
+    if (dom) {
+      const node = state.graph.getCellById(nodeId)
+      node.portProp(portId, ['args', 'dy'], dom.offsetTop + 17)
+    }
   }
 })
-provide('graph', graphRef)
 
 const getJsonData = () => {
   const data = ref_workflow.value.toJSON()
   console.log(data)
+  const res: any = {
+    nodes: [],
+    edges: []
+  }
+  data.cells.forEach((cell: any) => {
+    if (cell.shape === 'workflow-node') {
+      const node: any = {
+        id: cell.id,
+        x: cell.position.x,
+        y: cell.position.y,
+        data: cell.data
+      }
+      res.nodes.push(node)
+    } else if (cell.shape === 'edge') {
+      const edge: any = {
+        target: cell.target.cell,
+        source: cell.source.cell,
+      }
+      if (!cell.source.port.includes('end')) {
+        edge.port = cell.source.port
+      }
+      res.edges.push(edge)
+    }
+  })
+  console.log(res)
 }
 const initData = () => {
   state.workflowData = data

+ 146 - 12
src/views/workflow/mockJson.ts

@@ -2,18 +2,19 @@ export const data = {
   "nodes": [
     {
       "id": "3ba412bb-3772-4f61-85de-095f4017858c",
-      "x": 0,
-      "y": 0,
+      "x": -370,
+      "y": -120,
       "data": {
         "title": "开始",
         "type": "root",
         "p1": "开始的参数1",
+        "id": "3ba412bb-3772-4f61-85de-095f4017858c"
       }
     },
     {
       "id": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
-      "x": 400,
-      "y": 0,
+      "x": -230,
+      "y": 50,
       "data": {
         "title": "条件分支",
         "type": "if-else",
@@ -31,6 +32,24 @@ export const data = {
             }
           },
           {
+            "id": "7d21639f-866a-46df-9ec2-04016527ccd0",
+            "data": {
+              "p1": ""
+            }
+          },
+          {
+            "id": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb",
+            "data": {
+              "p1": ""
+            }
+          },
+          {
+            "id": "d67172bc-ace5-43a0-8d30-ce53b7ce6762",
+            "data": {
+              "p1": ""
+            }
+          },
+          {
             "id": "7171167d-873b-4621-9ce1-dd45f9f4c9c3",
             "data": {
               "p1": "条件分支1的桩3"
@@ -38,12 +57,14 @@ export const data = {
           }
         ],
         "p1": "条件分支1的的参数1",
+        "id": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+        "edgeSource": "3ba412bb-3772-4f61-85de-095f4017858c"
       }
     },
     {
       "id": "b39b1a2f-8474-456b-8859-ce0b6597dd47",
-      "x": 400,
-      "y": 200,
+      "x": 60,
+      "y": 700,
       "data": {
         "title": "条件分支",
         "type": "if-else",
@@ -62,6 +83,85 @@ export const data = {
           }
         ],
         "p1": "条件分支2的参数1",
+        "id": "b39b1a2f-8474-456b-8859-ce0b6597dd47",
+        "edgeSource": "7171167d-873b-4621-9ce1-dd45f9f4c9c3"
+      }
+    },
+    {
+      "id": "b948a0d9-6e18-4b0f-a4c4-9a60bf3fc624",
+      "x": 140,
+      "y": -220,
+      "data": {
+        "id": "b948a0d9-6e18-4b0f-a4c4-9a60bf3fc624",
+        "title": "测试节点",
+        "type": "test",
+        "edgeSource": "ce2c26aa-9b40-4e32-858e-38fa4b09718d"
+      }
+    },
+    {
+      "id": "b7dc7ea7-239b-40c5-b751-8ce5ebf49a23",
+      "x": 180,
+      "y": -110,
+      "data": {
+        "id": "b7dc7ea7-239b-40c5-b751-8ce5ebf49a23",
+        "title": "测试节点",
+        "type": "test",
+        "edgeSource": "ce2c26aa-9b40-4e32-858e-38fa4b09718d"
+      }
+    },
+    {
+      "id": "94653d7d-c496-4e42-8ad2-7fa038abcc1e",
+      "x": 520,
+      "y": -10,
+      "data": {
+        "id": "94653d7d-c496-4e42-8ad2-7fa038abcc1e",
+        "title": "测试节点",
+        "type": "test",
+        "edgeSource": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+      }
+    },
+    {
+      "id": "123fc5c7-1d97-4be0-93f6-3afe0dfaf592",
+      "x": 470,
+      "y": 100,
+      "data": {
+        "id": "123fc5c7-1d97-4be0-93f6-3afe0dfaf592",
+        "title": "测试节点",
+        "type": "test",
+        "edgeSource": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+      }
+    },
+    {
+      "id": "e2d0d66f-3c14-4b28-b617-48243c75e18a",
+      "x": 490,
+      "y": 270,
+      "data": {
+        "id": "e2d0d66f-3c14-4b28-b617-48243c75e18a",
+        "title": "测试节点",
+        "type": "test",
+        "edgeSource": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+      }
+    },
+    {
+      "id": "e48dc03d-38c2-4668-ace1-220f7a01a878",
+      "x": 404,
+      "y": 418,
+      "data": {
+        "id": "e48dc03d-38c2-4668-ace1-220f7a01a878",
+        "title": "测试节点",
+        "type": "test",
+        "edgeSource": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+      }
+    },
+    {
+      "id": "75fd8fd1-e286-4100-afb4-869f8250814d",
+      "x": 404,
+      "y": 577,
+      "data": {
+        "id": "75fd8fd1-e286-4100-afb4-869f8250814d",
+        "title": "测试节点",
+        "type": "test",
+        "edgeSource": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
       }
     }
   ],
@@ -70,11 +170,45 @@ export const data = {
       "target": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
       "source": "3ba412bb-3772-4f61-85de-095f4017858c"
     },
-    // {
-    //   "target": "b39b1a2f-8474-456b-8859-ce0b6597dd47",
-    //   "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
-    //   "port": "7171167d-873b-4621-9ce1-dd45f9f4c9c3"
-    // }
+    {
+      "target": "b39b1a2f-8474-456b-8859-ce0b6597dd47",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "7171167d-873b-4621-9ce1-dd45f9f4c9c3"
+    },
+    {
+      "target": "b948a0d9-6e18-4b0f-a4c4-9a60bf3fc624",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "ce2c26aa-9b40-4e32-858e-38fa4b09718d"
+    },
+    {
+      "target": "b7dc7ea7-239b-40c5-b751-8ce5ebf49a23",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "ce2c26aa-9b40-4e32-858e-38fa4b09718d"
+    },
+    {
+      "target": "94653d7d-c496-4e42-8ad2-7fa038abcc1e",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+    },
+    {
+      "target": "123fc5c7-1d97-4be0-93f6-3afe0dfaf592",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+    },
+    {
+      "target": "e2d0d66f-3c14-4b28-b617-48243c75e18a",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+    },
+    {
+      "target": "e48dc03d-38c2-4668-ace1-220f7a01a878",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+    },
+    {
+      "target": "75fd8fd1-e286-4100-afb4-869f8250814d",
+      "source": "676e9ade-d857-4fea-b2d4-ff9484dcebb8",
+      "port": "2ae1788e-b022-44ea-a2d4-98f8eee7cafb"
+    }
   ]
 }
-

+ 1 - 0
src/views/workflow/nodes/if-else/index.vue

@@ -43,6 +43,7 @@ onMounted(() => {
 <style lang="scss" scoped>
 .node-if-else {
   .port-item {
+    word-break: break-all;
     .port-item-head {
       display: flex;
       justify-content: space-between;

+ 1 - 1
src/views/workflow/nodes/index.vue

@@ -43,7 +43,7 @@ onMounted(() => {
   border-radius: 10px;
   background-color: #ffffff;
   position: absolute;
-  min-width: 240px;
+  width: 240px;
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
   &:hover {
     border-color: #286bfb;

+ 1 - 1
src/views/workflow/panel/index.vue

@@ -25,7 +25,7 @@ import ifElsePanel from './is-else/index.vue'
 const emits = defineEmits([])
 const props = defineProps({
   show: {},
-  node: {}
+  node: <any>{},
 })
 const {proxy}: any = getCurrentInstance()
 const state: any = reactive({})

+ 9 - 4
src/views/workflow/panel/is-else/index.vue

@@ -15,10 +15,12 @@
 </template>
 
 <script setup lang="ts">
-import {getCurrentInstance, reactive, ref, watch} from "vue";
+import {getCurrentInstance, inject, reactive, ref, watch} from "vue";
 import { v4 } from "uuid";
+import {WorkflowFunc} from "@/views/workflow/types";
 
-const emits = defineEmits([])
+const workflowFuncInject = inject('workflowFunc', {} as WorkflowFunc)
+const emits = defineEmits(['reLayoutPort'])
 const props = defineProps({
   node: <any>{}
 })
@@ -29,11 +31,14 @@ const state: any = reactive({
 watch(() => props.node, (n) => {
   if (n) {
     state.nodeData = n.data
-    console.log(state.nodeData)
   }
 }, {immediate: true})
+watch(() => state.nodeData, (n) => {
+  n.ports.forEach(p => {
+    workflowFuncInject.layoutPort(props.node.id, p.id)
+  })
+}, {deep: true})
 const onAddPort = () => {
-  console.log(props.node)
   const data = {
     id: v4(),
     data: {

+ 2 - 1
src/views/workflow/types.ts

@@ -1,5 +1,6 @@
 export type WorkflowFunc = {
-  nodeClick: (node) => void
+  nodeClick: (node: any) => void
+  layoutPort: (nodeId: string, portId: string) => void
 }
 
 export type NodeStruct = {