From 3229f6a34f4982d1a551d86e68d313482e33f701 Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期三, 11 十二月 2024 14:37:43 +0800
Subject: [PATCH] 条件节点

---
 src/components/vue-flow/ui/nodes/EndNode.vue       |    4 
 src/components/vue-flow/VueFlowHelper.ts           |  116 ++++++++++++
 src/components/vue-flow/VueFlowConstant.ts         |    3 
 src/components/vue-flow/ui/nodes/ConditionNode.vue |  284 +++++++++++++++++++++++++++++++
 src/components/vue-flow/ui/edges/CustomEdge.vue    |   23 ++
 src/components/vue-flow/MainCanvas.vue             |   19 +
 src/components/vue-flow/vueFlowEnum.ts             |   40 ++++
 src/components/vue-flow/ui/nodes/StartNode.vue     |   34 ++-
 8 files changed, 495 insertions(+), 28 deletions(-)

diff --git a/src/components/vue-flow/MainCanvas.vue b/src/components/vue-flow/MainCanvas.vue
index 203aeda..ad45f8d 100644
--- a/src/components/vue-flow/MainCanvas.vue
+++ b/src/components/vue-flow/MainCanvas.vue
@@ -1,6 +1,9 @@
 <template>
 	<div class="relative h-full w-full" id="main-canvas" @drop="handleOnDrop" @dragover="handleOnDragOver">
 		<VueFlow v-model="elements" :node-types="nodeTypes" :connection-mode="ConnectionMode.Loose">
+			<template #edge-custom="customEdgeProps">
+				<CustomEdge v-bind="customEdgeProps" />
+			</template>
 			<Controls />
 			<Background />
 		</VueFlow>
@@ -10,16 +13,19 @@
 <script setup lang="ts">
 import { Background } from '@vue-flow/background';
 import { Controls } from '@vue-flow/controls';
-import { Dimensions, Elements, useVueFlow, VueFlow, ConnectionMode } from '@vue-flow/core';
+import { Dimensions, Elements, useVueFlow, VueFlow, ConnectionMode, MarkerType } from '@vue-flow/core';
 import { markRaw, nextTick, ref, watch } from 'vue';
 import { Test_data } from './testData';
 import StartNode from './ui/nodes/StartNode.vue';
 import EndNode from './ui/nodes/EndNode.vue';
 import { VueFlowHelper } from './VueFlowHelper';
 import { NodeType, nodeTypeMap } from './vueFlowEnum';
+import ConditionNode from './ui/nodes/ConditionNode.vue';
+import CustomEdge from './ui/edges/CustomEdge.vue';
 const nodeTypes = {
 	start: markRaw(StartNode),
 	end: markRaw(EndNode),
+	condition: markRaw(ConditionNode),
 	// LLM: markRaw(LLMNode),
 	// code: markRaw(CodeNode),
 	// knowledge: markRaw(KnowledgeNode),
@@ -31,18 +37,14 @@
 		{
 			id: '1',
 			type: 'start',
-			data: {
-				title: '寮�濮�',
-			},
+			data: VueFlowHelper.getDefaultData(NodeType.Start),
 
 			position: { x: 25, y: 400 },
 		},
 		{
 			id: '2',
 			type: 'end',
-			data: {
-				title: '缁撴潫',
-			},
+			data: VueFlowHelper.getDefaultData(NodeType.End),
 			position: { x: 1000, y: 400 },
 		},
 	],
@@ -56,6 +58,7 @@
 });
 
 onConnect((params) => {
+
 	addEdges(params);
 });
 
