From a1ca81341c057355a70f3622d474109eb3438cbb Mon Sep 17 00:00:00 2001 From: shaohuzhang1 Date: Wed, 12 Jun 2024 17:35:46 +0800 Subject: [PATCH] =?UTF-8?q?=20feat:=20=E5=B7=A5=E4=BD=9C=E7=BC=96=E6=8E=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../condition_node/compare/contain_compare.py | 2 + .../direct_reply_node/i_reply_node.py | 2 +- .../direct_reply_node/impl/base_reply_node.py | 2 +- apps/application/flow/workflow_manage.py | 499 ++++++++++++++++++ apps/smartdoc/wsgi.py | 6 + ui/src/workflow/common/NodeContainer.vue | 42 +- ui/src/workflow/common/app-node.ts | 84 +-- ui/src/workflow/common/edge.ts | 7 +- ui/src/workflow/index.vue | 122 +---- ui/src/workflow/nodes/condition-node/index.ts | 59 ++- .../workflow/nodes/condition-node/index.vue | 75 ++- 11 files changed, 658 insertions(+), 242 deletions(-) diff --git a/apps/application/flow/step_node/condition_node/compare/contain_compare.py b/apps/application/flow/step_node/condition_node/compare/contain_compare.py index fee2cddef..6073131a5 100644 --- a/apps/application/flow/step_node/condition_node/compare/contain_compare.py +++ b/apps/application/flow/step_node/condition_node/compare/contain_compare.py @@ -18,4 +18,6 @@ class ContainCompare(Compare): return True def compare(self, source_value, compare, target_value): + if isinstance(source_value, str): + return str(target_value) in source_value return any([str(item) == str(target_value) for item in source_value]) diff --git a/apps/application/flow/step_node/direct_reply_node/i_reply_node.py b/apps/application/flow/step_node/direct_reply_node/i_reply_node.py index 45bbebc38..268ee295c 100644 --- a/apps/application/flow/step_node/direct_reply_node/i_reply_node.py +++ b/apps/application/flow/step_node/direct_reply_node/i_reply_node.py @@ -39,7 +39,7 @@ class IReplyNode(INode): return ReplyNodeParamsSerializer def _run(self): - return self.execute(**self.flow_params_serializer.data) + return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data) def execute(self, reply_type, stream, fields=None, content=None, **kwargs) -> NodeResult: pass diff --git a/apps/application/flow/step_node/direct_reply_node/impl/base_reply_node.py b/apps/application/flow/step_node/direct_reply_node/impl/base_reply_node.py index 94a78a860..51dca9dc9 100644 --- a/apps/application/flow/step_node/direct_reply_node/impl/base_reply_node.py +++ b/apps/application/flow/step_node/direct_reply_node/impl/base_reply_node.py @@ -65,7 +65,7 @@ class BaseReplyNode(IReplyNode): else: result = self.generate_reply_content(content) if stream: - return NodeResult({'result': iter(AIMessageChunk(content=result))}, {}, + return NodeResult({'result': iter([AIMessageChunk(content=result)])}, {}, _to_response=to_stream_response) else: return NodeResult({'result': AIMessage(content=result)}, {}, _to_response=to_response) diff --git a/apps/application/flow/workflow_manage.py b/apps/application/flow/workflow_manage.py index 12f4a5a06..ae3b6fde1 100644 --- a/apps/application/flow/workflow_manage.py +++ b/apps/application/flow/workflow_manage.py @@ -6,6 +6,8 @@ @date:2024/1/9 17:40 @desc: """ +import json +import uuid from typing import List, Dict from langchain_core.prompts import PromptTemplate @@ -172,3 +174,500 @@ class WorkflowManage: def get_node_reference(self, reference_address: Dict): node = self.get_node_by_id(reference_address.get('node_id')) return node.context[reference_address.get('node_field')] + + +json_str = """ +{ + "nodes": [ + { + "id": "base-node", + "type": "base-node", + "x": 200, + "y": 270, + "properties": { + "height": 200, + "stepName": "基本信息", + "node_data": { + "name": "", + "desc": "", + "prologue": "您好,我是 MaxKB 小助手,您可以向我提出 MaxKB 使用问题。" + } + } + }, + { + "id": "start-node", + "type": "start-node", + "x": 140, + "y": 800, + "properties": { + "height": 200, + "stepName": "开始", + "output": [ + { + "key": "" + } + ], + "fields": [ + { + "label": "用户问题", + "value": "question" + } + ] + } + }, + { + "id": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd5", + "type": "search-dataset-node", + "x": 1490, + "y": 580, + "properties": { + "height": 200, + "stepName": "知识库检索", + "input": [ + { + "key": "输入" + } + ], + "output": [ + { + "key": "输出" + } + ], + "fields": [ + { + "label": "检索结果", + "value": "data" + }, + { + "label": "满足直接回答的分段内容", + "value": "paragraph" + } + ], + "node_data": { + "dataset_id_list": [ + "e750b5f5-247a-11ef-8fc8-a8a1595801ab", + "1e42a226-1bfd-11ef-be5f-a8a1595801ab", + "e3b4ad8d-18f2-11ef-9a18-a8a1595801ab", + "861d1f5c-18f3-11ef-a40e-a8a1595801ab" + ], + "dataset_setting": { + "top_n": 3, + "similarity": 0.6, + "max_paragraph_char_number": 5000, + "search_mode": "embedding" + }, + "question_reference_address": [ + "start-node", + "question" + ] + } + } + }, + { + "id": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6", + "type": "condition-node", + "x": 1080, + "y": 500, + "properties": { + "height": 200, + "width": 600, + "stepName": "判断器", + "input": [ + { + "key": "输入" + } + ], + "output": [ + { + "key": "9208" + }, + { + "key": "1143" + }, + { + "key": "输出" + } + ], + "node_data": { + "branch": [ + { + "conditions": [ + { + "field": [ + "03597cb0-ed4c-4bcb-b25b-3b358f72b266", + "answer" + ], + "compare": "contain", + "value": "打招呼" + } + ], + "id": "2391", + "type": "IF", + "condition": "and" + }, + { + "conditions": [ + { + "field": [ + "03597cb0-ed4c-4bcb-b25b-3b358f72b266", + "answer" + ], + "compare": "contain", + "value": "售前咨询" + } + ], + "id": "1143", + "type": "IF ELSE 1", + "condition": "and" + }, + { + "conditions": [ + + ], + "id": "9208", + "type": "ELSE", + "condition": "and" + } + ] + } + } + }, + { + "id": "03597cb0-ed4c-4bcb-b25b-3b358f72b266", + "type": "ai-chat-node", + "x": 580, + "y": 400, + "properties": { + "height": "", + "stepName": "AI 对话", + "input": [ + { + "key": "输入" + } + ], + "output": [ + { + "key": "输出" + } + ], + "node_data": { + "model_id": "9bdd1ab3-135b-11ef-b688-a8a1595801ab", + "system": "你是问题分析大师", + "prompt": "请直接返回所属的问题分类,不要说推理过程。用户问题为:{{context['start-node'].question}} 问题分类是:打招呼 售前咨询 售后咨询其他咨询", + "dialogue_number": 1 + } + } + }, + { + "id": "6649ee86-348c-4d68-9cad-71f0612beb05", + "type": "ai-chat-node", + "x": 2030, + "y": 500, + "properties": { + "height": "", + "stepName": "AI 对话", + "input": [ + { + "key": "输入" + } + ], + "output": [ + { + "key": "输出" + } + ], + "node_data": { + "model_id": "9bdd1ab3-135b-11ef-b688-a8a1595801ab", + "system": "你是售前咨询工程师", + "prompt": "已知信息:{{context['34902d3d-a3ff-497f-b8e1-0c34a44d7dd5'].data}}回答用户问题:{{context['start-node'].question}}", + "dialogue_number": 0 + } + } + }, + { + "id": "0004a9c9-e2fa-40ac-9215-2e1ad04f09c5", + "type": "ai-chat-node", + "x": 1360, + "y": 1300, + "properties": { + "height": "", + "stepName": "AI 对话", + "input": [ + { + "key": "输入" + } + ], + "output": [ + { + "key": "输出" + } + ], + "node_data": { + "model_id": "9bdd1ab3-135b-11ef-b688-a8a1595801ab", + "system": "你是售后咨询工程师", + "prompt": "{{context['start-node'].question}}", + "dialogue_number": 0 + } + } + }, + { + "id": "30c16d31-3881-48cd-991e-da3f99c45681", + "type": "reply-node", + "x": 1690, + "y": 170, + "properties": { + "height": "", + "stepName": "指定回复", + "input": [ + { + "key": "" + } + ], + "output": [ + { + "key": "" + } + ], + "node_data": { + "reply_type": "content", + "content": "你好,有什么需要帮助的吗", + "fields": [ + + ] + } + } + } + ], + "edges": [ + { + "id": "214aa478-78ce-4c95-89aa-11f821bc65d2", + "type": "app-edge", + "sourceNodeId": "start-node", + "targetNodeId": "03597cb0-ed4c-4bcb-b25b-3b358f72b266", + "startPoint": { + "x": 300, + "y": 865.3335000000001 + }, + "endPoint": { + "x": 420, + "y": 677 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 300, + "y": 865.3335000000001 + }, + { + "x": 410, + "y": 865.3335000000001 + }, + { + "x": 310, + "y": 677 + }, + { + "x": 420, + "y": 677 + } + ], + "sourceAnchorId": "start-node__right", + "targetAnchorId": "03597cb0-ed4c-4bcb-b25b-3b358f72b266_输入_left" + }, + { + "id": "d56fb64a-4fc0-4779-911b-283a2238ef7b", + "type": "app-edge", + "sourceNodeId": "03597cb0-ed4c-4bcb-b25b-3b358f72b266", + "targetNodeId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6", + "startPoint": { + "x": 740, + "y": 672 + }, + "endPoint": { + "x": 790, + "y": 678.6665 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 740, + "y": 672 + }, + { + "x": 850, + "y": 672 + }, + { + "x": 680, + "y": 678.6665 + }, + { + "x": 790, + "y": 678.6665 + } + ], + "sourceAnchorId": "03597cb0-ed4c-4bcb-b25b-3b358f72b266_输出_right", + "targetAnchorId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_输入_left" + }, + { + "id": "26fe01d6-8d41-4025-a637-e09f41c9b2c8", + "type": "app-edge", + "sourceNodeId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6", + "targetNodeId": "30c16d31-3881-48cd-991e-da3f99c45681", + "startPoint": { + "x": 1370, + "y": 673.6665 + }, + "endPoint": { + "x": 1530, + "y": 286 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1370, + "y": 673.6665 + }, + { + "x": 1480, + "y": 673.6665 + }, + { + "x": 1420, + "y": 286 + }, + { + "x": 1530, + "y": 286 + } + ], + "sourceAnchorId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_9208_right", + "targetAnchorId": "30c16d31-3881-48cd-991e-da3f99c45681__left" + }, + { + "id": "5c85d2bb-cb27-44ed-9e05-505f702381f6", + "type": "app-edge", + "sourceNodeId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6", + "targetNodeId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd5", + "startPoint": { + "x": 1370, + "y": 697.6665 + }, + "endPoint": { + "x": 1330, + "y": 898.889 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1370, + "y": 697.6665 + }, + { + "x": 1480, + "y": 697.6665 + }, + { + "x": 1220, + "y": 898.889 + }, + { + "x": 1330, + "y": 898.889 + } + ], + "sourceAnchorId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_1143_right", + "targetAnchorId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd5_输入_left" + }, + { + "id": "4d4b5740-910e-48b0-badd-8b9ce10e6e4e", + "type": "app-edge", + "sourceNodeId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd5", + "targetNodeId": "6649ee86-348c-4d68-9cad-71f0612beb05", + "startPoint": { + "x": 1650, + "y": 893.889 + }, + "endPoint": { + "x": 1870, + "y": 777 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1650, + "y": 893.889 + }, + { + "x": 1760, + "y": 893.889 + }, + { + "x": 1760, + "y": 777 + }, + { + "x": 1870, + "y": 777 + } + ], + "sourceAnchorId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd5_输出_right", + "targetAnchorId": "6649ee86-348c-4d68-9cad-71f0612beb05_输入_left" + }, + { + "id": "9c446d4d-e500-4867-8d47-ed99f80b9b48", + "type": "app-edge", + "sourceNodeId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6", + "targetNodeId": "0004a9c9-e2fa-40ac-9215-2e1ad04f09c5", + "startPoint": { + "x": 1370, + "y": 721.6665 + }, + "endPoint": { + "x": 1200, + "y": 1577 + }, + "properties": { + + }, + "pointsList": [ + { + "x": 1370, + "y": 721.6665 + }, + { + "x": 1480, + "y": 721.6665 + }, + { + "x": 1090, + "y": 1577 + }, + { + "x": 1200, + "y": 1577 + } + ], + "sourceAnchorId": "34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_2391_right", + "targetAnchorId": "0004a9c9-e2fa-40ac-9215-2e1ad04f09c5_输入_left" + } + ] +} +""" +f = Flow.new_instance(json.loads(json_str)) +_id = str(uuid.uuid1()) +w_manage = WorkflowManage(flow=f, + params={"history_chat_record": [], "question": "有企业版吗", "chat_id": _id, + "chat_record_id": _id, + "stream": True, "client_id": _id, "client_type": "xxxx"}) +w_manage.run() diff --git a/apps/smartdoc/wsgi.py b/apps/smartdoc/wsgi.py index e04ec5274..29adeb29f 100644 --- a/apps/smartdoc/wsgi.py +++ b/apps/smartdoc/wsgi.py @@ -25,3 +25,9 @@ def post_handler(): post_handler() + + +def run(): + from application.flow.workflow_manage import WorkflowManage + + diff --git a/ui/src/workflow/common/NodeContainer.vue b/ui/src/workflow/common/NodeContainer.vue index 371b228c1..7be819190 100644 --- a/ui/src/workflow/common/NodeContainer.vue +++ b/ui/src/workflow/common/NodeContainer.vue @@ -8,20 +8,6 @@
- @@ -42,33 +28,7 @@ const height = ref<{ const resizeStepContainer = (wh: any) => { if (wh.height) { height.value.stepContainerHeight = wh.height - props.nodeModel.setHeight( - height.value.stepContainerHeight, - height.value.inputContainerHeight, - height.value.outputContainerHeight - ) - } -} - -const resetOutputContainer = (wh: { height: number; width: number }) => { - if (wh.height) { - height.value.outputContainerHeight = wh.height - props.nodeModel.setHeight( - height.value.stepContainerHeight, - height.value.inputContainerHeight, - height.value.outputContainerHeight - ) - } -} - -const resetInputContainer = (wh: { height: number; width: number }) => { - if (wh.height) { - height.value.inputContainerHeight = wh.height - props.nodeModel.setHeight( - height.value.stepContainerHeight, - height.value.inputContainerHeight, - height.value.outputContainerHeight - ) + props.nodeModel.setHeight(height.value.stepContainerHeight) } } diff --git a/ui/src/workflow/common/app-node.ts b/ui/src/workflow/common/app-node.ts index 7abf2b493..37ac06de9 100644 --- a/ui/src/workflow/common/app-node.ts +++ b/ui/src/workflow/common/app-node.ts @@ -47,24 +47,6 @@ class AppNode extends HtmlNode { } class AppNodeModel extends HtmlNodeModel { - /** - * 给model自定义添加字段方法 - */ - addField(item: any) { - this.properties.output.unshift(item) - this.setAttributes() - // 为了保持节点顶部位置不变,在节点变化后,对节点进行一个位移,位移距离为添加高度的一半。 - this.move(0, 24 / 2) - // 更新节点连接边的path - this.incoming.edges.forEach((edge: any) => { - // 调用自定义的更新方案 - edge.updatePathByAnchor() - }) - this.outgoing.edges.forEach((edge: any) => { - // 调用自定义的更新方案 - edge.updatePathByAnchor() - }) - } getOutlineStyle() { const style = super.getOutlineStyle() style.stroke = 'none' @@ -87,12 +69,8 @@ class AppNodeModel extends HtmlNodeModel { return style } - setHeight(height: number, inputContainerHeight: number, outputContainerHeight: number) { - this.height = height + inputContainerHeight + outputContainerHeight + 100 - this.baseHeight = height - this.inputContainerHeight = inputContainerHeight - this.outputContainerHeight = outputContainerHeight - + setHeight(height: number) { + this.height = height + 100 this.outgoing.edges.forEach((edge: any) => { // 调用自定义的更新方案 edge.updatePathByAnchor() @@ -104,7 +82,6 @@ class AppNodeModel extends HtmlNodeModel { } setAttributes() { this.width = this.properties?.width || 340 - const circleOnlyAsTarget = { message: '只允许从右边的锚点连出', validate: (sourceNode: any, targetNode: any, sourceAnchor: any) => { @@ -120,50 +97,21 @@ class AppNodeModel extends HtmlNodeModel { }) } getDefaultAnchor() { - const { - id, - x, - y, - width, - height, - properties: { input, output } - } = this - - if (this.baseHeight === undefined) { - this.baseHeight = 0 - } - if (this.inputContainerHeight === undefined) { - this.inputContainerHeight = 0 - } - if (this.height === undefined) { - this.height = 200 - } - if (this.outputContainerHeight === undefined) { - this.outputContainerHeight = 0 - } - + const { id, x, y, width } = this const anchors: any = [] - if (input) { - input.forEach((field: any, index: any) => { - anchors.push({ - x: x - width / 2 + 10, - y: y - height / 2 + this.baseHeight + 35 + index * 24, - id: `${id}_${field.key}_left`, - edgeAddable: false, - type: 'left' - }) - }) - } - if (output) { - output.forEach((field: any, index: any) => { - anchors.push({ - x: x + width / 2 - 10, - y: y - height / 2 + this.baseHeight + this.inputContainerHeight + 30 + index * 24, - id: `${id}_${field.key}_right`, - type: 'right' - }) - }) - } + anchors.push({ + x: x - width / 2 + 10, + y: y, + id: `${id}`, + edgeAddable: false, + type: 'left' + }) + anchors.push({ + x: x + width / 2 - 10, + y: y, + id: `${id}`, + type: 'right' + }) return anchors } diff --git a/ui/src/workflow/common/edge.ts b/ui/src/workflow/common/edge.ts index fb13bea36..dd38bc703 100644 --- a/ui/src/workflow/common/edge.ts +++ b/ui/src/workflow/common/edge.ts @@ -4,7 +4,10 @@ class CustomEdge2 extends BezierEdge {} class CustomEdgeModel2 extends BezierEdgeModel { getArrowStyle() { - return { offset: 0 } + const arrowStyle = super.getArrowStyle() + arrowStyle.offset = 1 + arrowStyle.verticalLength = 0 + return arrowStyle } getEdgeStyle() { @@ -13,6 +16,7 @@ class CustomEdgeModel2 extends BezierEdgeModel { // svg属性 style.strokeWidth = 2 style.stroke = '#BBBFC4' + style.offset = 0 return style } /** @@ -50,6 +54,7 @@ class CustomEdgeModel2 extends BezierEdgeModel { x: targetAnchor.x, y: targetAnchor.y } + this.updateEndPoint(endPoint) } diff --git a/ui/src/workflow/index.vue b/ui/src/workflow/index.vue index 600b4a5ea..dceabf452 100644 --- a/ui/src/workflow/index.vue +++ b/ui/src/workflow/index.vue @@ -61,34 +61,13 @@ const graphData = { type: 'condition-node', x: 810, y: 760, + properties: { height: 200, width: 600, stepName: '判断器', input: [{ key: '输入' }], - output: [{ key: '9208' }, { key: '1143' }, { key: '输出' }], - node_data: { - branch: [ - { - conditions: [{ field: [], compare: '', value: '' }], - id: '2391', - type: 'IF', - condition: 'and' - }, - { - conditions: [{ field: [], compare: '', value: '' }], - id: '1143', - type: 'IF ELSE 1', - condition: 'and' - }, - { - conditions: [{ field: [], compare: '', value: '' }], - id: '9208', - type: 'ELSE', - condition: 'and' - } - ] - } + output: [{ key: '9208' }, { key: '1143' }, { key: '输出' }] } }, { @@ -118,8 +97,6 @@ const graphData = { properties: { height: '', stepName: 'AI 对话', - input: [{ key: '输入' }], - output: [{ key: '输出' }], node_data: { model_id: '', system: '', @@ -137,8 +114,6 @@ const graphData = { properties: { height: '', stepName: 'AI 对话', - input: [{ key: '输入' }], - output: [{ key: '输出' }], node_data: { model_id: '', system: '', @@ -161,93 +136,7 @@ const graphData = { } } ], - edges: [ - { - id: '8dde4baf-0965-4999-9d37-f867ab16d638', - type: 'app-edge', - sourceNodeId: 'start-node', - targetNodeId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd5', - startPoint: { x: 340, y: 788 }, - endPoint: { x: 440, y: 469 }, - properties: {}, - pointsList: [ - { x: 340, y: 788 }, - { x: 450, y: 788 }, - { x: 330, y: 469 }, - { x: 440, y: 469 } - ], - sourceAnchorId: 'start-node_输出_right', - targetAnchorId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd5_输入_left' - }, - { - id: 'b60de7b4-d8d2-4e7d-bba6-3738b9e523b9', - type: 'app-edge', - sourceNodeId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd5', - targetNodeId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6', - startPoint: { x: 760, y: 503 }, - endPoint: { x: 520, y: 931.0625 }, - properties: {}, - pointsList: [ - { x: 760, y: 503 }, - { x: 870, y: 503 }, - { x: 410, y: 931.0625 }, - { x: 520, y: 931.0625 } - ], - sourceAnchorId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd5_输出_right', - targetAnchorId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_输入_left' - }, - { - id: '8de0da85-b5d6-459a-8be9-4d00082baf1c', - type: 'app-edge', - sourceNodeId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6', - targetNodeId: '03597cb0-ed4c-4bcb-b25b-3b358f72b266', - startPoint: { x: 1100, y: 926.0625 }, - endPoint: { x: 1170, y: 969 }, - properties: {}, - pointsList: [ - { x: 1100, y: 926.0625 }, - { x: 1210, y: 926.0625 }, - { x: 1060, y: 969 }, - { x: 1170, y: 969 } - ], - sourceAnchorId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_9208_right', - targetAnchorId: '03597cb0-ed4c-4bcb-b25b-3b358f72b266_输入_left' - }, - { - id: '3e66821a-ce0a-4ef9-a6cf-ea4095158261', - type: 'app-edge', - sourceNodeId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6', - targetNodeId: '6649ee86-348c-4d68-9cad-71f0612beb05', - startPoint: { x: 1100, y: 950.0625 }, - endPoint: { x: 1160, y: 1269 }, - properties: {}, - pointsList: [ - { x: 1100, y: 950.0625 }, - { x: 1210, y: 950.0625 }, - { x: 1050, y: 1269 }, - { x: 1160, y: 1269 } - ], - sourceAnchorId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_1143_right', - targetAnchorId: '6649ee86-348c-4d68-9cad-71f0612beb05_输入_left' - }, - { - id: 'cc52ab90-58e7-4f54-9660-d9fb16f776ea', - type: 'app-edge', - sourceNodeId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6', - targetNodeId: '0004a9c9-e2fa-40ac-9215-2e1ad04f09c5', - startPoint: { x: 1100, y: 1016.75 }, - endPoint: { x: 1200, y: 1413 }, - properties: {}, - pointsList: [ - { x: 1100, y: 974.0625 }, - { x: 1210, y: 974.0625 }, - { x: 1090, y: 1579 }, - { x: 1200, y: 1579 } - ], - sourceAnchorId: '34902d3d-a3ff-497f-b8e1-0c34a44d7dd6_输出_right', - targetAnchorId: '0004a9c9-e2fa-40ac-9215-2e1ad04f09c5_输入_left' - } - ] + edges: [] } const lf = ref() @@ -318,6 +207,11 @@ onMounted(() => { lf.value.setDefaultEdgeType('app-edge') lf.value.render(graphData) + lf.value.graphModel.eventCenter.on('delete_edge', (id_list: Array) => { + id_list.forEach((id: string) => { + lf.value.deleteEdge(id) + }) + }) } }) const validate = () => { diff --git a/ui/src/workflow/nodes/condition-node/index.ts b/ui/src/workflow/nodes/condition-node/index.ts index 117af80f6..b3cf5fea6 100644 --- a/ui/src/workflow/nodes/condition-node/index.ts +++ b/ui/src/workflow/nodes/condition-node/index.ts @@ -1,12 +1,69 @@ import ConditioNodeVue from './index.vue' +import { cloneDeep, set } from 'lodash' import { AppNode, AppNodeModel } from '@/workflow/common/app-node' class ConditioNode extends AppNode { constructor(props: any) { super(props, ConditioNodeVue) } } +const get_up_index_height = (condition_list: Array, index: number) => { + return condition_list + .filter((item, i) => i < index) + .map((item) => item.height + 8) + .reduce((x, y) => x + y, 0) +} +class ConditionModel extends AppNodeModel { + refreshBranch() { + // 为了保持节点顶部位置不变,在节点变化后,对节点进行一个位移,位移距离为添加高度的一半。 + this.move(0, 24 / 2) + // 更新节点连接边的path + this.incoming.edges.forEach((edge: any) => { + // 调用自定义的更新方案 + edge.updatePathByAnchor() + }) + this.outgoing.edges.forEach((edge: any) => { + edge.updatePathByAnchor() + }) + } + getDefaultAnchor() { + const { + id, + x, + y, + width, + height, + properties: { barnch_condition_list } + } = this + if (this.height === undefined) { + this.height = 200 + } + const anchors: any = [] + anchors.push({ + x: x - width / 2 + 10, + y: y, + id: `${id}`, + edgeAddable: false, + type: 'left' + }) + + if (barnch_condition_list) { + for (let index = 0; index < barnch_condition_list.length; index++) { + const element = barnch_condition_list[index] + const h = get_up_index_height(barnch_condition_list, index) + anchors.push({ + x: x + width / 2 - 10, + y: y - height / 2 + 75 + h + element.height / 2, + id: `${id}_${element.id}_right`, + type: 'right' + }) + } + } + + return anchors + } +} export default { type: 'condition-node', - model: AppNodeModel, + model: ConditionModel, view: ConditioNode } diff --git a/ui/src/workflow/nodes/condition-node/index.vue b/ui/src/workflow/nodes/condition-node/index.vue index d56ef73a0..f6f195460 100644 --- a/ui/src/workflow/nodes/condition-node/index.vue +++ b/ui/src/workflow/nodes/condition-node/index.vue @@ -12,8 +12,13 @@ @mousedown.stop @mousemove.stop > -