FlowEditor初期合体

This commit is contained in:
2023-09-08 14:28:45 +09:00
12 changed files with 832 additions and 8 deletions

View File

@@ -0,0 +1,107 @@
<template>
<div class="row justify-center" :style="{marginLeft:node.inputPoint!==''?'240px':''}">
<div class="row">
<q-card class="action-node" :class="{'root-node':node.isRoot,'text-white':node.isRoot}" :square="false">
<q-card-section>
<div class="text-h6">{{ node.title }}</div>
<div class="text-subtitle2">{{ node.subTitle }}</div>
</q-card-section>
<template v-if="hasBranch">
<q-separator />
<q-card-actions align="around">
<q-btn flat v-for="(point,index) in node.outputPoints" :key="index">
{{ point }}
</q-btn>
</q-card-actions>
</template>
</q-card>
</div>
</div>
<template v-if="hasBranch">
<div class="row justify-center" :style="{marginLeft:node.inputPoint!==''?'240px':''}">
<div v-for="(point,index) in node.outputPoints" :key="index">
<node-line :action-node="node" :mode="getMode(point)" @addNode="addNode" :input-point="point" ></node-line>
</div>
</div>
</template>
<template v-if="!hasBranch">
<div class="row justify-center" :style="{marginLeft:node.inputPoint!==''?'240px':''}">
<node-line :action-node="node" :mode="getMode('')" @addNode="addNode" input-point=""></node-line>
</div>
</template>
</template>
<script lang="ts">
import {defineComponent,computed} from 'vue';
import {IActionNode } from '../../types/ActionTypes';
import NodeLine,{Direction} from '../main/NodeLine.vue';
export default defineComponent({
name: 'NodeItem',
components: {
NodeLine
},
props: {
actionNode:{
type:Object as ()=>IActionNode,
required:true
}
},
emits: [
'addNode'
],
setup(props,context){
const hasBranch = computed(() => props.actionNode.outputPoints.length > 0);
const getMode =(point:string)=>{
if(point==='' || props.actionNode.outputPoints.length===0){
return Direction.Default;
}
if(point===props.actionNode.outputPoints[0]){
if(props.actionNode.nextNodes.get(point)){
return Direction.Left;
}else{
return Direction.LeftNotNext;
}
}else{
if(props.actionNode.nextNodes.get(point)){
return Direction.Right;
}else{
return Direction.RightNotNext;
}
}
}
const addNode=(point:string)=>{
context.emit('addNode',props.actionNode,point);
}
return {
node:props.actionNode,
hasBranch,
isRoot:props.actionNode.isRoot,
getMode,
addNode
}
}
});
</script>
<style lang="scss">
.action-node{
min-width:250px !important;
}
.line{
height:20px;
}
.line:after{
content:'';
background-color:$blue-7;
display:block;
width:3px;
}
.add-icon{
font-size: 2em;
color:$blue-7;
}
.root-node{
background-color:$blue-7;
border-radius: 20px;
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div>
<svg class="node-line">
<polyline :points="points.linePoints" class="line" ></polyline>
<text class="add-icon" @click="addNode(node)" :x="points.iconPoint.x" :y="points.iconPoint.y" font-family="Arial" font-size="25" text-anchor="middle" dy=".3em" style="cursor: pointer;" >
</text>
</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
},
mode: {
type: String as PropType<Direction>,
required: true
},
inputPoint:{
type:String
}
},
emits: ['addNode'],
setup(props,context) {
const hasBranch = computed(() => props.actionNode.outputPoints.length > 0);
const points = computed(() => {
switch (props.mode) {
case Direction.Left:
return {
linePoints: '180, 0, 180, 40, 120, 40, 120, 60',
iconPoint: { x: 180, y: 20 }
};
case Direction.Right:
return {
linePoints: '60, 0, 60, 40, 120, 40, 120, 60',
iconPoint: { x: 60, y: 20 }
};
case Direction.LeftNotNext:
return {
linePoints: '180, 0, 180, 40',
iconPoint: { x: 180, y: 20 }
};
case Direction.RightNotNext:
return {
linePoints: '60, 0, 60, 40',
iconPoint: { x: 60, y: 30 }
};
default:
return {
linePoints: '120, 0, 120, 60',
iconPoint: { x: 120, y: 30 }
};
}
});
const addNode=(prveNode:IActionNode)=>{
context.emit('addNode',props.inputPoint);
}
return {
node: props.actionNode,
hasBranch,
points,
addNode
}
}
});
</script>
<style lang="scss">
.node-line {
height: 60px;
width: 240px;
}
.line {
stroke: $blue-7;
fill: none;
stroke-width: 2;
}
.add-icon {
stroke: $blue-7;
fill: $blue-7;
font-family: Arial;
pointer-events: all;
}
</style>

