fix(web): workflow bugfix

This commit is contained in:
zhaoying
2026-01-14 14:47:46 +08:00
parent e72ecfcb0a
commit 8ed2d12da1
10 changed files with 114 additions and 111 deletions

View File

@@ -60,7 +60,7 @@ const AssignmentList: FC<AssignmentListProps> = ({
>
<VariableSelect
placeholder={t('common.pleaseSelect')}
options={options.filter(vo => vo.nodeData.type === 'loop' || vo.value.includes('conv.'))}
options={options.filter(vo => vo.nodeData.type === 'loop' || vo.value.includes('conv.') || (vo.nodeData.type === 'iteration' && (vo.label === 'item' || vo.label === 'index')))}
popupMatchSelectWidth={false}
onChange={() => {
form.setFieldValue([parentName, name, 'operation'], undefined);

View File

@@ -40,8 +40,6 @@ const operatorsObj: { [key: string]: SelectProps['options'] } = {
boolean: [
{ value: 'eq', label: 'workflow.config.if-else.boolean.eq' },
{ value: 'ne', label: 'workflow.config.if-else.boolean.ne' },
{ value: 'empty', label: 'workflow.config.if-else.empty' },
{ value: 'not_empty', label: 'workflow.config.if-else.not_empty' },
]
}
@@ -85,11 +83,14 @@ const CaseList: FC<CaseListProps> = ({
selectedNode.prop('size', { width: 240, height: newHeight })
// 计算端口间距
const dy = totalPorts;
// 添加 IF 端口
selectedNode.addPort({
id: 'CASE1',
group: 'right',
args: { dy: 24 },
// args: { dy },
attrs: { text: { text: 'IF', fontSize: 12, fill: '#5B6167' }}
});
@@ -98,6 +99,7 @@ const CaseList: FC<CaseListProps> = ({
selectedNode.addPort({
id: `CASE${i + 1}`,
group: 'right',
// args: { dy },
attrs: { text: { text: 'ELIF', fontSize: 12, fill: '#5B6167' }}
});
}
@@ -106,11 +108,22 @@ const CaseList: FC<CaseListProps> = ({
selectedNode.addPort({
id: `CASE${caseCount + 1}`,
group: 'right',
// args: { dy },
attrs: { text: { text: 'ELSE', fontSize: 12, fill: '#5B6167' }}
});
// 恢复仍然存在的端口连线
setTimeout(() => {
// 计算删除前的总端口数来确定原ELSE端口编号
const originalCaseCount = removedCaseIndex !== undefined ? caseCount + 1 : caseCount;
const originalElsePortNumber = originalCaseCount + 1;
// 检查ELSE端口是否有连线
const elseHasConnection = edgeConnections.some(({ sourcePortId, isIncoming }: any) => {
const caseNumber = parseInt(sourcePortId.match(/CASE(\d+)/)?.[1] || '0');
return !isIncoming && caseNumber === originalElsePortNumber;
});
edgeConnections.forEach(({ edge, sourcePortId, targetCellId, targetPortId, sourceCellId, isIncoming }: any) => {
// 如果是进入连线(左侧端口),直接恢复
if (isIncoming) {
@@ -138,7 +151,7 @@ const CaseList: FC<CaseListProps> = ({
// 处理右侧端口连线
const originalCaseNumber = parseInt(sourcePortId.match(/CASE(\d+)/)?.[1] || '0');
// 如果是被删除的端口,不重新创建连线
// 如果是被删除的端口,只删除该端口的连线
if (removedCaseIndex !== undefined && originalCaseNumber === removedCaseIndex + 1) {
graphRef.current?.removeCell(edge);
return;
@@ -146,15 +159,8 @@ const CaseList: FC<CaseListProps> = ({
let newPortId = sourcePortId;
// 如果是原来的ELSE端口重新映射到新的ELSE端口
const maxOriginalCaseNumber = Math.max(...edgeConnections
.filter(({ isIncoming }: any) => !isIncoming)
.map(({ sourcePortId }: any) => {
const match = sourcePortId.match(/CASE(\d+)/);
return match ? parseInt(match[1]) : 0;
}));
if (originalCaseNumber === maxOriginalCaseNumber) {
// 如果是原来的ELSE端口且有连线重新映射到新的ELSE端口
if (originalCaseNumber === originalElsePortNumber && elseHasConnection) {
newPortId = `CASE${caseCount + 1}`; // 新的ELSE端口
} else if (removedCaseIndex !== undefined && originalCaseNumber > removedCaseIndex + 1) {
// 如果是被删除端口之后的端口,编号向前移动

View File

@@ -53,6 +53,7 @@ const operatorsObj: { [key: string]: SelectProps['options'] } = {
const ConditionList: FC<CaseListProps> = ({
options,
parentName,
selectedNode,
}) => {
const { t } = useTranslation();
const form = Form.useFormInstance();
@@ -114,7 +115,12 @@ const ConditionList: FC<CaseListProps> = ({
<Col span={14}>
<Form.Item name={[field.name, 'left']} noStyle>
<VariableSelect
options={options.filter(vo => vo.value.includes('sys.') || vo.value.includes('conv.') || vo.nodeData.type === 'loop')}
options={options.filter(vo =>
vo.value.includes('sys.') ||
vo.value.includes('conv.') ||
vo.nodeData.type === 'loop' ||
(vo.nodeData.cycle && vo.nodeData.cycle === selectedNode?.id)
)}
size="small"
allowClear={false}
popupMatchSelectWidth={false}

View File

@@ -566,42 +566,6 @@ const Properties: FC<PropertiesProps> = ({
nodeData: nodeData,
});
}
// Check if connected via ERROR connection point
const errorEdges = edges.filter(edge =>
edge.getTargetCellId() === selectedNode.id &&
edge.getSourceCellId() === nodeId &&
edge.getSourcePortId() === 'ERROR'
);
if (errorEdges.length > 0) {
const errorMessageKey = `${dataNodeId}_error_message`;
const errorTypeKey = `${dataNodeId}_error_type`;
if (!addedKeys.has(errorMessageKey)) {
addedKeys.add(errorMessageKey);
variableList.push({
key: errorMessageKey,
label: 'error_message',
type: 'variable',
dataType: 'string',
value: `${dataNodeId}.error_message`,
nodeData: nodeData,
});
}
if (!addedKeys.has(errorTypeKey)) {
addedKeys.add(errorTypeKey);
variableList.push({
key: errorTypeKey,
label: 'error_type',
type: 'variable',
dataType: 'string',
value: `${dataNodeId}.error_type`,
nodeData: nodeData,
});
}
}
break
case 'jinja-render':
const jinjaOutputKey = `${dataNodeId}_output`;
@@ -793,54 +757,6 @@ const Properties: FC<PropertiesProps> = ({
}
}
}
// Check if parent loop/iteration is connected to http-request via ERROR connection
if (parentData.type === 'loop' || parentData.type === 'iteration') {
const parentPreviousNodeIds = getAllPreviousNodes(parentLoopNode.id);
parentPreviousNodeIds.forEach(prevNodeId => {
const prevNode = nodes.find(n => n.id === prevNodeId);
if (!prevNode) return;
const prevNodeData = prevNode.getData();
if (prevNodeData.type === 'http-request') {
// Check if connected via ERROR connection point
const errorEdges = edges.filter(edge => {
return edge.getTargetCellId() === parentLoopNode.id &&
edge.getSourceCellId() === prevNodeId &&
edge.getSourcePortId() === 'ERROR'
});
if (errorEdges.length > 0) {
const errorMessageKey = `${prevNodeData.id}_error_message`;
const errorTypeKey = `${prevNodeData.id}_error_type`;
if (!addedKeys.has(errorMessageKey)) {
addedKeys.add(errorMessageKey);
variableList.push({
key: errorMessageKey,
label: 'error_message',
type: 'variable',
dataType: 'string',
value: `${prevNodeData.id}.error_message`,
nodeData: prevNodeData,
});
}
if (!addedKeys.has(errorTypeKey)) {
addedKeys.add(errorTypeKey);
variableList.push({
key: errorTypeKey,
label: 'error_type',
type: 'variable',
dataType: 'string',
value: `${prevNodeData.id}.error_type`,
nodeData: prevNodeData,
});
}
}
}
});
}
}
return variableList;
@@ -999,12 +915,12 @@ const Properties: FC<PropertiesProps> = ({
return filteredList;
}
if (nodeType === 'knowledge-retrieval' || nodeType === 'parameter-extractor' && key !== 'prompt' || nodeType === 'memory-read' || nodeType === 'memory-write' || nodeType === 'question-classifier') {
let filteredList = variableList.filter(variable => variable.dataType === 'string');
return addParentIterationVars(filteredList);
let filteredList = addParentIterationVars(variableList).filter(variable => variable.dataType === 'string');
return filteredList;
}
if (nodeType === 'parameter-extractor' && key === 'prompt') {
let filteredList = variableList.filter(variable => variable.dataType === 'string' || variable.dataType === 'number');
return addParentIterationVars(filteredList);
let filteredList = addParentIterationVars(variableList).filter(variable => variable.dataType === 'string' || variable.dataType === 'number');
return filteredList;
}
if (nodeType === 'iteration' && key === 'output') {
return variableList.filter(variable => variable.value.includes('sys.'));
@@ -1013,8 +929,71 @@ const Properties: FC<PropertiesProps> = ({
return variableList.filter(variable => variable.dataType.includes('array'));
}
if (nodeType === 'loop' && key === 'condition') {
let filteredList = variableList.filter(variable => variable.nodeData.type !== 'loop');
return addParentIterationVars(filteredList);
let filteredList = addParentIterationVars(variableList).filter(variable => variable.nodeData.type !== 'loop');
// Add child node output variables for loop nodes
if (selectedNode) {
const graph = graphRef.current;
if (graph) {
const nodes = graph.getNodes();
const childNodes = nodes.filter(node => {
const nodeData = node.getData();
return nodeData?.cycle === selectedNode.id;
});
// Add output variables from child nodes
childNodes.forEach(childNode => {
const childData = childNode.getData();
const childNodeId = childData.id;
// Add child node output variables based on their type
switch(childData.type) {
case 'llm':
case 'jinja-render':
case 'tool':
const outputKey = `${childNodeId}_output`;
const existingOutput = filteredList.find(v => v.key === outputKey);
if (!existingOutput) {
filteredList.push({
key: outputKey,
label: 'output',
type: 'variable',
dataType: 'string',
value: `${childNodeId}.output`,
nodeData: childData,
});
}
break;
case 'http-request':
const bodyKey = `${childNodeId}_body`;
const statusKey = `${childNodeId}_status_code`;
if (!filteredList.find(v => v.key === bodyKey)) {
filteredList.push({
key: bodyKey,
label: 'body',
type: 'variable',
dataType: 'string',
value: `${childNodeId}.body`,
nodeData: childData,
});
}
if (!filteredList.find(v => v.key === statusKey)) {
filteredList.push({
key: statusKey,
label: 'status_code',
type: 'variable',
dataType: 'number',
value: `${childNodeId}.status_code`,
nodeData: childData,
});
}
break;
}
});
}
}
return filteredList;
}
// For all other node types, add parent iteration variables if applicable
@@ -1025,7 +1004,7 @@ const Properties: FC<PropertiesProps> = ({
// const defaultVariableList = calculateVariableList(selectedNode as Node, graphRef, workflowConfig )
console.log('values', values)
// console.log('variableList', variableList, defaultVariableList)
console.log('variableList', variableList)
return (
<div className="rb:w-75 rb:fixed rb:right-0 rb:top-16 rb:bottom-0 rb:p-3">