@@ -78,7 +81,7 @@
 	});
 
 	const newNode = {
-		id: (nodes.value.length + 1).toString(),
+		id: VueFlowHelper.genGeometryId(),
 		type,
 		position,
 		label: nodeTypeMap[type],
diff --git a/src/components/vue-flow/VueFlowConstant.ts b/src/components/vue-flow/VueFlowConstant.ts
index 85d8d86..fcea352 100644
--- a/src/components/vue-flow/VueFlowConstant.ts
+++ b/src/components/vue-flow/VueFlowConstant.ts
@@ -1,3 +1,4 @@
 export class VueFlowConstant {
-    static PARAMS_KEY = 'input';
+    static GROUP_PARAMS_KEY = 'group_params';
+    static PARAMS_KEY = 'params'
 }
\ No newline at end of file
diff --git a/src/components/vue-flow/VueFlowHelper.ts b/src/components/vue-flow/VueFlowHelper.ts
index 79671ec..cbb0d0e 100644
--- a/src/components/vue-flow/VueFlowHelper.ts
+++ b/src/components/vue-flow/VueFlowHelper.ts
@@ -1,15 +1,51 @@
-import { HandleType, Position } from '@vue-flow/core';
-import { NodeType, nodeTypeMap } from './vueFlowEnum';
+import { HandleType } from '@vue-flow/core';
+import { v4 as uuid } from 'uuid';
+import { VueFlowConstant } from './VueFlowConstant';
+import { CompareOperation, ConditionOperator, NodeType, VarType, nodeTypeMap } from './vueFlowEnum';
+import { get } from 'lodash';
 
 export class VueFlowHelper {
+	static genId() {
+		return uuid().slice(0, 8);
+	}
+
+	static genGeometryId(){
+		return uuid().slice(0, 12);
+	}
+
 	static getDefaultData = (type: NodeType) => {
 		let data: any = {
 			title: nodeTypeMap[type],
 		};
 		switch (type) {
 			case NodeType.Start:
+				data[VueFlowConstant.GROUP_PARAMS_KEY] = [
+					{
+						[VueFlowConstant.PARAMS_KEY]: [
+							{
+								key: 'var_list',
+								label: '',
+								type: 'var_list',
+								value: [],
+							},
+						],
+					},
+				];
 				break;
-
+			case NodeType.Condition:
+				data[VueFlowConstant.GROUP_PARAMS_KEY] = [
+					{
+						[VueFlowConstant.PARAMS_KEY]: [
+							{
+								key: 'condition',
+								label: '',
+								type: 'condition',
+								value: [ConditionHelper.getDefaultConditionGroup()],
+							},
+						],
+					},
+				];
+				break;
 			default:
 				break;
 		}
@@ -20,4 +56,78 @@
 		const orderSuffix = order == undefined ? '' : `__${order + ''}`;
 		return `${node.id}__handle-${handleType}${orderSuffix}`;
 	};
+
+	static getFieldValue = (data, key, index = 0) => {
+		let varList = [];
+		const group = data?.[VueFlowConstant.GROUP_PARAMS_KEY];
+		if (group && group.length > 0) {
+			if (index !== null) {
+				const val = group?.[index]?.[VueFlowConstant.PARAMS_KEY]?.find((item) => item.key === key)?.value;
+				if (val) {
+					varList.push(val);
+				}
+			} else {
+				for (const item of group) {
+					if (item[VueFlowConstant.PARAMS_KEY].key === key) {
+						varList.push(item[VueFlowConstant.PARAMS_KEY].value);
+					}
+				}
+			}
+		}
+		if (varList.length === 0) {
+			return null;
+		} else if (varList.length === 1) {
+			return varList[0];
+		} else {
+			return varList;
+		}
+	};
+}
+
+export class StartNodeHelper {
+	// static getDefaultData = () => {
+	// 	return {
+	// 		title: nodeTypeMap[NodeType.Start],
+	// 	};
+	// };
+
+	static getVarList = (data) => {
+		const varList = data[VueFlowConstant.GROUP_PARAMS_KEY][0][VueFlowConstant.PARAMS_KEY].find(
+			(item) => item.key === 'condition'
+		).value;
+		return varList;
+	};
+}
+
+export class ConditionHelper {
+	static getConditionItem = (
+		left?: {
+			var: string;
+			label: string;
+		},
+		right?: {
+			type: VarType;
+			value: string;
+			label: string;
+		},
+		operation?: CompareOperation
+	) => {
+		return {
+			id: VueFlowHelper.genId(),
+			left_var: left?.var ?? '',
+			left_label: left?.label ?? '',
+			comparison_operation: operation ?? '',
+			right_value_type: right?.type ?? VarType.Input,
+			right_value: right?.value ?? '',
+			right_label: right?.label ?? '',
+		};
+	};
+
+	static getDefaultConditionGroup = () => {
+		return {
+			id: VueFlowHelper.genId(),
+			operator: ConditionOperator.And,
+			conditions: [],
+		};
+	};
 }
diff --git a/src/components/vue-flow/ui/edges/CustomEdge.vue b/src/components/vue-flow/ui/edges/CustomEdge.vue
new file mode 100644
index 0000000..5f3765a
--- /dev/null
+++ b/src/components/vue-flow/ui/edges/CustomEdge.vue
@@ -0,0 +1,23 @@
+<script setup lang="ts">
+import { BezierEdge } from '@vue-flow/core';
+
+// props were passed from the slot using `v-bind="customEdgeProps"`
+const props = defineProps(['sourceX', 'sourceY', 'targetX', 'targetY', 'sourcePosition', 'targetPosition']);
+</script>
+
+<script lang="ts">
+export default {
+	name: 'CustomEdge',
+};
+</script>
+
+<template>
+	<BezierEdge
+		:source-x="sourceX"
+		:source-y="sourceY"
+		:target-x="targetX"
+		:target-y="targetY"
+		:source-position="sourcePosition"
+		:target-position="targetPosition"
+	/>
+</template>
diff --git a/src/components/vue-flow/ui/nodes/ConditionNode.vue b/src/components/vue-flow/ui/nodes/ConditionNode.vue
new file mode 100644
index 0000000..6513543
--- /dev/null
+++ b/src/components/vue-flow/ui/nodes/ConditionNode.vue
@@ -0,0 +1,284 @@
+<template>
+	<div
+		class="w-max-[520px] border-2 rounded-lg border-solid border-gray-100 bg-white p-3 shadow-md relative hover:border-blue-500 group"
+	>
+		<Handle :id="leftId" type="target" :position="Position.Left" />
+		<div
+			class="group-hover:visible invisible flex absolute divide-y-[1.5px] divide-solid divide-gray-100 rounded-lg right-0 -top-0.5 translate-y-[-100%]"
+			style="box-shadow: 0 0 15px #dbdee6"
+		>
+			<el-tooltip effect="dark" content="澶嶅埗" placement="top">
+				<div
+					class="flex content-center items-center border-x-0 p-1 hover:bg-gray-200 active:bg-gray-300 cursor-pointer"
+					@click="handleClickDuplicateBtn"
+				>
+					<span class="ywifont !text-[20px] mb-1 p-1.5 ywicon-copy"></span>
+				</div>
+			</el-tooltip>
+			<el-tooltip effect="dark" content="鍒犻櫎" placement="top">
+				<div
+					@click="clickDeleteBtn"
+					class="flex content-center items-center border-x-0 p-1 hover:bg-gray-200 active:bg-gray-300 hover:text-red-400 cursor-pointer"
+				>
+					<span class="ywifont !text-[20px] mb-1 p-1.5 ywicon-shanchu"></span>
+				</div>
+			</el-tooltip>
+		</div>
+		<div class="flex flex-col gap-y-2 min-w-[400px]">
+			<div class="flex justify-between flex-0">
+				<div class="flex items-center gap-x-2">
+					<img src="/@/components/vue-flow/ui/assets/images/icon_Start.png" class="h-4 w-4" alt="Start icon" />
+					<div class="flex flex-col gap-y-1">
+						<p v-if="!titleIsEdit" class="text-xl font-bold text-gray-500" @click="titleIsEdit = true">{{ data.title }}</p>
+						<el-input v-else v-model="data.title" @blur="() => (titleIsEdit = false)"></el-input>
+					</div>
+				</div>
+			</div>
+
+			<div class="flex-auto gap-y-2 flex-col flex nodrag">
+				<div v-for="(item, index) in conditionGroupList" class="flex-column gap-3 relative group/conditionGroup">
+					<div class="flex-items-center justify-between">
+						<div class="text-lg font-bold">濡傛灉</div>
+						<div class="flex-items-center gap-3">
+							<el-select v-model="item.operator" class="w-[130px]">
+								<el-option
+									v-for="item in Object.keys(conditionOperatorMap)"
+									:key="item"
+									:value="item"
+									:label="conditionOperatorMap[item]"
+								></el-option>
+							</el-select>
+							<!-- v-if="conditionGroupList.length > 1" -->
+
+							<span
+								class="ywifont ywicon-shanchu text-red-400 invisible group-hover/conditionGroup:visible cursor-pointer"
+								@click="delConditionBranch(index)"
+							></span>
+						</div>
+					</div>
+
+					<div class="flex-column gap-y-2">
+						<div v-for="(subItem, subIndex) in item.conditions" class="ml-5 flex-items-center gap-x-2 group/conditionItem">
+							<el-tree-select
+								filterable
+								class="w-[120px] flex-0"
+								v-model="subItem.left_var"
+								:data="treeReferOptions"
+								node-key="id"
+								:clearable="true"
+								:accordion="false"
+								:expandNode="false"
+								:check-strictly="false"
+								placeholder="閫夋嫨鍙橀噺"
+							>
+							</el-tree-select>
+							<el-select v-model="subItem.comparison_operation" class="flex-0 w-[120px]" placeholder="閫夋嫨鏉′欢">
+								<el-option
+									v-for="item in Object.keys(compareOperationMap)"
+									:key="item"
+									:value="item"
+									:label="compareOperationMap[item]"
+								></el-option>
+							</el-select>
+
+							<el-select v-model="subItem.right_value_type" class="flex-0 w-[90px]" placeholder="璇烽�夋嫨">
+								<el-option v-for="item in Object.keys(varTypeMap)" :key="item" :value="item" :label="varTypeMap[item]"></el-option>
+							</el-select>
+
+							<el-input
+								v-if="subItem.right_value_type === VarType.Input"
+								v-model="subItem.right_value"
+								class="w-[120px]"
+								placeholder="杈撳叆鍊�"
+							>
+							</el-input>
+
+							<el-tree-select
+								v-else
+								filterable
+								class="w-[120px] flex-0"
+								v-model="subItem.right_value"
+								:data="treeReferOptions"
+								node-key="id"
+								:clearable="true"
+								:accordion="false"
+								:expandNode="false"
+								:check-strictly="false"
+								placeholder="閫夋嫨鍙橀噺"
+							>
+							</el-tree-select>
+
+							<span
+								class="ywifont ywicon-shanchu text-red-400 invisible group-hover/conditionItem:visible cursor-pointer"
+								@click="delConditionItem(item, subIndex)"
+							></span>
+						</div>
+						<el-button class="w-fit mt-3" type="primary" @click="addConditionItem(item)">娣诲姞鏉′欢</el-button>
+					</div>
+					<Handle :id="item.id" type="source" :position="Position.Right" />
+				</div>
+
+				<div class="flex-column gap-3 relative">
+					<div class="flex-items-center justify-between">
+						<div class="text-lg font-bold">鍚﹀垯</div>
+						<!-- <el-select class="w-[130px]">
+							<el-option
+								v-for="item in Object.keys(conditionOperatorMap)"
+								:key="item"
+								:value="parseInt(item)"
+								:label="conditionOperatorMap[item]"
+							></el-option>
+						</el-select> -->
+					</div>
+
+					<div class="flex-column">
+						<el-button @click="addConditionBranch" class="w-fit mt-3" type="success">娣诲姞鍒嗘敮</el-button>
+					</div>
+					<Handle :id="otherHandleId" type="source" :position="Position.Right" />
+				</div>
+			</div>
+		</div>
+		<!-- <Handle :id="handleId" type="source" :position="Position.Right" /> -->
+	</div>
+
+	<!-- <div>
+		<span>璧峰</span>
+
+		<Handle type="source" :position="Position.Right" />
+	</div> -->
+</template>
+
+<script lang="ts" setup>
+import { Handle, Position, useNode, useVueFlow } from '@vue-flow/core';
+import { ref, watchEffect } from 'vue';
+
+import type { NodeProps } from '@vue-flow/core';
+import { computed } from 'vue';
+import { VueFlowConstant } from '../../VueFlowConstant';
+import { ConditionHelper, VueFlowHelper } from '../../VueFlowHelper';
+import { compareOperationMap, VarType, conditionOperatorMap, varTypeMap } from '../../vueFlowEnum';
+import { LLMNodeData, LLMNodeEvents } from './index';
+import { deepClone } from '/@/utils/other';
+defineProps<NodeProps<LLMNodeData, LLMNodeEvents>>();
+
+const node = useNode();
+const leftId = VueFlowHelper.getHandleId(node, 'target');
+const { findNode } = useVueFlow();
+const referenceOptions = ref([]);
+const otherHandleId = VueFlowHelper.genId();
+const treeReferOptions = computed(() => {
+	const result = [];
+	for (const item of referenceOptions.value) {
+		result.push({
+			id: item.id,
+			label: item.groupName,
+			children: item.options.map((subItem, index) => {
+				return {
+					id: `${item.id}_${index}`,
+					label: subItem.label,
+					value: subItem.value,
+				};
+			}),
+		});
+	}
+	return result;
+});
+
+const travelConnectNode = (node, cb: Function) => {
+	if (node.connectedEdges && node.connectedEdges.value.length > 0) {
+		const filteredEdges = node.connectedEdges.value.filter((item) => item.target === node.id);
+		filteredEdges.map((edge) => {
+			const node = findNode(edge.source);
+			if (node) {
+				travelConnectNode(node, cb);
+				cb(node);
+			}
+		});
+	}
+};
+watchEffect(() => {
+	const result = [];
+	travelConnectNode(node, (item) => {
+		const currentItem = {
+			id: `option-${item.id}`,
+			groupName: item?.data.title ?? item?.label,
+			options: [],
+		};
+        const varList = VueFlowHelper.getFieldValue(item.data,'var_list');
+		if (varList) {
+			varList
+				.filter((item: any) => Boolean(item.name))
+				.forEach((option: any) => {
+					currentItem.options.push({
+						label: option.name,
+						value: option.name,
+					});
+				});
+		} else {
+			currentItem.options = [];
+		}
+		result.push(currentItem);
+	});
+	referenceOptions.value = result;
+});
+
+const data = ref(node.node.data);
+const conditionGroupList = ref(VueFlowHelper.getFieldValue(data.value,'condition'));
+const titleIsEdit = ref(false);
+
+function handleClickAddBtn() {
+	if (!data.value[VueFlowConstant.GROUP_PARAMS_KEY]) {
+		data.value[VueFlowConstant.GROUP_PARAMS_KEY] = [];
+	}
+
+	data.value[VueFlowConstant.GROUP_PARAMS_KEY].push({
+		name: '',
+		description: '',
+		type: '',
+		isRequired: true,
+	});
+}
+
+function handleClickDeleteBtn(index: number) {
+	data.value[VueFlowConstant.GROUP_PARAMS_KEY].splice(index, 1);
+}
+const { removeNodes, nodes, addNodes } = useVueFlow();
+
+function handleClickDuplicateBtn() {
+	const { type, position, data } = node.node;
+	const newNode = {
+		id: VueFlowHelper.genGeometryId(),
+		type,
+		position: {
+			x: position.x + 100,
+			y: position.y + 100,
+		},
+		data: deepClone(data),
+	};
+	addNodes(newNode);
+}
+const clickDeleteBtn = () => {
+	removeNodes(node.id);
+};
+
+const addConditionBranch = () => {
+	const conditionGroup = ConditionHelper.getDefaultConditionGroup();
+	conditionGroupList.value.push(conditionGroup);
+};
+
+const delConditionBranch = (index) => {
+	conditionGroupList.value.splice(index, 1);
+	if (conditionGroupList.value.length === 0) {
+		addConditionBranch();
+	}
+};
+
+const addConditionItem = (group) => {
+	const conditionGroup = ConditionHelper.getConditionItem();
+	group.conditions.push(conditionGroup);
+};
+
+const delConditionItem = (group, index) => {
+	group.conditions.splice(index, 1);
+};
+</script>
diff --git a/src/components/vue-flow/ui/nodes/EndNode.vue b/src/components/vue-flow/ui/nodes/EndNode.vue
index fce65bd..5c57725 100644
--- a/src/components/vue-flow/ui/nodes/EndNode.vue
+++ b/src/components/vue-flow/ui/nodes/EndNode.vue
@@ -62,13 +62,13 @@
 
 const data = ref(node.node.data);
 const titleIsEdit = ref(false);
-const parameterTable = computed(() => data.value[VueFlowConstant.PARAMS_KEY]);
+const parameterTable = computed(() => data.value[VueFlowConstant.GROUP_PARAMS_KEY]);
 const { removeNodes, nodes, addNodes } = useVueFlow();
 
 function handleClickDuplicateBtn() {
 	const { type, position, data } = node.node;
 	const newNode = {
-		id: (nodes.value.length + 1).toString(),
+		id: VueFlowHelper.genGeometryId(),
 		type,
 		position: {
 			x: position.x + 100,
diff --git a/src/components/vue-flow/ui/nodes/StartNode.vue b/src/components/vue-flow/ui/nodes/StartNode.vue
index daec7bf..40fc09c 100644
--- a/src/components/vue-flow/ui/nodes/StartNode.vue
+++ b/src/components/vue-flow/ui/nodes/StartNode.vue
@@ -36,7 +36,7 @@
 
 			<div class="flex-auto gap-y-2 flex-col flex nodrag">
 				<div class="text-lg font-bold">鍙傛暟</div>
-				<el-table size="small" class="flex-auto" :data="parameterTable" border>
+				<el-table size="small" class="flex-auto" :data="varList" border>
 					<el-table-column prop="name" width="90" label="鍙傛暟鍚�" fixed>
 						<template #default="scope">
 							<el-input v-model="scope.row.name"></el-input>
@@ -91,15 +91,15 @@
 
 <script lang="ts" setup>
 import { Handle, Position, useNode, useVueFlow } from '@vue-flow/core';
-import { ref } from 'vue';
+import { ref, watchEffect } from 'vue';
 
 import type { NodeProps } from '@vue-flow/core';
 import { computed } from 'vue';
 import { VueFlowConstant } from '../../VueFlowConstant';
+import { VueFlowHelper } from '../../VueFlowHelper';
 import { parameterTypeMap } from '../../vueFlowEnum';
 import { LLMNodeData, LLMNodeEvents } from './index';
 import { deepClone } from '/@/utils/other';
-import { VueFlowHelper } from '../../VueFlowHelper';
 
 defineProps<NodeProps<LLMNodeData, LLMNodeEvents>>();
 
@@ -107,14 +107,21 @@
 const handleId = ref(VueFlowHelper.getHandleId(node.node, 'source'));
 
 const data = ref(node.node.data);
-const titleIsEdit = ref(false);
-const parameterTable = computed(() => data.value[VueFlowConstant.PARAMS_KEY]);
-function handleClickAddBtn() {
-	if (!data.value[VueFlowConstant.PARAMS_KEY]) {
-		data.value[VueFlowConstant.PARAMS_KEY] = [];
-	}
 
-	data.value[VueFlowConstant.PARAMS_KEY].push({
+const getVarList = () =>{
+	const varList = data.value[VueFlowConstant.GROUP_PARAMS_KEY][0][VueFlowConstant.PARAMS_KEY].find(
+		(item) => item.key === 'condition'
+	).value;
+	return varList;
+}
+
+const varList = ref(VueFlowHelper.getFieldValue(data.value,'var_list'));
+const titleIsEdit = ref(false);
+
+function handleClickAddBtn() {
+
+
+	varList.value.push({
 		name: '',
 		description: '',
 		type: '',
@@ -123,14 +130,14 @@
 }
 
 function handleClickDeleteBtn(index: number) {
-	data.value[VueFlowConstant.PARAMS_KEY].splice(index, 1);
+	varList.value.splice(index, 1);
 }
 const { removeNodes, nodes, addNodes } = useVueFlow();
 
 function handleClickDuplicateBtn() {
 	const { type, position, data } = node.node;
 	const newNode = {
-		id: (nodes.value.length + 1).toString(),
+		id: VueFlowHelper.genGeometryId(),
 		type,
 		position: {
 			x: position.x + 100,
@@ -143,4 +150,7 @@
 const clickDeleteBtn = () => {
 	removeNodes(node.id);
 };
+
+
+
 </script>
diff --git a/src/components/vue-flow/vueFlowEnum.ts b/src/components/vue-flow/vueFlowEnum.ts
index dabd789..85e7936 100644
--- a/src/components/vue-flow/vueFlowEnum.ts
+++ b/src/components/vue-flow/vueFlowEnum.ts
@@ -14,7 +14,7 @@
 	LLM = 'LLM',
 	Start = 'start',
 	End = 'end',
-	Condition='condition'
+	Condition = 'condition',
 }
 
 export const nodeTypeMap = {
@@ -22,5 +22,41 @@
 	[NodeType.Start]: '寮�濮�',
 	[NodeType.End]: '缁撴潫',
 	[NodeType.Condition]: '鏉′欢鍒ゆ柇',
-
 };
+
+export const enum CompareOperation {
+	/** @description 澶т簬 */
+	gt = 'gt',
+	/** @description 灏忎簬 */
+	lt = 'lt',
+	/** @description 澶т簬鎴栫瓑浜� */
+	gte = 'gte',
+	/** @description 灏忎簬鎴栫瓑浜� */
+	lte = 'lte',
+}
+export const compareOperationMap = {
+	[CompareOperation.gt]: '>',
+	[CompareOperation.lt]: '<',
+	[CompareOperation.gte]: '鈮�',
+	[CompareOperation.lte]: '鈮�',
+};
+
+export const enum VarType {
+	Input = 'input',
+	Reference = 'reference',
+}
+
+export const varTypeMap = {
+	[VarType.Input]: '杈撳叆',
+	[VarType.Reference]: '寮曠敤',
+};
+
+export const enum ConditionOperator {
+	And = 'and',
+	Or = 'or',
+}
+
+export const conditionOperatorMap = {
+	[ConditionOperator.And]: '涓�',
+	[ConditionOperator.Or]: '鎴�',
+};
\ No newline at end of file

--
Gitblit v1.9.3