View File

@@ -32,4 +32,3 @@ export interface AppInfo {
creator?:User;
modifier?:User;
}

View File

@@ -0,0 +1,57 @@
<template>
<div>
<div v-for="(item, index) in componentData" :key="index">
<component :is="item.component" v-bind="item.props" v-model="item.props.modelValue"></component>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import InputText from '../right/InputText.vue';
import SelectBox from '../right/SelectBox.vue';
import DatePicker from '../right/DatePicker.vue';
import FieldInput from '../right/FieldInput.vue';
export default defineComponent({
name: 'ActionProperty',
components: {
InputText,
SelectBox,
DatePicker,
FieldInput
},
props: {
jsonData: {
type: Object,
required: true,
},
jsonValue:{
type: Object,
required: false,
}
},
computed: {
componentData() {
return this.jsonData.elements.map((element: any) => {
if(this.jsonValue != undefined )
{
if(this.jsonValue.hasOwnProperty(element.props.name))
{
element.props.modelValue = this.jsonValue[element.props.name];
}
else
{
element.props.modelValue = '';
}
}
return {
component: element.component,
props: element.props,
};
});
},
},
});
</script>

View File

@@ -0,0 +1,45 @@
<template>
<q-input v-model="selectedDate" :label="placeholder" mask="date" :rules="['date']">
<template v-slot:append>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
<q-date v-model="selectedDate">
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</template>
<script lang="ts">
import { defineComponent, ref ,watchEffect} from 'vue';
export default defineComponent({
name: 'DatePicker',
props: {
placeholder: {
type: String,
default: '',
},
modelValue: {
type: String,
default: '',
},
},
setup(props, { emit }) {
const selectedDate = ref(props.modelValue);
watchEffect(() => {
emit('update:modelValue', selectedDate.value);
});
return {
selectedDate
};
}
});
</script>

View File

@@ -0,0 +1,62 @@
<template>
<q-input v-model="selectedField" :label="placeholder">
<template v-slot:append>
<q-icon name="search" class="cursor-pointer" @click="showDg"/>
</template>
</q-input>
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeDg">
<field-select ref="appDg" name="フィールド" type="single" :appId="1"></field-select>
</show-dialog>
</template>
<script lang="ts">
import { defineComponent, ref ,watchEffect} from 'vue';
import ShowDialog from '../ShowDialog.vue';
import FieldSelect from '../FieldSelect.vue';
export default defineComponent({
name: 'FieldInput',
components: {
ShowDialog,
FieldSelect,
},
props: {
placeholder: {
type: String,
default: '',
},
modelValue: {
type: String,
default: '',
},
},
setup(props, { emit }) {
const appDg = ref();
const show = ref(false);
const selectedField = ref(props.modelValue);
const showDg = () => {
show.value = true;
};
const closeDg = (val:string) => {
if (val == 'OK') {
selectedField.value = appDg.value.selected[0].name;
}
};
watchEffect(() => {
emit('update:modelValue', selectedField.value);
});
return {
appDg,
show,
showDg,
closeDg,
selectedField,
};
}
});
</script>

View File

@@ -0,0 +1,33 @@
<template>
<q-input :label="placeholder" v-model="inputValue"/>
</template>
<script lang="ts">
import { defineComponent,ref,watchEffect } from 'vue';
export default defineComponent({
name: 'InputText',
props: {
placeholder: {
type: String,
default: '',
},
modelValue: {
type: String,
default: '',
},
},
setup(props, { emit }) {
const inputValue = ref(props.modelValue);
watchEffect(() => {
emit('update:modelValue', inputValue.value);
});
return {
inputValue,
};
},
});
</script>

View File

@@ -0,0 +1,36 @@
<template>
<q-select v-model="selectedValue" :label="placeholder" :options="options"/>
</template>
<script lang="ts">
import { defineComponent,ref,watchEffect } from 'vue';
export default defineComponent({
name: 'SelectBox',
props: {
placeholder: {
type: String,
default: '',
},
options: {
type: Array,
required: true,
},
modelValue: {
type: String,
default: '',
},
},
setup(props, { emit }) {
const selectedValue = ref(props.modelValue);
watchEffect(() => {
emit('update:modelValue', selectedValue.value);
});
return {
selectedValue
};
},
});
</script>