feat: 工作编排

This commit is contained in:
shaohuzhang1 2024-06-12 17:35:46 +08:00
parent 7bf01df60b
commit a1ca81341c
11 changed files with 658 additions and 242 deletions

View File

@ -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])

View File

@ -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

View File

@ -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)

View File

@ -6,6 +6,8 @@
@date2024/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()

View File

@ -25,3 +25,9 @@ def post_handler():
post_handler()
def run():
from application.flow.workflow_manage import WorkflowManage

View File

@ -8,20 +8,6 @@
</div>
<div><slot></slot></div>
</div>
<!-- <div class="input-container" v-resize="resetInputContainer">
<div v-for="(item, index) in nodeModel.properties.input" :key="index" class="step-field">
<span>{{ item.key }}</span>
</div>
</div>
<div class="output-container" v-resize="resetOutputContainer">
<div
v-for="(item, index) in nodeModel.properties.output"
:key="index"
class="out-step-field"
>
<span>{{ item.key }}</span>
</div>
</div> -->
</div>
</div>
</template>
@ -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)
}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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<string>) => {
id_list.forEach((id: string) => {
lf.value.deleteEdge(id)
})
})
}
})
const validate = () => {

View File

@ -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<any>, 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
}

View File

@ -12,8 +12,13 @@
@mousedown.stop
@mousemove.stop
>
<template v-for="(item, index) in form_data.branch" :key="index">
<el-card shadow="never" class="card-never mb-8" style="--el-card-padding: 12px">
<template v-for="(item, index) in form_data.branch" :key="item.id">
<el-card
v-resize="(wh) => resizeCondition(wh, item, index)"
shadow="never"
class="card-never mb-8"
style="--el-card-padding: 12px"
>
<div class="flex-between lighter">
{{ item.type }}
<div class="info" v-if="item.conditions.length > 1">
@ -110,9 +115,10 @@ import { cloneDeep, set } from 'lodash'
import NodeContainer from '@/workflow/common/NodeContainer.vue'
import NodeCascader from '@/workflow/common/NodeCascader.vue'
import type { FormInstance } from 'element-plus'
import { ref, computed, onMounted } from 'vue'
import { ref, computed, onMounted, nextTick } from 'vue'
import { randomId } from '@/utils/utils'
import { compareList } from '@/workflow/common/data'
const props = defineProps<{ nodeModel: any }>()
const form = {
branch: [
@ -137,12 +143,28 @@ const form = {
]
}
const resizeCondition = (wh: any, row: any, index: number) => {
const barnch_condition_list = cloneDeep(
props.nodeModel.properties.barnch_condition_list
? props.nodeModel.properties.barnch_condition_list
: []
)
const new_barnch_condition_list = barnch_condition_list.map((item: any) => {
if (item.id === row.id) {
return { ...item, height: wh.height, index: index }
}
return item
})
set(props.nodeModel.properties, 'barnch_condition_list', new_barnch_condition_list)
refreshBranchAnchor(props.nodeModel.properties.node_data.branch, true)
}
const form_data = computed({
get: () => {
if (props.nodeModel.properties.node_data) {
return props.nodeModel.properties.node_data
} else {
set(props.nodeModel.properties, 'node_data', form)
refreshBranchAnchor(form.branch, true)
}
return props.nodeModel.properties.node_data
},
@ -157,16 +179,6 @@ const validate = () => {
ConditionNodeFormRef.value?.validate()
}
// const judgeLabel = (index: number) => {
// if (index === 0) {
// return 'IF'
// } else if (index === form_data.value.branch.length - 1) {
// return 'ELSE'
// } else {
// return 'ELSE IF ' + index
// }
// }
function addBranch() {
const list = cloneDeep(props.nodeModel.properties.node_data.branch)
const obj = {
@ -182,9 +194,31 @@ function addBranch() {
condition: 'and'
}
list.splice(list.length - 1, 0, obj)
props.nodeModel.addField({ key: obj.id })
refreshBranchAnchor(list, true)
set(props.nodeModel.properties.node_data, 'branch', list)
}
function refreshBranchAnchor(list: Array<any>, is_add: boolean) {
const barnch_condition_list = cloneDeep(
props.nodeModel.properties.barnch_condition_list
? props.nodeModel.properties.barnch_condition_list
: []
)
const new_barnch_condition_list = list
.map((item, index) => {
const find = barnch_condition_list.find((b) => b.id === item.id)
if (find) {
return { index: index, height: find.height, id: item.id }
} else {
if (is_add) {
return { index: index, height: 12, id: item.id }
}
}
})
.filter((item) => item)
set(props.nodeModel.properties, 'barnch_condition_list', new_barnch_condition_list)
props.nodeModel.refreshBranch()
}
function addCondition(index: number) {
const list = cloneDeep(props.nodeModel.properties.node_data.branch)
@ -200,7 +234,18 @@ function deleteCondition(index: number, cIndex: number) {
const list = cloneDeep(props.nodeModel.properties.node_data.branch)
list[index]['conditions'].splice(cIndex, 1)
if (list[index]['conditions'].length === 0) {
list.splice(index, 1)
const delete_edge = list.splice(index, 1)
const delete_target_anchor_id_list = delete_edge.map(
(item) => props.nodeModel.id + '_' + item.id + '_right'
)
props.nodeModel.graphModel.eventCenter.emit(
'delete_edge',
props.nodeModel.outgoing.edges
.filter((item) => delete_target_anchor_id_list.includes(item.sourceAnchorId))
.map((item) => item.id)
)
refreshBranchAnchor(list, false)
}
set(props.nodeModel.properties.node_data, 'branch', list)
}