|
@@ -8,6 +8,7 @@
|
|
|
<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"
|
|
@@ -47,19 +48,10 @@
|
|
|
<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";
|
|
|
|
|
|
-type Node = {
|
|
|
- id: string
|
|
|
- type: string
|
|
|
- x: number
|
|
|
- y: number
|
|
|
- w: number
|
|
|
- h: number
|
|
|
-}
|
|
|
-type Line = {
|
|
|
- source: string
|
|
|
- target: string
|
|
|
-}
|
|
|
|
|
|
const {proxy} = getCurrentInstance()
|
|
|
const markerStyle = {
|
|
@@ -71,59 +63,158 @@ const state: any = reactive({
|
|
|
nodes: [
|
|
|
{
|
|
|
id: '8facce0d-c5ff-42ba-b6a0-6a920510c794',
|
|
|
- type: 'root',
|
|
|
+ type: 'NodeRoot',
|
|
|
x: 0,
|
|
|
y: 0,
|
|
|
- w: 240,
|
|
|
- h: 50,
|
|
|
},
|
|
|
{
|
|
|
id: 'f001c786-c4a0-402f-a79d-19456f9346a6',
|
|
|
- type: 'type-1',
|
|
|
+ type: 'NodeIf',
|
|
|
x: 300,
|
|
|
y: 0,
|
|
|
- w: 240,
|
|
|
- h: 100,
|
|
|
+ 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: 'type-1',
|
|
|
+ type: 'NodeSwitch',
|
|
|
x: 300,
|
|
|
y: 200,
|
|
|
- w: 240,
|
|
|
- h: 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 Node[],
|
|
|
+ ] as NodeDef[],
|
|
|
lines: [
|
|
|
- {source: '8facce0d-c5ff-42ba-b6a0-6a920510c794', target: 'f001c786-c4a0-402f-a79d-19456f9346a6'},
|
|
|
- {source: '8facce0d-c5ff-42ba-b6a0-6a920510c794', target: 'e7dacb7d-8505-4bf7-abae-91e81d27106e'},
|
|
|
- ] as Line[]
|
|
|
+ {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(() => {
|
|
|
- let maxW = 0
|
|
|
- let minW = 0
|
|
|
- let maxH = 0
|
|
|
- let minH = 0
|
|
|
- state.nodes.forEach((v: Node) => {
|
|
|
- if (v.x < minW) {
|
|
|
- minW = v.x
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
- if (v.x + v.w > maxW) {
|
|
|
- maxW = v.x + v.w
|
|
|
+ return {
|
|
|
+ width: maxW - minW - 40,
|
|
|
+ height: maxH - minH,
|
|
|
+ left: minW - 40,
|
|
|
+ top: minH
|
|
|
}
|
|
|
- if (v.y < minH) {
|
|
|
- minH = v.y
|
|
|
- }
|
|
|
- if (v.y + v.h > maxH) {
|
|
|
- maxH = v.y + v.h
|
|
|
- }
|
|
|
- })
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ }
|
|
|
return {
|
|
|
- width: maxW - minW - 40,
|
|
|
- height: maxH - minH,
|
|
|
- left: minW - 40,
|
|
|
- top: minH
|
|
|
+ width: 0,
|
|
|
+ height: 0,
|
|
|
+ left: 0,
|
|
|
+ top: 0
|
|
|
}
|
|
|
})
|
|
|
const moveStart = (e) => {
|
|
@@ -131,11 +222,11 @@ const moveStart = (e) => {
|
|
|
}
|
|
|
const move = (e) => {
|
|
|
if (state.moving) {
|
|
|
- const dom = ref_chart.value
|
|
|
- const x = dom.style.left ? Number(dom.style.left.replace('px', '')) : 0
|
|
|
- const y = dom.style.top ? Number(dom.style.top.replace('px', '')) : 0
|
|
|
- dom.style.left = `${x + e.movementX}px`
|
|
|
- dom.style.top = `${y + e.movementY}px`
|
|
|
+ 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) => {
|
|
@@ -143,20 +234,31 @@ const moveEnd = (e) => {
|
|
|
}
|
|
|
// 计算连线路径
|
|
|
const getPath = (line) => {
|
|
|
- const sourceNode = state.nodes.find(node => node.id === line.source);
|
|
|
- const targetNode = state.nodes.find(node => node.id === line.target);
|
|
|
- const startX = sourceNode.x + sourceNode.w - offsetStyleCpt.value.left
|
|
|
- const startY = sourceNode.y + sourceNode.h / 2 - offsetStyleCpt.value.top;
|
|
|
- const endX = targetNode.x - offsetStyleCpt.value.left - markerStyle.width;
|
|
|
- const endY = targetNode.y + targetNode.h / 2 - offsetStyleCpt.value.top;
|
|
|
- // 调整控制点位置,让连线起点和终点保持距离再弯曲
|
|
|
- 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}`;
|
|
|
+ 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(() => {
|
|
@@ -166,7 +268,7 @@ onMounted(() => {
|
|
|
<style lang="scss" scoped>
|
|
|
.chart {
|
|
|
position: relative;
|
|
|
- width: 800px;
|
|
|
+ width: 1400px;
|
|
|
height: 800px;
|
|
|
overflow: hidden;
|
|
|
background-color: #f2f4f7;
|