|
@@ -1,291 +0,0 @@
|
|
|
-<template>
|
|
|
- <div class="chart"
|
|
|
- @mousedown="moveStart"
|
|
|
- @mousemove="move"
|
|
|
- @mouseup="moveEnd"
|
|
|
- @mouseleave="moveEnd"
|
|
|
- >
|
|
|
- <div class="chart-block" ref="ref_chart">
|
|
|
- <template v-for="n in state.nodes">
|
|
|
- <node
|
|
|
- :item="n"
|
|
|
- :type="n.type"
|
|
|
- v-model:x="n.x"
|
|
|
- v-model:y="n.y"
|
|
|
- v-model:w="n.w"
|
|
|
- v-model:h="n.h"
|
|
|
- />
|
|
|
- </template>
|
|
|
- <svg class="lines" :style="{width: offsetStyleCpt.width + 'px', height: offsetStyleCpt.height + 'px', left: offsetStyleCpt.left + 'px', top: offsetStyleCpt.top + 'px'}">
|
|
|
- <defs>
|
|
|
- <marker
|
|
|
- id="arrow"
|
|
|
- :viewBox="`0 0 ${markerStyle.width} ${markerStyle.width}`"
|
|
|
- :refX="0"
|
|
|
- :refY="markerStyle.height"
|
|
|
- :markerWidth="markerStyle.width"
|
|
|
- :markerHeight="markerStyle.height"
|
|
|
- orient="auto-start-reverse"
|
|
|
- >
|
|
|
- <path :d="`M 0 0 L ${markerStyle.width} ${markerStyle.height} L 0 ${markerStyle.width} z`" fill="#d0d5dc" />
|
|
|
- </marker>
|
|
|
- </defs>
|
|
|
- <!-- 绘制曲线连线 -->
|
|
|
- <path
|
|
|
- v-for="(line, index) in state.lines"
|
|
|
- :key="index"
|
|
|
- :d="getPath(line)"
|
|
|
- stroke="#d0d5dc"
|
|
|
- stroke-width="2"
|
|
|
- fill="none"
|
|
|
- marker-end="url(#arrow)"
|
|
|
- />
|
|
|
- </svg>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang="ts">
|
|
|
-import {computed, getCurrentInstance, onMounted, reactive, ref} from "vue";
|
|
|
-import node from '../node/index.vue'
|
|
|
-import {LineDef, NodeDef} from "@/views/draw/config/types";
|
|
|
-import {nodeStyleConfig} from "@/views/draw/config/config";
|
|
|
-import {IfLevelsCondition} from "@/views/draw/node/component/if/type";
|
|
|
-
|
|
|
-
|
|
|
-const {proxy} = getCurrentInstance()
|
|
|
-const markerStyle = {
|
|
|
- width: 10,
|
|
|
- height: 5,
|
|
|
-}
|
|
|
-const state: any = reactive({
|
|
|
- moving: false,
|
|
|
- nodes: [
|
|
|
- {
|
|
|
- id: '8facce0d-c5ff-42ba-b6a0-6a920510c794',
|
|
|
- type: 'NodeRoot',
|
|
|
- x: 0,
|
|
|
- y: 0,
|
|
|
- },
|
|
|
- {
|
|
|
- id: 'f001c786-c4a0-402f-a79d-19456f9346a6',
|
|
|
- type: 'NodeIf',
|
|
|
- x: 300,
|
|
|
- y: 0,
|
|
|
- data: {
|
|
|
- title: '条件分支1',
|
|
|
- levels: [
|
|
|
- {
|
|
|
- id: '418af28e-8799-45f3-8c26-29bbbad37cbf',
|
|
|
- method: 'AND',
|
|
|
- conditions: [
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: 'b812382b-f1bd-4539-a8a3-0efc875107f9',
|
|
|
- method: 'OR',
|
|
|
- conditions: [
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: '883881a6-d993-4f5f-ba4f-f382cda4395c',
|
|
|
- method: 'AND',
|
|
|
- conditions: [
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- {
|
|
|
- source: 'asd',
|
|
|
- to: 'zxc',
|
|
|
- target: 'qwe',
|
|
|
- targetType: 'value'
|
|
|
- },
|
|
|
- ]
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- id: 'e7dacb7d-8505-4bf7-abae-91e81d27106e',
|
|
|
- type: 'NodeSwitch',
|
|
|
- x: 300,
|
|
|
- y: 200,
|
|
|
- },
|
|
|
- {
|
|
|
- id: '329dd688-461d-4dec-af1e-80685b135e27',
|
|
|
- type: 'NodeFor',
|
|
|
- x: 600,
|
|
|
- y: 200,
|
|
|
- },
|
|
|
- {
|
|
|
- id: 'e3c9c844-4333-4d0d-9fad-b952f7f04496',
|
|
|
- type: 'NodeFor',
|
|
|
- x: 600,
|
|
|
- y: 400,
|
|
|
- }
|
|
|
- ] as NodeDef[],
|
|
|
- lines: [
|
|
|
- {source: '8facce0d-c5ff-42ba-b6a0-6a920510c794', target: 'f001c786-c4a0-402f-a79d-19456f9346a6', type: 'NODE'},
|
|
|
- {source: '8facce0d-c5ff-42ba-b6a0-6a920510c794', target: 'e7dacb7d-8505-4bf7-abae-91e81d27106e', type: 'NODE'},
|
|
|
- {source: 'e7dacb7d-8505-4bf7-abae-91e81d27106e', target: '329dd688-461d-4dec-af1e-80685b135e27', type: 'NODE'},
|
|
|
- {source: 'b812382b-f1bd-4539-a8a3-0efc875107f9', target: 'e3c9c844-4333-4d0d-9fad-b952f7f04496', type: 'LEVEL'},
|
|
|
- ] as LineDef[]
|
|
|
-})
|
|
|
-const ref_chart = ref()
|
|
|
-const offsetStyleCpt = computed(() => {
|
|
|
- try {
|
|
|
- let maxW = 0
|
|
|
- let minW = 0
|
|
|
- let maxH = 0
|
|
|
- let minH = 0
|
|
|
- const chart = ref_chart.value
|
|
|
- if (chart) {
|
|
|
- state.nodes.forEach((v: NodeDef) => {
|
|
|
- const dom = chart.querySelector(`#NODE_${v.id}`)
|
|
|
- if (v.x < minW) {
|
|
|
- minW = v.x
|
|
|
- }
|
|
|
- if (v.x + dom.clientWidth > maxW) {
|
|
|
- maxW = v.x + dom.clientWidth
|
|
|
- }
|
|
|
- if (v.y < minH) {
|
|
|
- minH = v.y
|
|
|
- }
|
|
|
- if (v.y + dom.clientHeight > maxH) {
|
|
|
- maxH = v.y + dom.clientHeight
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- return {
|
|
|
- width: maxW - minW - 40,
|
|
|
- height: maxH - minH,
|
|
|
- left: minW - 40,
|
|
|
- top: minH
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.log(e)
|
|
|
- }
|
|
|
- return {
|
|
|
- width: 0,
|
|
|
- height: 0,
|
|
|
- left: 0,
|
|
|
- top: 0
|
|
|
- }
|
|
|
-})
|
|
|
-const moveStart = (e) => {
|
|
|
- state.moving = true
|
|
|
-}
|
|
|
-const move = (e) => {
|
|
|
- if (state.moving) {
|
|
|
- const chart = ref_chart.value
|
|
|
- const x = chart.style.left ? Number(chart.style.left.replace('px', '')) : 0
|
|
|
- const y = chart.style.top ? Number(chart.style.top.replace('px', '')) : 0
|
|
|
- chart.style.left = `${x + e.movementX}px`
|
|
|
- chart.style.top = `${y + e.movementY}px`
|
|
|
- }
|
|
|
-}
|
|
|
-const moveEnd = (e) => {
|
|
|
- state.moving = false
|
|
|
-}
|
|
|
-// 计算连线路径
|
|
|
-const getPath = (line) => {
|
|
|
- const chart = ref_chart.value
|
|
|
- if (chart) {
|
|
|
- const sourceNode = chart.querySelector(`#${line.type}_${line.source}`)
|
|
|
- const targetNode = chart.querySelector(`#NODE_${line.target}`)
|
|
|
- let startX
|
|
|
- let startY
|
|
|
- if (line.type === 'NODE') {
|
|
|
- startX = Number(sourceNode.getAttribute('x')) + sourceNode.clientWidth - offsetStyleCpt.value.left + nodeStyleConfig.nodeBorderWidth
|
|
|
- startY = Number(sourceNode.getAttribute('y')) + nodeStyleConfig.titleHeight / 2 - offsetStyleCpt.value.top + nodeStyleConfig.nodeBorderWidth
|
|
|
- } else if (line.type === 'LEVEL') {
|
|
|
- const node = chart.querySelector(`#NODE_${sourceNode.getAttribute('node-id')}`)
|
|
|
- startX = Number(node.getAttribute('x')) + node.clientWidth - offsetStyleCpt.value.left + nodeStyleConfig.nodeBorderWidth
|
|
|
- startY = Number(node.getAttribute('y')) + sourceNode.offsetTop + nodeStyleConfig.nodeBorderWidth + nodeStyleConfig.lineOperationRadius + 2
|
|
|
- }
|
|
|
- const endX = Number(targetNode.getAttribute('x')) - offsetStyleCpt.value.left - markerStyle.width;
|
|
|
- const endY = Number(targetNode.getAttribute('y')) - offsetStyleCpt.value.top + nodeStyleConfig.titleHeight / 2 + nodeStyleConfig.nodeBorderWidth
|
|
|
- // 调整控制点位置,让连线起点和终点保持距离再弯曲
|
|
|
- const offset = 50
|
|
|
- const controlX1 = startX + offset
|
|
|
- const controlY1 = startY
|
|
|
- const controlX2 = endX - offset
|
|
|
- const controlY2 = endY
|
|
|
- return `M ${startX} ${startY} C ${controlX1} ${controlY1} ${controlX2} ${controlY2} ${endX} ${endY}`
|
|
|
- }
|
|
|
- return ''
|
|
|
-};
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.chart {
|
|
|
- position: relative;
|
|
|
- width: 1400px;
|
|
|
- height: 800px;
|
|
|
- overflow: hidden;
|
|
|
- background-color: #f2f4f7;
|
|
|
- .chart-block {
|
|
|
- position: absolute;
|
|
|
- }
|
|
|
-}
|
|
|
-.lines {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- pointer-events: none;
|
|
|
- z-index: 0;
|
|
|
- marker {
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|