feat: 处理循环体
This commit is contained in:
parent
783e54bab0
commit
5c7134f691
@ -109,7 +109,7 @@ export const recursiveFilter = (data, id, type = ['loop', 'customGroup'], result
|
||||
data.forEach((item) => {
|
||||
if (type.includes(item.type) && item.children && item.children.includes(id)) {
|
||||
result.push(item)
|
||||
recursiveFilter(data, item.id, result)
|
||||
recursiveFilter(data, item.id, type, result)
|
||||
}
|
||||
});
|
||||
return result
|
||||
|
||||
@ -3,11 +3,30 @@
|
||||
v-model="props.drawer"
|
||||
custom-class="custom-drawer-header"
|
||||
class="no-header-margin"
|
||||
:title="props.data.properties?.name || '参数配置'"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:show-close="false"
|
||||
>
|
||||
<template #header>
|
||||
<div class="drawer-header">
|
||||
<div>{{ props.data.properties?.name || '参数配置' }}</div>
|
||||
<div>
|
||||
<el-popconfirm
|
||||
width="220"
|
||||
confirm-button-text="确认删除"
|
||||
cancel-button-text="误点击,不删除"
|
||||
:icon="InfoFilled"
|
||||
icon-color="#626AEF"
|
||||
title="是否删除此节点?"
|
||||
@confirm="deleteNode"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="primary" size="small">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="input__container" v-if="props.data.type === 'start'">
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item name="1" icon-position="left">
|
||||
@ -787,7 +806,6 @@
|
||||
</template>
|
||||
<div class="form__container">
|
||||
<el-select v-model="httpNodeData.body.type">
|
||||
<el-option label="None" value="none" />
|
||||
<el-option label="JSON" value="json" />
|
||||
<el-option label="form-data" value="form-data" />
|
||||
</el-select>
|
||||
@ -818,7 +836,7 @@
|
||||
<el-select
|
||||
v-model="property.type"
|
||||
class="param-type"
|
||||
@change="handleTypeChange(index)"
|
||||
@change="handleTypeChange(index, 'httpBody')"
|
||||
>
|
||||
<el-option label="引用" value="quote" />
|
||||
<el-option label="输入" value="input" />
|
||||
@ -887,7 +905,7 @@
|
||||
:options="quoteOptions"
|
||||
placeholder="请选择"
|
||||
@visible-change="
|
||||
(visible) => visibleChange(visible, index, property.quote)
|
||||
(visible) => visibleChange(visible, index, property.quote, 'httpBody')
|
||||
"
|
||||
@change="(value) => cascaderChange(value, index, 'httpBody')"
|
||||
/>
|
||||
@ -931,6 +949,11 @@ const props = defineProps({
|
||||
|
||||
const emits = defineEmits(['close'])
|
||||
|
||||
const deleteNode = () => {
|
||||
lf.deleteNode(props.data.id);
|
||||
emits('close')
|
||||
}
|
||||
|
||||
const formData = reactive({
|
||||
inputParams: [],
|
||||
nodeParams: [],
|
||||
@ -955,28 +978,25 @@ const confirm = async () => {
|
||||
ElMessage.error('JSON中存在错误,请修正后再保存!');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
const nodeParams = []
|
||||
nodeParams.push({ name: "config", type: "input", input: "", children: httpNodeData.value.config, disabled: true, required: true })
|
||||
console.log('httpNodeData.value:', httpNodeData.value)
|
||||
if (httpNodeData.value?.headers?.length > 0) {
|
||||
nodeParams.push({ name: "headers", type: "input", input: "", children: httpNodeData.value.headers, disabled: true, required: true })
|
||||
}
|
||||
if (httpNodeData.value?.params?.length > 0) {
|
||||
nodeParams.push({ name: "params", type: "input", input: "", children: httpNodeData.value.params, disabled: true, required: true })
|
||||
}
|
||||
if (httpNodeData.value.body.type !== 'none') {
|
||||
const bodyObj = {
|
||||
name: "body", type: "input", input: "", children: [
|
||||
{ name: 'bodyType', type: "input", input: "json", disabled: true },
|
||||
{ name: 'json', type: "input", input: editorInstance.getValue() || '' },
|
||||
{ name: 'formData', type: "input", input: "", children: httpNodeData.value.body.formData }
|
||||
]
|
||||
}
|
||||
nodeParams.push(bodyObj)
|
||||
|
||||
const bodyObj = {
|
||||
name: "body", type: "input", input: "", children: [
|
||||
{ name: 'bodyType', type: "input", input: httpNodeData.value.body.type, disabled: true },
|
||||
{ name: 'json', type: "input", input: httpNodeData.value.body.type === 'json' ? editorInstance.getValue() : '' },
|
||||
{ name: 'formData', type: "input", input: "", children: httpNodeData.value.body.formData }
|
||||
]
|
||||
}
|
||||
nodeParams.push(bodyObj)
|
||||
|
||||
lf.setProperties(props.data.id, {
|
||||
...props.data.properties,
|
||||
nodeParams
|
||||
@ -1078,14 +1098,32 @@ const handleDelete = (index) => {
|
||||
};
|
||||
|
||||
const quoteOptions = ref([]);
|
||||
const handleTypeChange = (index) => {
|
||||
if (formData.nodeParams[index].type === "input") {
|
||||
formData.nodeParams[index].quote = "";
|
||||
const handleTypeChange = (index, type = 'default') => {
|
||||
if (type === 'default') {
|
||||
if (formData.nodeParams[index].type === "input") {
|
||||
formData.nodeParams[index].quote = "";
|
||||
} else {
|
||||
formData.nodeParams[index].input = "";
|
||||
const option = getInput(props.data.id);
|
||||
if (option) {
|
||||
quoteOptions.value = option;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
formData.nodeParams[index].input = "";
|
||||
const option = getInput(props.model.id);
|
||||
if (option) {
|
||||
quoteOptions.value = option;
|
||||
const bodyItem = formData.nodeParams.find(item => item.name === 'body');
|
||||
if (bodyItem) {
|
||||
const formDataItem = bodyItem.children.find(child => child.name === 'formData');
|
||||
if (formDataItem) {
|
||||
if (formDataItem.children[index].type === "input") {
|
||||
formDataItem.children[index].quote = "";
|
||||
} else {
|
||||
formDataItem.children[index].input = "";
|
||||
const option = getInput(props.data.id);
|
||||
if (option) {
|
||||
quoteOptions.value = option;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1097,12 +1135,12 @@ const cascaderChange = (value, index, type = 'default') => {
|
||||
formData.nodeParams[index].quote = value;
|
||||
formData.nodeParams[index].quoteType = selectedOptions[0].data.type;
|
||||
} else {
|
||||
formData.nodeParams.find(item => item.name === 'body').children.find(child => child.name === 'formData').children[index].quote = value;
|
||||
formData.nodeParams.find(item => item.name === 'body').children.find(child => child.name === 'formData').children[index].quoteType = selectedOptions[0].data.type;
|
||||
httpNodeData.value.body.formData[index].quote = value;
|
||||
httpNodeData.value.body.formData[index].quoteType = selectedOptions[0].data.type;
|
||||
}
|
||||
};
|
||||
|
||||
const visibleChange = (value, index, quote) => {
|
||||
const visibleChange = (value, index, quote = '', type = 'default') => {
|
||||
if (value) {
|
||||
const option = getInput(props.data.id);
|
||||
if (option) {
|
||||
@ -1113,15 +1151,21 @@ const visibleChange = (value, index, quote) => {
|
||||
// 等待DOM更新后再设置值,确保新options已生效
|
||||
setTimeout(() => {
|
||||
// 如果当前有选中值,重新设置一次以触发重新匹配
|
||||
if (currentValue.length) {
|
||||
formData.nodeParams[index].quote = [];
|
||||
// 确保响应式更新
|
||||
setTimeout(() => {
|
||||
formData.nodeParams[index].quote = currentValue;
|
||||
}, 0);
|
||||
if (currentValue.length > 0) {
|
||||
if (type === 'default') {
|
||||
formData.nodeParams[index].quote = [];
|
||||
// 确保响应式更新
|
||||
setTimeout(() => {
|
||||
formData.nodeParams[index].quote = currentValue;
|
||||
}, 0);
|
||||
} else {
|
||||
httpNodeData.value.body.formData[index].quote = [];
|
||||
// 确保响应式更新
|
||||
setTimeout(() => {
|
||||
httpNodeData.value.body.formData[index].quote = currentValue;
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
// 手动触发级联选择器的重新渲染
|
||||
// cascaderRefs.value[index].updatePopper();
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
@ -1207,45 +1251,7 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
const httpMethodOptions = () => {
|
||||
return [{
|
||||
value: 'POST',
|
||||
label: 'POST'
|
||||
}, {
|
||||
value: 'GET',
|
||||
label: 'GET'
|
||||
}, {
|
||||
value: 'PUT',
|
||||
label: 'PUT'
|
||||
}, {
|
||||
value: 'DELETE',
|
||||
label: 'DELETE'
|
||||
}, {
|
||||
value: 'PATCH',
|
||||
label: 'PATCH'
|
||||
}]
|
||||
}
|
||||
|
||||
const httpNodeData = ref({
|
||||
// config: [
|
||||
// { name: "url", type: "input", input: "", disabled: true, required: true },
|
||||
// { name: "method", type: "input", input: "POST", componentType: 'select', selectOptions: httpMethodOptions(), disabled: true },
|
||||
// { name: "timeout", type: "input", input: "10000", componentType: 'number', disabled: true }
|
||||
// ],
|
||||
// headers: [
|
||||
// { name: "", type: "input", input: ""}
|
||||
// ],
|
||||
// params: [
|
||||
// { name: "", type: "input", input: ""}
|
||||
// ],
|
||||
// body: {
|
||||
// type: 'json',
|
||||
// json: '{}',
|
||||
// formData: [
|
||||
// { name: "", type: "input", input: ""}
|
||||
// ]
|
||||
// }
|
||||
});
|
||||
const httpNodeData = ref({});
|
||||
|
||||
const addHttpNodeFormItem = (e, type) => {
|
||||
e.stopPropagation();
|
||||
@ -1268,9 +1274,6 @@ const handleHttpNodeDelete = (type, index) => {
|
||||
} else {
|
||||
httpNodeData.value[type].splice(index, 1);
|
||||
}
|
||||
// nextTick(() => {
|
||||
// dynamicForm.value?.clearValidate()
|
||||
// });
|
||||
};
|
||||
|
||||
watch(
|
||||
@ -1300,15 +1303,14 @@ watch(
|
||||
} else if (props.data.type === 'http') {
|
||||
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
||||
const transformedData = transformHttpNodeData(nodeParams);
|
||||
console.log('transformedData', transformedData);
|
||||
httpNodeData.value = transformedData;
|
||||
if (transformedData.body.type === 'json') {
|
||||
console.log('httpNodeData', httpNodeData.value);
|
||||
if (httpNodeData.value.body.type === 'json') {
|
||||
setTimeout(() => {
|
||||
if (editorInstance) {
|
||||
setValue(transformedData.body.json || '{}')
|
||||
setValue(httpNodeData.value.body.json || '{}')
|
||||
}
|
||||
}, 100)
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1323,6 +1325,12 @@ onUnmounted(() => {
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.drawer-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.addFormItem {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import LogicFlow, { action } from "@logicflow/core";
|
||||
import LogicFlow from "@logicflow/core";
|
||||
import "@logicflow/core/es/index.css";
|
||||
import "@logicflow/core/lib/style/index.css";
|
||||
import "@logicflow/extension/lib/style/index.css";
|
||||
@ -220,7 +220,6 @@ const drop = (e) => {
|
||||
!["selectArea", "branch", "stopLoop", "subStart", "subEnd"].includes(newNode.type)
|
||||
) {
|
||||
showParamsDrawer.value = true;
|
||||
console.log("newNode", newNode);
|
||||
paramsDrawerData.value = newNode;
|
||||
}
|
||||
};
|
||||
@ -272,22 +271,7 @@ const testRun = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
let allValid = true;
|
||||
// for (const node of nodes) {
|
||||
// const nodeModel = lf.getNodeModelById(node.id);
|
||||
// if (nodeModel && nodeModel.validateForm) {
|
||||
// const result = await nodeModel.validateForm();
|
||||
// if (!result.valid) {
|
||||
// allValid = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (allValid) {
|
||||
isOpen.value = true;
|
||||
} else {
|
||||
ElMessage.error("部分节点验证失败,请查看详情");
|
||||
}
|
||||
isOpen.value = true;
|
||||
};
|
||||
|
||||
// 流程暂停
|
||||
@ -623,6 +607,8 @@ const initFlow = () => {
|
||||
lf.on("node:mousemove", ({ data, e }) => {
|
||||
const { nodes } = lf.getGraphData();
|
||||
const arr = recursiveFilter(nodes, data.id, "loop");
|
||||
// const arr = findRelationNodesById(nodes, data.id);
|
||||
console.log('arr', arr)
|
||||
arr.forEach((item) => {
|
||||
const node = lf.getNodeModelById(item.id);
|
||||
node.updateSize();
|
||||
@ -782,6 +768,12 @@ onMounted(() => {
|
||||
initFlow();
|
||||
document.addEventListener("singleNodeExecution", singleNodeExecution);
|
||||
registerBeforeUnload();
|
||||
|
||||
emitter.on("openParamsDrawer", (node) => {
|
||||
showParamsDrawer.value = true;
|
||||
paramsDrawerData.value = node;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
const operationEdge = (arr) => {
|
||||
@ -792,6 +784,8 @@ const operationEdge = (arr) => {
|
||||
|
||||
onUnmounted(() => {
|
||||
emitter.off("changeNodeState");
|
||||
emitter.off("openParamsDrawer");
|
||||
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
document.removeEventListener("singleNodeExecution", singleNodeExecution);
|
||||
});
|
||||
|
||||
@ -20,49 +20,57 @@ class loopBodyModel extends GroupNodeModel {
|
||||
this.componentInstance = instance;
|
||||
}
|
||||
|
||||
// 验证表单
|
||||
// async validateForm() {
|
||||
// if (this.componentInstance && this.componentInstance.validate) {
|
||||
// try {
|
||||
// const result = await this.componentInstance.validate();
|
||||
// if (result) {
|
||||
// return { valid: true, message: "验证通过" };
|
||||
// } else {
|
||||
// return { valid: false, message: "验证失败" };
|
||||
// }
|
||||
// } catch {
|
||||
// return { valid: false, message: "验证失败" };
|
||||
// }
|
||||
// }
|
||||
// return { valid: true, message: "无验证方法" };
|
||||
// }
|
||||
// 递归获取所有有效子节点(包含多层嵌套 children)
|
||||
getAllValidChildren = (nodeIds, graphModel) => {
|
||||
const validNodes = [];
|
||||
// 遍历当前层节点 ID
|
||||
Array.from(nodeIds).forEach((id) => {
|
||||
const node = graphModel.getNodeModelById(id);
|
||||
if (node) {
|
||||
// 当前节点有效,加入结果
|
||||
validNodes.push(node);
|
||||
// 如果节点还有 children,递归获取下级节点
|
||||
if (node.children && node.children.size > 0) {
|
||||
const childNodes = this.getAllValidChildren(node.children, graphModel);
|
||||
validNodes.push(...childNodes);
|
||||
}
|
||||
} else {
|
||||
// 无效 ID,从集合中删除
|
||||
nodeIds.delete(id);
|
||||
}
|
||||
});
|
||||
return validNodes;
|
||||
};
|
||||
|
||||
// 计算子节点的包围盒(包含所有子节点的最小矩形区域)
|
||||
getChildrenBBox() {
|
||||
const children = []
|
||||
Array.from(this.children).forEach((id) => {
|
||||
const node = this.graphModel.getNodeModelById(id)
|
||||
if (node) {
|
||||
children.push(this.graphModel.getNodeModelById(id))
|
||||
} else {
|
||||
this.children.delete(id)
|
||||
}
|
||||
});
|
||||
const children = this.getAllValidChildren(this.children, this.graphModel)
|
||||
console.log('children', children)
|
||||
// Array.from(this.children).forEach((id) => {
|
||||
// const node = this.graphModel.getNodeModelById(id)
|
||||
// if (node) {
|
||||
// children.push(this.graphModel.getNodeModelById(id))
|
||||
// } else {
|
||||
// this.children.delete(id)
|
||||
// }
|
||||
// });
|
||||
|
||||
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
||||
nextTick(() => {
|
||||
children.forEach((node) => {
|
||||
let width = node.width === 0 ? 320 : node.width
|
||||
let height = node.height === 0 ? 200 : node.height
|
||||
let _width = node.type === 'loop' ? 500 : 320
|
||||
let _height = node.type === 'loop' ? 300 : 200
|
||||
let width = node.width === 0 ? _width : node.width
|
||||
let height = node.height === 0 ? _height : node.height
|
||||
minX = Math.min(minX, node.x - width / 2);
|
||||
maxX = Math.max(maxX, node.x + width / 2);
|
||||
minY = Math.min(minY, node.y - height / 2);
|
||||
maxY = Math.max(maxY, node.y + height / 2);
|
||||
});
|
||||
this.width = maxX - minX + 50; // 增加内边距
|
||||
this.height = maxY - minY + 50;
|
||||
this.width = maxX - minX + 180; // 增加内边距
|
||||
this.height = maxY - minY + 300;
|
||||
this.x = (minX + maxX) / 2;
|
||||
this.y = (minY + maxY) / 2 - 120;
|
||||
this.y = (minY + maxY) / 2;
|
||||
const properties = lf.getProperties(this.id)
|
||||
this.setProperties({
|
||||
...properties,
|
||||
|
||||
@ -20,10 +20,11 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
import NodeTitle from "../../components/NodeTitle.vue";
|
||||
import loop from "../../icon/loop.svg";
|
||||
import { addNewEdge } from "@/utils/flow";
|
||||
import { emitter } from "@/utils/eventBus";
|
||||
import { onUnmounted } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
model: Object,
|
||||
@ -56,6 +57,11 @@ const handleDrop = (e) => {
|
||||
...other,
|
||||
},
|
||||
});
|
||||
if (
|
||||
!["selectArea", "branch", "stopLoop", "subStart", "subEnd"].includes(node.type)
|
||||
) {
|
||||
emitter.emit("openParamsDrawer", node);
|
||||
}
|
||||
|
||||
emits("addToGroup", node.id);
|
||||
setTimeout(() => {
|
||||
@ -72,6 +78,10 @@ const setNodeName = (name) => {
|
||||
emits("contentChange");
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
emitter.off("openParamsDrawer");
|
||||
})
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.group__container {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user