169 lines
4.6 KiB
Vue
169 lines
4.6 KiB
Vue
<template>
|
|
<div class="row justify-center">
|
|
<svg class="node-line" style="width:100%" :viewBox="viewBox()">
|
|
<template v-if="!node.outputPoints || node.outputPoints.length===0" >
|
|
<polyline :points="points(getMode('')).linePoints" class="line" ></polyline>
|
|
<text class="add-icon"
|
|
@click="addNode(node,'')"
|
|
:x="points(getMode('')).iconPoint.x"
|
|
:y="points(getMode('')).iconPoint.y"
|
|
font-family="Arial" font-size="25"
|
|
text-anchor="middle" dy=".3em" style="cursor: pointer;" >
|
|
⊕
|
|
</text>
|
|
</template>
|
|
<template v-for="(point, index) in node.outputPoints" :key="index" >
|
|
<polyline :points="points(getMode(point)).linePoints" class="line" ></polyline>
|
|
<text class="add-icon"
|
|
@click="addNode(node,point)"
|
|
:x="points(getMode(point)).iconPoint.x"
|
|
:y="points(getMode(point)).iconPoint.y"
|
|
font-family="Arial" font-size="25"
|
|
text-anchor="middle" dy=".3em" style="cursor: pointer;" >
|
|
⊕
|
|
</text>
|
|
</template>
|
|
</svg>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { ref, defineComponent, computed, PropType } from 'vue';
|
|
import { IActionNode, ActionNode, ActionFlow, RootAction } from '../../types/ActionTypes';
|
|
export enum Direction {
|
|
Default = "None",
|
|
Left = "LEFT",
|
|
Right = "RIGHT",
|
|
LeftNotNext = "LEFTNOTNEXT",
|
|
RightNotNext = "RIGHTNOTNEXT",
|
|
}
|
|
export default defineComponent({
|
|
name: 'NodeLine',
|
|
props: {
|
|
actionNode: {
|
|
type: Object as PropType<IActionNode>,
|
|
required: true
|
|
},
|
|
leftColumns:{
|
|
type:Number,
|
|
required:false
|
|
},
|
|
rightColumns:{
|
|
type:Number,
|
|
required:false
|
|
}
|
|
},
|
|
emits: ['addNode'],
|
|
setup(props,context) {
|
|
const hasBranch = computed(() => props.actionNode.outputPoints.length > 0);
|
|
const getMode = (point: string):Direction => {
|
|
if (point === '' || props.actionNode.outputPoints.length === 0) {
|
|
return Direction.Default;
|
|
}
|
|
if (point === props.actionNode.outputPoints[0]) {
|
|
if (props.actionNode.nextNodeIds.get(point)) {
|
|
return Direction.Left;
|
|
} else {
|
|
return Direction.LeftNotNext;
|
|
}
|
|
} else {
|
|
if (props.actionNode.nextNodeIds.get(point)) {
|
|
return Direction.Right;
|
|
} else {
|
|
return Direction.RightNotNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
const points = (mode:Direction) => {
|
|
let startX ,endX;
|
|
const leftColumn=props.leftColumns?props.leftColumns:1;
|
|
const rightColumn=props.rightColumns?props.rightColumns:1;
|
|
|
|
switch (mode) {
|
|
case Direction.Left:
|
|
startX = leftColumn*300/2.0;
|
|
endX = ((leftColumn+rightColumn)/2.0 - 0.25)*300;
|
|
return {
|
|
linePoints: `${startX}, 60, ${startX}, 40, ${endX}, 40, ${endX}, 0`,
|
|
iconPoint: { x: endX, y: 20 }
|
|
};
|
|
case Direction.Right:
|
|
startX = ((leftColumn+rightColumn)/2.0 + 0.25)*300;
|
|
endX = (leftColumn+(rightColumn/2.0))*300;
|
|
return {
|
|
linePoints: `${startX}, 0, ${startX}, 40, ${endX}, 40, ${endX}, 60`,
|
|
iconPoint: { x: startX, y: 20 }
|
|
};
|
|
case Direction.LeftNotNext:
|
|
startX = ((leftColumn+rightColumn)/2.0 - 0.25)*300;
|
|
return {
|
|
linePoints: `${startX}, 0, ${startX}, 40`,
|
|
iconPoint: { x: startX, y: 20 }
|
|
};
|
|
case Direction.RightNotNext:
|
|
startX = ((leftColumn+rightColumn)/2.0 + 0.25)*300;
|
|
return {
|
|
linePoints: `${startX}, 0, ${startX}, 40`,
|
|
iconPoint: { x: startX, y: 20 }
|
|
};
|
|
default:
|
|
return {
|
|
linePoints: '150, 0, 150, 60',
|
|
iconPoint: { x: 150, y: 30 }
|
|
};
|
|
}
|
|
};
|
|
|
|
const addNode=(prveNode:IActionNode,point:string)=>{
|
|
context.emit('addNode',point);
|
|
}
|
|
|
|
const viewBox=()=>{
|
|
let columns=0;
|
|
if(props.leftColumns!==undefined) columns+=props.leftColumns;
|
|
if(props.rightColumns!==undefined) columns+=props.rightColumns;
|
|
if(columns===0) columns=1;
|
|
const width= columns*300;
|
|
return `0 0 ${width} 60`;
|
|
};
|
|
|
|
return {
|
|
node: props.actionNode,
|
|
getMode,
|
|
hasBranch,
|
|
points,
|
|
addNode,
|
|
viewBox
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
<style lang="scss">
|
|
.node-line {
|
|
height: 60px;
|
|
width: 240px;
|
|
}
|
|
|
|
.line {
|
|
stroke: $blue-7;
|
|
fill: none;
|
|
stroke-width: 2;
|
|
}
|
|
|
|
.add-icon {
|
|
stroke: $blue-8;
|
|
fill: $blue-8;
|
|
font-family: Arial;
|
|
pointer-events: all;
|
|
font-size: 2.0em;
|
|
}
|
|
|
|
.add-icon:hover{
|
|
stroke: $blue-8;
|
|
fill:$blue-8;
|
|
font-weight: bold;
|
|
font-size: 2.4em;
|
|
}
|
|
</style>
|