-
- {plugin?.name ?? ''}
-
+
+ {plugin?.name ?? ''}
+
{renderDeleteIcon(plugin.id)}
}
diff --git a/framework/elsa/fit-elsa-react/src/components/loopNode/loopComponent.jsx b/framework/elsa/fit-elsa-react/src/components/loopNode/loopComponent.jsx
index 1dc8c58a2..6ac14423d 100644
--- a/framework/elsa/fit-elsa-react/src/components/loopNode/loopComponent.jsx
+++ b/framework/elsa/fit-elsa-react/src/components/loopNode/loopComponent.jsx
@@ -9,7 +9,7 @@ import {ChangeFlowMetaReducer} from '@/components/common/reducers/commonReducers
import {ChangePluginByMetaDataReducer, DeletePluginReducer, UpdateInputReducer, UpdateRadioInfoReducer} from '@/components/loopNode/reducers/reducers.js';
import {defaultComponent} from '@/components/defaultComponent.js';
import {v4 as uuidv4} from 'uuid';
-import {DATA_TYPES, DEFAULT_LOOP_NODE_CONTEXT, FROM_TYPE} from '@/common/Consts.js';
+import {DATA_TYPES, DEFAULT_ADD_TOOL_NODE_CONTEXT, FROM_TYPE} from '@/common/Consts.js';
export const loopComponent = (jadeConfig, shape) => {
const self = defaultComponent(jadeConfig);
@@ -50,7 +50,7 @@ export const loopComponent = (jadeConfig, shape) => {
from: FROM_TYPE.INPUT,
value: {},
},
- DEFAULT_LOOP_NODE_CONTEXT,
+ DEFAULT_ADD_TOOL_NODE_CONTEXT,
],
outputParams: [],
};
diff --git a/framework/elsa/fit-elsa-react/src/components/loopNode/reducers/reducers.js b/framework/elsa/fit-elsa-react/src/components/loopNode/reducers/reducers.js
index 621a4a376..ae2648620 100644
--- a/framework/elsa/fit-elsa-react/src/components/loopNode/reducers/reducers.js
+++ b/framework/elsa/fit-elsa-react/src/components/loopNode/reducers/reducers.js
@@ -8,7 +8,7 @@ import {updateInput} from '@/components/util/JadeConfigUtils.js';
import {DEFAULT_INPUT_PARAMS} from '@/components/loopNode/LoopConsts.js';
import {TOOL_TYPE} from '@/common/Consts.js';
-export const ChangePluginByMetaDataReducer = (shape) => {
+export const ChangePluginByMetaDataReducer = () => {
const self = {};
self.type = 'changePluginByMetaData';
@@ -39,19 +39,18 @@ export const ChangePluginByMetaDataReducer = (shape) => {
}
});
+ const updateToolInfo = (toolInfo = {}) => {
+ return {
+ ...toolInfo,
+ params: newConfig.inputParams?.find(param => param.name === 'args')?.value?.map(({name}) => ({name})) || [],
+ uniqueName: action.uniqueName,
+ return: { type: 'array' },
+ pluginName: action.pluginName,
+ tags: action.tags
+ };
+ };
- function updateToolInfo() {
- newToolInfo.params = newConfig.inputParams.find(param => param.name === 'args').value.map(property => {
- return {name: property.name};
- });
- newToolInfo.uniqueName = action.uniqueName;
- newToolInfo.return = {};
- newToolInfo.return.type = 'array';
- newToolInfo.pluginName = action.pluginName;
- newToolInfo.tags = action.tags;
- }
- let newToolInfo = {};
- updateToolInfo();
+ const newToolInfo = updateToolInfo();
Object.entries(newConfig).forEach(([key, value]) => {
if (key === 'inputParams') {
@@ -69,12 +68,9 @@ export const ChangePluginByMetaDataReducer = (shape) => {
newConfig[key] = value;
}
});
-
return newConfig;
};
-
-
return self;
};
@@ -134,7 +130,6 @@ export const UpdateInputReducer = () => {
newConfig[key] = value;
}
});
-
return newConfig;
};
diff --git a/framework/elsa/fit-elsa-react/src/components/manualCheck/ManualCheckForm.jsx b/framework/elsa/fit-elsa-react/src/components/manualCheck/ManualCheckForm.jsx
index a3448553b..e5445f379 100644
--- a/framework/elsa/fit-elsa-react/src/components/manualCheck/ManualCheckForm.jsx
+++ b/framework/elsa/fit-elsa-react/src/components/manualCheck/ManualCheckForm.jsx
@@ -13,6 +13,7 @@ import {convertParameter, convertReturnFormat} from '@/components/util/MethodMet
import {useTranslation} from 'react-i18next';
import {EyeOutlined, MinusCircleOutlined} from '@ant-design/icons';
import PropTypes from 'prop-types';
+import {recursive} from '@/components/util/ReferenceUtil.js';
/**
* 人工检查节点折叠区域组件
@@ -87,17 +88,6 @@ const _ManualCheckForm = ({form, data = undefined, handleFormChange, handleFormD
},
};
- const recursive = (params, parent, action) => {
- params.forEach(p => {
- if (p.type === 'Object') {
- recursive(p.value, p, action);
- action(p, parent);
- } else {
- action(p, parent);
- }
- });
- };
-
const deregisterObservables = () => {
if (data) {
recursive(data, null, (p) => {
diff --git a/framework/elsa/fit-elsa-react/src/components/parallelNode/ParallelPluginItem.jsx b/framework/elsa/fit-elsa-react/src/components/parallelNode/ParallelPluginItem.jsx
new file mode 100644
index 000000000..1d29e525d
--- /dev/null
+++ b/framework/elsa/fit-elsa-react/src/components/parallelNode/ParallelPluginItem.jsx
@@ -0,0 +1,145 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
+ * This file is a part of the ModelEngine Project.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import {Button, Collapse, Form} from 'antd';
+import {useDataContext, useShapeContext} from '@/components/DefaultRoot.jsx';
+import React, {useEffect, useState} from 'react';
+import {useTranslation} from 'react-i18next';
+import {MinusCircleOutlined} from '@ant-design/icons';
+import PropTypes from 'prop-types';
+import {InvokeOutput} from '@/components/common/InvokeOutput.jsx';
+import {InvokeInput} from '@/components/common/InvokeInput.jsx';
+import {JadeCollapse} from '@/components/common/JadeCollapse.jsx';
+import {TOOL_TYPE} from '@/common/Consts.js';
+import {v4 as uuidv4} from 'uuid';
+import {recursive} from '@/components/util/ReferenceUtil.js';
+
+const {Panel} = Collapse;
+
+/**
+ * 并行节点插件配置组件
+ *
+ * @param plugin 插件信息.
+ * @param handlePluginDelete 选项删除后的回调.
+ * @param shapeStatus 图形状态.
+ * @return {JSX.Element}
+ * @constructor
+ */
+const _ParallelPluginItem = ({plugin, handlePluginDelete, shapeStatus}) => {
+ const shape = useShapeContext();
+ const data = useDataContext();
+ const [pluginInValid, setPluginInValid] = useState(false);
+ const {t} = useTranslation();
+ const args = plugin?.value?.find(arg => arg.name === 'args')?.value ?? [];
+ const isWaterFlow = plugin?.value?.find(arg => arg.name === 'tags')?.value ?? [].some(tag => tag === TOOL_TYPE.WATER_FLOW)
+ const filterArgs = isWaterFlow ? args.find(arg => arg.name === 'inputParams')?.value ?? args : args;
+ const outputName = plugin?.value?.find(item => item.name === 'outputName')?.value ?? '';
+ const output = data?.outputParams?.find(arg => arg.name === 'output') ?? {};
+ const registryOutputObject = output?.value?.find(arg => arg.name === outputName) ?? {};
+ const virtualPluginOutputData = [{
+ id: "output_" + uuidv4(),
+ name: "output",
+ type: registryOutputObject?.type,
+ value: registryOutputObject?.value ?? []
+ }];
+
+ const registryNode = (nodeData, parent, shape) => {
+ shape.page.registerObservable({
+ nodeId: shape.id,
+ observableId: nodeData.id,
+ value: nodeData.name,
+ type: nodeData.type,
+ parentId: parent ? parent.id : null
+ });
+ if (nodeData.type === "Object") {
+ nodeData?.value?.map(v => registryNode(v, nodeData, shape));
+ }
+ };
+
+ useEffect(() => {
+ if (!registryOutputObject) {
+ return;
+ }
+ registryNode(registryOutputObject, output, shape);
+ }, [registryOutputObject]);
+
+ const deregisterObservables = () => {
+ if (registryOutputObject) {
+ recursive([registryOutputObject], output, (p) => {
+ shape.page.removeObservable(shape.id, p.id);
+ });
+ }
+ };
+
+ const renderDeleteIcon = (id, outputName) => {
+ return (<>
+