Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
3d0e23ca
authored
Jul 08, 2026
by
Archer
Committed by
GitHub
Jul 08, 2026
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: use stable branch ids for ifelse node (#7276)
parent
e02e1545
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
317 additions
and
33 deletions
+317
-33
packages/global/core/workflow/template/system/ifElse/type.ts
+1
-0
packages/global/core/workflow/template/system/ifElse/utils.ts
+59
-0
packages/global/test/core/workflow/utils.test.ts
+44
-0
packages/service/core/workflow/dispatch/tools/runIfElse.ts
+21
-10
packages/service/test/core/workflow/dispatch/tools/runIfElse.test.ts
+107
-0
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx
+20
-12
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx
+9
-3
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx
+10
-2
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/utils/edge.ts
+21
-6
projects/app/src/web/core/workflow/utils.ts
+25
-0
No files found.
packages/global/core/workflow/template/system/ifElse/type.ts
View file @
3d0e23ca
...
...
@@ -9,6 +9,7 @@ export type ConditionListItemType = {
valueType
?:
'input'
|
'reference'
;
};
export
type
IfElseListItemType
=
{
branchId
?:
string
;
condition
:
IfElseConditionType
;
list
:
ConditionListItemType
[];
};
packages/global/core/workflow/template/system/ifElse/utils.ts
0 → 100644
View file @
3d0e23ca
import
{
getNanoid
}
from
'../../../../../common/string/tools'
;
import
{
getElseIFLabel
}
from
'../../../utils'
;
import
type
{
IfElseListItemType
}
from
'./type'
;
export
const
createIfElseBranchId
=
()
=>
getNanoid
();
/**
* 返回判断器分支的稳定 handle key。旧数据没有 branchId 时回退到旧展示标签,
* 保证未迁移工作流的 IF / ELSE IF n 连线仍能匹配。
*/
export
const
getIfElseBranchHandleKey
=
(
item
:
IfElseListItemType
,
index
:
number
)
=>
item
.
branchId
||
getElseIFLabel
(
index
);
const
ensureUniqueBranchIds
=
({
list
,
createFallback
}:
{
list
:
IfElseListItemType
[];
createFallback
:
(
item
:
IfElseListItemType
,
index
:
number
)
=>
string
;
})
=>
{
const
usedBranchIds
=
new
Set
<
string
>
();
return
list
.
map
((
item
,
index
)
=>
{
const
preferredBranchId
=
item
.
branchId
||
createFallback
(
item
,
index
);
const
branchId
=
(()
=>
{
if
(
!
usedBranchIds
.
has
(
preferredBranchId
))
return
preferredBranchId
;
let
nextBranchId
=
createIfElseBranchId
();
while
(
usedBranchIds
.
has
(
nextBranchId
))
{
nextBranchId
=
createIfElseBranchId
();
}
return
nextBranchId
;
})();
usedBranchIds
.
add
(
branchId
);
return
{
...
item
,
branchId
};
});
};
/**
* 旧工作流加载兼容:缺失 branchId 的分支补旧 handle label,避免保存后断开旧 edge。
*/
export
const
normalizeIfElseList
=
(
list
:
IfElseListItemType
[]
=
[])
=>
ensureUniqueBranchIds
({
list
,
createFallback
:
(
_item
,
index
)
=>
getElseIFLabel
(
index
)
});
/**
* 新建判断器节点初始化:默认分支必须生成随机 ID,不能继续复用 index label。
*/
export
const
initNewIfElseList
=
(
list
:
IfElseListItemType
[]
=
[])
=>
ensureUniqueBranchIds
({
list
,
createFallback
:
()
=>
createIfElseBranchId
()
});
packages/global/test/core/workflow/utils.test.ts
View file @
3d0e23ca
...
...
@@ -39,6 +39,11 @@ import {
defaultQGConfig
}
from
'@fastgpt/global/core/app/constants'
;
import
{
IfElseResultEnum
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/constant'
;
import
{
getIfElseBranchHandleKey
,
initNewIfElseList
,
normalizeIfElseList
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/utils'
;
import
type
{
FlowNodeInputItemType
}
from
'@fastgpt/global/core/workflow/type/io'
;
import
type
{
StoreNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node'
;
import
{
ChatFileTypeEnum
}
from
'@fastgpt/global/core/chat/constants'
;
...
...
@@ -1128,6 +1133,45 @@ describe('getElseIFLabel', () => {
});
});
describe
(
'ifElse branch helpers'
,
()
=>
{
it
(
'should normalize legacy branches with old handle labels'
,
()
=>
{
const
result
=
normalizeIfElseList
([
{
condition
:
'AND'
,
list
:
[]
},
{
condition
:
'OR'
,
list
:
[]
}
]);
expect
(
result
[
0
].
branchId
).
toBe
(
IfElseResultEnum
.
IF
);
expect
(
result
[
1
].
branchId
).
toBe
(
`
${
IfElseResultEnum
.
ELSE_IF
}
1`
);
});
it
(
'should initialize new branches with random branch ids'
,
()
=>
{
const
result
=
initNewIfElseList
([{
condition
:
'AND'
,
list
:
[]
}]);
expect
(
result
[
0
].
branchId
).
toMatch
(
/^
[
a-z
][
a-zA-Z0-9
]{15}
$/
);
expect
(
result
[
0
].
branchId
).
not
.
toBe
(
IfElseResultEnum
.
IF
);
});
it
(
'should keep the first duplicate branch id and regenerate the rest'
,
()
=>
{
const
result
=
normalizeIfElseList
([
{
branchId
:
'same'
,
condition
:
'AND'
,
list
:
[]
},
{
branchId
:
'same'
,
condition
:
'AND'
,
list
:
[]
}
]);
expect
(
result
[
0
].
branchId
).
toBe
(
'same'
);
expect
(
result
[
1
].
branchId
).
toMatch
(
/^
[
a-z
][
a-zA-Z0-9
]{15}
$/
);
expect
(
result
[
1
].
branchId
).
not
.
toBe
(
'same'
);
});
it
(
'should return branch id before falling back to label'
,
()
=>
{
expect
(
getIfElseBranchHandleKey
({
branchId
:
'stableId1'
,
condition
:
'AND'
,
list
:
[]
},
1
)).
toBe
(
'stableId1'
);
expect
(
getIfElseBranchHandleKey
({
condition
:
'AND'
,
list
:
[]
},
1
)).
toBe
(
`
${
IfElseResultEnum
.
ELSE_IF
}
1`
);
});
});
describe
(
'clientGetWorkflowToolRunUserQuery'
,
()
=>
{
it
(
'should return user chat item with dataId'
,
()
=>
{
const
pluginInputs
:
FlowNodeInputItemType
[]
=
[
...
...
packages/service/core/workflow/dispatch/tools/runIfElse.ts
View file @
3d0e23ca
...
...
@@ -15,6 +15,7 @@ import {
type
IfElseConditionType
,
type
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
{
getIfElseBranchHandleKey
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/utils'
;
import
{
type
ModuleDispatchProps
}
from
'@fastgpt/global/core/workflow/runtime/type'
;
import
{
getElseIFLabel
,
getHandleId
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
getReferenceVariableValue
}
from
'@fastgpt/global/core/workflow/runtime/utils'
;
...
...
@@ -137,37 +138,47 @@ function getResult(
export
const
dispatchIfElse
=
async
(
props
:
Props
):
Promise
<
Response
>
=>
{
const
{
params
,
runtimeEdges
,
runtimeNodesMap
,
variableState
,
node
:
{
nodeId
}
}
=
props
;
const
{
ifElseList
}
=
params
;
let
res
=
IfElseResultEnum
.
ELSE
as
string
;
let
selectedLabel
=
IfElseResultEnum
.
ELSE
as
string
;
let
selectedHandleKey
=
IfElseResultEnum
.
ELSE
as
string
;
for
(
let
i
=
0
;
i
<
ifElseList
.
length
;
i
++
)
{
const
item
=
ifElseList
[
i
];
const
result
=
getResult
(
item
.
condition
,
item
.
list
,
variableState
,
runtimeNodesMap
);
if
(
result
)
{
res
=
getElseIFLabel
(
i
);
selectedLabel
=
getElseIFLabel
(
i
);
selectedHandleKey
=
getIfElseBranchHandleKey
(
item
,
i
);
break
;
}
}
const
resArray
=
Array
.
from
({
length
:
ifElseList
.
length
+
1
},
(
_
,
index
)
=>
{
const
label
=
index
<
ifElseList
.
length
?
getElseIFLabel
(
index
)
:
IfElseResultEnum
.
ELSE
;
return
getHandleId
(
nodeId
,
'source'
,
label
);
});
const
selectedHandleId
=
getHandleId
(
nodeId
,
'source'
,
selectedHandleKey
);
const
sourceHandlePrefix
=
`
${
nodeId
}
-source-`
;
const
sourceHandleIds
=
Array
.
from
(
new
Set
(
runtimeEdges
.
filter
(
(
edge
)
=>
edge
.
source
===
nodeId
&&
edge
.
sourceHandle
.
startsWith
(
sourceHandlePrefix
)
)
.
map
((
edge
)
=>
edge
.
sourceHandle
)
)
);
return
{
data
:
{
[
NodeOutputKeyEnum
.
ifElseResult
]:
res
[
NodeOutputKeyEnum
.
ifElseResult
]:
selectedLabel
},
[
DispatchNodeResponseKeyEnum
.
nodeResponse
]:
{
totalPoints
:
0
,
ifElseResult
:
res
ifElseResult
:
selectedLabel
},
[
DispatchNodeResponseKeyEnum
.
skipHandleId
]:
resArray
.
filter
(
(
item
)
=>
item
!==
getHandleId
(
nodeId
,
'source'
,
res
)
[
DispatchNodeResponseKeyEnum
.
skipHandleId
]:
sourceHandleIds
.
filter
(
(
handleId
)
=>
handleId
!==
selectedHandleId
)
};
};
packages/service/test/core/workflow/dispatch/tools/runIfElse.test.ts
0 → 100644
View file @
3d0e23ca
import
{
describe
,
expect
,
it
}
from
'vitest'
;
import
{
VARIABLE_NODE_ID
,
NodeOutputKeyEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
DispatchNodeResponseKeyEnum
}
from
'@fastgpt/global/core/workflow/runtime/constants'
;
import
{
IfElseResultEnum
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/constant'
;
import
{
VariableConditionEnum
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/constant'
;
import
type
{
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
{
getHandleId
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
dispatchIfElse
}
from
'@fastgpt/service/core/workflow/dispatch/tools/runIfElse'
;
type
DispatchProps
=
Parameters
<
typeof
dispatchIfElse
>
[
0
];
const
variableState
=
(
variables
:
Record
<
string
,
unknown
>
)
=>
({
toRuntimeRecord
:
()
=>
variables
})
as
DispatchProps
[
'variableState'
];
const
ref
=
(
key
:
string
)
=>
[
VARIABLE_NODE_ID
,
key
]
as
[
string
,
string
];
const
edge
=
(
sourceHandle
:
string
)
=>
({
source
:
'ifElse'
,
target
:
`
${
sourceHandle
}
-target`
,
sourceHandle
,
targetHandle
:
'target-left'
,
status
:
'waiting'
})
as
DispatchProps
[
'runtimeEdges'
][
number
];
const
buildProps
=
({
ifElseList
,
value
,
sourceHandles
}:
{
ifElseList
:
IfElseListItemType
[];
value
:
string
;
sourceHandles
:
string
[];
})
=>
({
params
:
{
ifElseList
},
node
:
{
nodeId
:
'ifElse'
},
runtimeEdges
:
sourceHandles
.
map
(
edge
),
runtimeNodesMap
:
new
Map
(),
variableState
:
variableState
({
input
:
value
})
})
as
unknown
as
DispatchProps
;
describe
(
'dispatchIfElse branch handles'
,
()
=>
{
it
(
'should use legacy labels for old branches and skip stale source handles'
,
async
()
=>
{
const
result
=
await
dispatchIfElse
(
buildProps
({
value
:
'b'
,
ifElseList
:
[
{
condition
:
'AND'
,
list
:
[{
variable
:
ref
(
'input'
),
condition
:
VariableConditionEnum
.
equalTo
,
value
:
'a'
}]
},
{
condition
:
'AND'
,
list
:
[{
variable
:
ref
(
'input'
),
condition
:
VariableConditionEnum
.
equalTo
,
value
:
'b'
}]
}
],
sourceHandles
:
[
getHandleId
(
'ifElse'
,
'source'
,
IfElseResultEnum
.
IF
),
getHandleId
(
'ifElse'
,
'source'
,
`
${
IfElseResultEnum
.
ELSE_IF
}
1`
),
getHandleId
(
'ifElse'
,
'source'
,
`
${
IfElseResultEnum
.
ELSE_IF
}
2`
),
getHandleId
(
'ifElse'
,
'source'
,
IfElseResultEnum
.
ELSE
)
]
})
);
expect
(
result
.
data
?.[
NodeOutputKeyEnum
.
ifElseResult
]).
toBe
(
`
${
IfElseResultEnum
.
ELSE_IF
}
1`
);
expect
(
result
[
DispatchNodeResponseKeyEnum
.
skipHandleId
]).
toEqual
([
getHandleId
(
'ifElse'
,
'source'
,
IfElseResultEnum
.
IF
),
getHandleId
(
'ifElse'
,
'source'
,
`
${
IfElseResultEnum
.
ELSE_IF
}
2`
),
getHandleId
(
'ifElse'
,
'source'
,
IfElseResultEnum
.
ELSE
)
]);
});
it
(
'should use branchId as selected handle while keeping display result label'
,
async
()
=>
{
const
result
=
await
dispatchIfElse
(
buildProps
({
value
:
'a'
,
ifElseList
:
[
{
branchId
:
'stableA'
,
condition
:
'AND'
,
list
:
[{
variable
:
ref
(
'input'
),
condition
:
VariableConditionEnum
.
equalTo
,
value
:
'a'
}]
},
{
branchId
:
'stableB'
,
condition
:
'AND'
,
list
:
[{
variable
:
ref
(
'input'
),
condition
:
VariableConditionEnum
.
equalTo
,
value
:
'b'
}]
}
],
sourceHandles
:
[
getHandleId
(
'ifElse'
,
'source'
,
'stableA'
),
getHandleId
(
'ifElse'
,
'source'
,
'stableB'
),
getHandleId
(
'ifElse'
,
'source'
,
IfElseResultEnum
.
ELSE
)
]
})
);
expect
(
result
.
data
?.[
NodeOutputKeyEnum
.
ifElseResult
]).
toBe
(
IfElseResultEnum
.
IF
);
expect
(
result
[
DispatchNodeResponseKeyEnum
.
skipHandleId
]).
toEqual
([
getHandleId
(
'ifElse'
,
'source'
,
'stableB'
),
getHandleId
(
'ifElse'
,
'source'
,
IfElseResultEnum
.
ELSE
)
]);
});
});
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx
View file @
3d0e23ca
...
...
@@ -4,13 +4,13 @@ import {
type
DraggableStateSnapshot
}
from
'@fastgpt/web/components/common/DndDrag/index'
;
import
Container
from
'../../components/Container'
;
import
{
MinusIcon
}
from
'@chakra-ui/icons'
;
import
{
type
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
{
type
ReferenceItemValueType
}
from
'@fastgpt/global/core/workflow/type/io'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
{
ReferSelector
,
useReference
}
from
'../render/RenderInput/templates/Reference'
;
import
{
VARIABLE_NODE_ID
,
WorkflowIOValueTypeEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
getIfElseBranchHandleKey
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/utils'
;
import
{
VariableConditionEnum
,
allConditionList
,
...
...
@@ -58,7 +58,11 @@ const ListItem = ({
const
{
t
}
=
useTranslation
();
const
{
getZoom
}
=
useReactFlow
();
const
onDelEdge
=
useContextSelector
(
WorkflowActionsContext
,
(
v
)
=>
v
.
onDelEdge
);
const
handleId
=
getHandleId
(
nodeId
,
'source'
,
getElseIFLabel
(
conditionIndex
));
const
handleId
=
getHandleId
(
nodeId
,
'source'
,
getIfElseBranchHandleKey
(
conditionItem
,
conditionIndex
)
);
const
Render
=
useMemo
(()
=>
{
return
(
...
...
@@ -291,16 +295,20 @@ const ListItem = ({
]);
return
(
<
Box
ref=
{
provided
.
innerRef
}
{
...
provided
.
draggableProps
}
style=
{
{
...
provided
.
draggableProps
.
style
,
opacity
:
snapshot
.
isDragging
?
0.8
:
1
}
}
>
{
Render
}
</
Box
>
<>
{
/* eslint-disable react-hooks/refs -- react-beautiful-dnd requires passing provided refs and props during render. */
}
<
Box
ref=
{
provided
.
innerRef
}
{
...
provided
.
draggableProps
}
style=
{
{
...
provided
.
draggableProps
.
style
,
opacity
:
snapshot
.
isDragging
?
0.8
:
1
}
}
>
{
Render
}
</
Box
>
{
/* eslint-enable react-hooks/refs */
}
</>
);
};
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx
View file @
3d0e23ca
...
...
@@ -6,6 +6,10 @@ import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import
{
type
NodeProps
,
Position
}
from
'reactflow'
;
import
{
type
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node'
;
import
{
type
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
{
createIfElseBranchId
,
getIfElseBranchHandleKey
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/utils'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
Container
from
'../../components/Container'
;
import
DndDrag
,
{
Draggable
}
from
'@fastgpt/web/components/common/DndDrag/index'
;
...
...
@@ -69,8 +73,8 @@ const NodeIfElse = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
<
Box
{
...
provided
.
droppableProps
}
ref=
{
provided
.
innerRef
}
>
{
ifElseList
.
map
((
conditionItem
,
conditionIndex
)
=>
(
<
Draggable
key=
{
conditionIndex
}
draggableId=
{
conditionIndex
.
toString
(
)
}
key=
{
getIfElseBranchHandleKey
(
conditionItem
,
conditionIndex
)
}
draggableId=
{
getIfElseBranchHandleKey
(
conditionItem
,
conditionIndex
)
}
index=
{
conditionIndex
}
>
{
(
provided
,
snapshot
)
=>
(
...
...
@@ -118,12 +122,14 @@ const NodeIfElse = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
onUpdateIfElseList
([
...
ifElseList
,
{
branchId
:
createIfElseBranchId
(),
condition
:
'AND'
,
list
:
[
{
variable
:
undefined
,
condition
:
undefined
,
value
:
undefined
value
:
undefined
,
valueType
:
'input'
}
]
}
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx
View file @
3d0e23ca
import
React
,
{
useMemo
}
from
'react'
;
import
{
Position
}
from
'reactflow'
;
import
{
MySourceHandle
,
MyTargetHandle
}
from
'.'
;
import
{
getHandleId
,
getElseIFLabel
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
getHandleId
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
NodeInputKeyEnum
,
NodeOutputKeyEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
WorkflowBufferDataContext
}
from
'../../../../context/workflowInitContext'
;
import
{
WorkflowActionsContext
}
from
'../../../../context/workflowActionsContext'
;
import
{
FlowNodeTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
import
type
{
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
{
getIfElseBranchHandleKey
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/utils'
;
export
const
ConnectionSourceHandle
=
({
nodeId
,
...
...
@@ -40,7 +42,13 @@ export const ConnectionSourceHandle = ({
return
getHandleId
(
nodeId
,
'source'
,
options
[
0
].
key
);
}
}
else
if
(
node
.
flowNodeType
===
FlowNodeTypeEnum
.
ifElseNode
)
{
return
getHandleId
(
nodeId
,
'source'
,
getElseIFLabel
(
0
));
const
ifElseList
=
node
.
inputs
.
find
(
(
input
)
=>
input
.
key
===
NodeInputKeyEnum
.
ifElseList
)?.
value
as
IfElseListItemType
[]
|
undefined
;
const
firstIfElse
=
ifElseList
?.[
0
];
if
(
firstIfElse
)
{
return
getHandleId
(
nodeId
,
'source'
,
getIfElseBranchHandleKey
(
firstIfElse
,
0
));
}
}
else
if
(
node
.
flowNodeType
===
FlowNodeTypeEnum
.
classifyQuestion
)
{
const
options
=
node
?.
inputs
?.
find
(
(
input
)
=>
input
.
key
===
NodeInputKeyEnum
.
agents
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/utils/edge.ts
View file @
3d0e23ca
...
...
@@ -9,6 +9,9 @@ import { type FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node';
import
{
NodeInputKeyEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
FlowNodeTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
import
{
IfElseResultEnum
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/constant'
;
import
{
getIfElseBranchHandleKey
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/utils'
;
import
type
{
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
{
getHandleId
}
from
'@fastgpt/global/core/workflow/utils'
;
// Get sort index from source node's output handle order
export
const
getHandleIndex
=
(
...
...
@@ -29,14 +32,26 @@ export const getHandleIndex = (
}
}
// ifElseNode:
IF=0, ELSE IF=1/2/3..., ELSE=999
// ifElseNode:
sort by stable branch handle, ELSE always last.
if
(
flowNodeType
===
FlowNodeTypeEnum
.
ifElseNode
)
{
if
(
handleId
.
includes
(
IfElseResultEnum
.
ELSE_IF
))
{
const
match
=
handleId
.
match
(
/ELSE IF
(\d
+
)
/
);
return
match
?
parseInt
(
match
[
1
])
:
1
;
const
ifElseList
=
inputs
?.
find
((
i
)
=>
i
.
key
===
NodeInputKeyEnum
.
ifElseList
)?.
value
as
|
IfElseListItemType
[]
|
undefined
;
if
(
Array
.
isArray
(
ifElseList
))
{
const
idx
=
ifElseList
.
findIndex
((
item
,
index
)
=>
{
const
itemHandleId
=
getHandleId
(
sourceNode
.
data
.
nodeId
,
'source'
,
getIfElseBranchHandleKey
(
item
,
index
)
);
return
itemHandleId
===
handleId
;
});
if
(
idx
>=
0
)
return
idx
;
}
if
(
handleId
.
endsWith
(
`-
${
IfElseResultEnum
.
IF
}
`
))
return
0
;
if
(
handleId
.
endsWith
(
`-
${
IfElseResultEnum
.
ELSE
}
`
))
return
999
;
if
(
handleId
===
getHandleId
(
sourceNode
.
data
.
nodeId
,
'source'
,
IfElseResultEnum
.
ELSE
))
{
return
999
;
}
return
998
;
}
// classifyQuestion: sort by agent index
...
...
projects/app/src/web/core/workflow/utils.ts
View file @
3d0e23ca
...
...
@@ -32,6 +32,10 @@ import {
type
ReferenceValueType
}
from
'@fastgpt/global/core/workflow/type/io'
;
import
{
type
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
{
initNewIfElseList
,
normalizeIfElseList
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/utils'
;
import
{
LoopRunModeEnum
}
from
'@fastgpt/global/core/workflow/template/system/loopRun/loopRun'
;
import
{
VariableConditionEnum
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/constant'
;
import
{
type
TUpdateListItem
}
from
'@fastgpt/global/core/workflow/template/system/variableUpdate/type'
;
...
...
@@ -49,6 +53,17 @@ import type { LLMModelItemType } from '@fastgpt/global/core/ai/model.schema';
* 这里仅处理旧字段到新字段的 key 和 valueType 迁移。
*/
export
const
adaptStoreNodeInputs
=
(
storeNode
:
StoreNodeItemType
):
FlowNodeInputItemType
[]
=>
{
if
(
storeNode
.
flowNodeType
===
FlowNodeTypeEnum
.
ifElseNode
)
{
return
storeNode
.
inputs
.
map
((
input
)
=>
{
if
(
input
.
key
!==
NodeInputKeyEnum
.
ifElseList
)
return
input
;
return
{
...
input
,
value
:
normalizeIfElseList
(
input
.
value
as
IfElseListItemType
[])
};
});
}
if
(
storeNode
.
flowNodeType
!==
FlowNodeTypeEnum
.
datasetSearchNode
)
{
return
storeNode
.
inputs
;
}
...
...
@@ -91,6 +106,16 @@ export const nodeTemplate2FlowNode = ({
nodeId
:
getNanoid
(),
parentNodeId
};
if
(
moduleItem
.
flowNodeType
===
FlowNodeTypeEnum
.
ifElseNode
)
{
moduleItem
.
inputs
=
moduleItem
.
inputs
.
map
((
input
)
=>
{
if
(
input
.
key
!==
NodeInputKeyEnum
.
ifElseList
)
return
input
;
return
{
...
input
,
value
:
initNewIfElseList
(
input
.
value
as
IfElseListItemType
[])
};
});
}
return
{
id
:
moduleItem
.
nodeId
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment