setup()

in seatunnel-engine/seatunnel-engine-ui/src/components/directed-acyclic-graph/index.tsx [131:362]


  setup(props) {
    let focusedId = 0
    let graph: Graph
    watch(
      () => props.focusedId,
      () => {
        if (!graph || focusedId === props.focusedId) return
        if (props.focusedId) {
          // const cell = graph.getCellById('node-' + props.focusedId)
          // if (cell) {
          //   cell.trigger('click')
          // }
          graph.select('node-' + props.focusedId)
        } else {
          graph.select('node-0')
          // graph.trigger('blank:click')
        }
      }
    )
    onMounted(() => {
      graph = new Graph({
        container: document.getElementById('container')!,
        panning: {
          enabled: true,
          eventTypes: ['leftMouseDown', 'mouseWheel']
        },
        mousewheel: {
          enabled: true,
          modifiers: 'ctrl',
          factor: 1.1,
          maxScale: 1.5,
          minScale: 0.5
        },
        highlighting: {
          magnetAdsorbed: {
            name: 'stroke',
            args: {
              attrs: {
                fill: '#fff',
                stroke: '#31d0c6',
                strokeWidth: 4
              }
            }
          }
        },
        connecting: {
          snap: true,
          allowBlank: false,
          allowLoop: false,
          highlight: true,
          connector: 'algo-connector',
          connectionPoint: 'anchor',
          anchor: 'center',
          validateMagnet({ magnet }) {
            return magnet.getAttribute('port-group') !== 'left'
          },
          createEdge() {
            return graph.createEdge({
              shape: 'dag-edge',
              attrs: {
                line: {
                  strokeDasharray: '5 5'
                }
              },
              zIndex: -1
            })
          }
        }
      })
      graph.use(
        new Selection({
          multiple: false,
          rubberEdge: true,
          rubberNode: true,
          modifiers: 'shift',
          rubberband: true
        })
      )

      graph.on('edge:connected', ({ edge }) => {
        edge.attr({
          line: {
            strokeDasharray: ''
          }
        })
      })

      graph.on('node:change:data', ({ node }) => {
        const edges = graph.getIncomingEdges(node)
        const { status } = node.getData() as NodeStatus
        edges?.forEach((edge) => {
          if (status === 'RUNNING') {
            edge.attr('line/strokeDasharray', 5)
            edge.attr('line/style/animation', 'running-line 30s infinite linear')
          } else {
            edge.attr('line/strokeDasharray', '')
            edge.attr('line/style/animation', '')
          }
        })
      })
      graph.on('node:click', ({ node }) => {
        const { id } = node.getData() as NodeStatus
        focusedId = id
        const vertex = props?.job?.jobDag?.vertexInfoMap?.find((item) => item.vertexId === id)
        props.onNodeClick(vertex)
      })
      graph.on('blank:click', () => {
        props.onNodeClick()
      })

      const init = () => {
        const matrix = [] as Vertex[][]
        const items: Cell.Metadata[] = []

        const offsetY = 140
        const offsetX = nodeWidth + 200

        const processed = [] as Vertex[]
        const vertexs = props?.job?.jobDag?.vertexInfoMap || []
        const edgeMap = props?.job?.jobDag?.pipelineEdges || {}
        let zIndex = 0
        for (const pipelineId of Object.keys(edgeMap)) {
          const edges = edgeMap[pipelineId]
          const row = [] as Vertex[]
          matrix.push(row)
          for (const edge of edges) {
            items.push({
              id: `edge-${pipelineId}-${edge.inputVertexId}-${edge.targetVertexId}`,
              shape: 'dag-edge',
              source: {
                cell: `node-${edge.inputVertexId}`,
                port: `node-${edge.inputVertexId}-right`
              },
              target: {
                cell: `node-${edge.targetVertexId}`,
                port: `node-${edge.targetVertexId}-left`
              },
              zIndex: zIndex++
            })
            const input = vertexs.find((item) => item.vertexId === Number(edge.inputVertexId))
            if (input && !processed.includes(input)) {
              row.push(input)
              processed.push(input)
            }
            const target = vertexs.find((item) => item.vertexId === Number(edge.targetVertexId))
            if (target && !processed.includes(target)) {
              row.push(target)
              processed.push(target)
            }
          }
        }
        matrix.forEach((row) => {
          row.sort((a, b) => {
            if (a.type === 'source') {
              return -1
            } else if (b.type === 'sink') {
              return 1
            } else {
              return 0
            }
          })
        })
        type Port = { id: string; group: string }
        matrix.forEach((row, rowNumber) => {
          row.forEach((item, colNumber) => {
            const data: NodeStatus = {
              id: item.vertexId,
              label: item.vertexName,
              status: props?.job?.jobStatus
            }
            const id = 'node-' + item.vertexId
            const ports = [] as Port[]
            if (colNumber !== 0) {
              ports.push({
                id: `${id}-left`,
                group: 'left'
              })
            }
            if (colNumber !== row.length - 1) {
              ports.push({
                id: `${id}-right`,
                group: 'right'
              })
            }
            items.push({
              id,
              shape: 'dag-node',
              x: colNumber * offsetX,
              y: rowNumber * offsetY,
              data,
              ports
            })
          })
        })

        const cells: Cell[] = []
        items.forEach((item) => {
          if (item.shape === 'dag-node') {
            cells.push(graph.createNode(item))
          } else {
            cells.push(graph.createEdge(item))
          }
        })
        graph.resetCells(cells)
      }

      // 显示节点状态
      const showNodeStatus = async (statusList: NodeStatus[][]) => {
        const status = statusList[Math.floor(Math.random() * statusList.length)]
        status?.forEach((item) => {
          const { id, status } = item
          const node = graph.getCellById(`node-${id}`)
          const data = node.getData() as NodeStatus
          node.setData({
            ...data,
            status
          })
        })
        if (!status) return
        setTimeout(() => {
          showNodeStatus(statusList)
        }, 5000)
      }

      setTimeout(() => {
        init()
        graph.centerContent()
      }, 500)
    })

    return () => <div id="container" style="height: 600px" />
  }