mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
fix: loop node snapshot & infinite reload (#3349)
This commit is contained in:
@@ -292,63 +292,7 @@ export const useWorkflow = () => {
|
||||
const { getIntersectingNodes } = useReactFlow();
|
||||
const { isDowningCtrl } = useKeyboard();
|
||||
|
||||
// Loop node size and position
|
||||
const resetParentNodeSizeAndPosition = useMemoizedFn((parentId: string) => {
|
||||
const { childNodes, loopNode } = nodes.reduce(
|
||||
(acc, node) => {
|
||||
if (node.data.parentNodeId === parentId) {
|
||||
acc.childNodes.push(node);
|
||||
}
|
||||
if (node.id === parentId) {
|
||||
acc.loopNode = node;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ childNodes: [] as Node[], loopNode: undefined as Node<FlowNodeItemType> | undefined }
|
||||
);
|
||||
|
||||
if (!loopNode) return;
|
||||
|
||||
const rect = getNodesBounds(childNodes);
|
||||
// Calculate parent node size with minimum width/height constraints
|
||||
const width = Math.max(rect.width + 80, 840);
|
||||
const height = Math.max(rect.height + 80, 600);
|
||||
|
||||
const offsetHeight =
|
||||
loopNode.data.inputs.find((input) => input.key === NodeInputKeyEnum.loopNodeInputHeight)
|
||||
?.value ?? 83;
|
||||
|
||||
// Update parentNode size and position
|
||||
onChangeNode({
|
||||
nodeId: parentId,
|
||||
type: 'updateInput',
|
||||
key: NodeInputKeyEnum.nodeWidth,
|
||||
value: {
|
||||
...Input_Template_Node_Width,
|
||||
value: width
|
||||
}
|
||||
});
|
||||
onChangeNode({
|
||||
nodeId: parentId,
|
||||
type: 'updateInput',
|
||||
key: NodeInputKeyEnum.nodeHeight,
|
||||
value: {
|
||||
...Input_Template_Node_Height,
|
||||
value: height
|
||||
}
|
||||
});
|
||||
// Update parentNode position
|
||||
onNodesChange([
|
||||
{
|
||||
id: parentId,
|
||||
type: 'position',
|
||||
position: {
|
||||
x: rect.x - 70,
|
||||
y: rect.y - offsetHeight - 240
|
||||
}
|
||||
}
|
||||
]);
|
||||
});
|
||||
const { resetParentNodeSizeAndPosition } = useLoopNode();
|
||||
|
||||
/* helper line */
|
||||
const [helperLineHorizontal, setHelperLineHorizontal] = useState<THelperLine>();
|
||||
@@ -704,7 +648,7 @@ export const useWorkflow = () => {
|
||||
chatConfig: appDetail.chatConfig
|
||||
});
|
||||
},
|
||||
[nodes, edges, appDetail.chatConfig, pushPastSnapshot],
|
||||
[nodes, edges, appDetail.chatConfig],
|
||||
{ wait: 500 }
|
||||
);
|
||||
|
||||
@@ -721,7 +665,73 @@ export const useWorkflow = () => {
|
||||
helperLineVertical,
|
||||
onNodeDragStop,
|
||||
onPaneContextMenu,
|
||||
onPaneClick,
|
||||
onPaneClick
|
||||
};
|
||||
};
|
||||
|
||||
export const useLoopNode = () => {
|
||||
const nodes = useContextSelector(WorkflowInitContext, (state) => state.nodes);
|
||||
const onNodesChange = useContextSelector(WorkflowNodeEdgeContext, (state) => state.onNodesChange);
|
||||
const { onChangeNode } = useContextSelector(WorkflowContext, (v) => v);
|
||||
|
||||
const resetParentNodeSizeAndPosition = useMemoizedFn((parentId: string) => {
|
||||
const { childNodes, loopNode } = nodes.reduce(
|
||||
(acc, node) => {
|
||||
if (node.data.parentNodeId === parentId) {
|
||||
acc.childNodes.push(node);
|
||||
}
|
||||
if (node.id === parentId) {
|
||||
acc.loopNode = node;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ childNodes: [] as Node[], loopNode: undefined as Node<FlowNodeItemType> | undefined }
|
||||
);
|
||||
|
||||
if (!loopNode) return;
|
||||
|
||||
const rect = getNodesBounds(childNodes);
|
||||
// Calculate parent node size with minimum width/height constraints
|
||||
const width = Math.max(rect.width + 80, 840);
|
||||
const height = Math.max(rect.height + 80, 600);
|
||||
|
||||
const offsetHeight =
|
||||
loopNode.data.inputs.find((input) => input.key === NodeInputKeyEnum.loopNodeInputHeight)
|
||||
?.value ?? 83;
|
||||
|
||||
// Update parentNode size and position
|
||||
onChangeNode({
|
||||
nodeId: parentId,
|
||||
type: 'updateInput',
|
||||
key: NodeInputKeyEnum.nodeWidth,
|
||||
value: {
|
||||
...Input_Template_Node_Width,
|
||||
value: width
|
||||
}
|
||||
});
|
||||
onChangeNode({
|
||||
nodeId: parentId,
|
||||
type: 'updateInput',
|
||||
key: NodeInputKeyEnum.nodeHeight,
|
||||
value: {
|
||||
...Input_Template_Node_Height,
|
||||
value: height
|
||||
}
|
||||
});
|
||||
// Update parentNode position
|
||||
onNodesChange([
|
||||
{
|
||||
id: parentId,
|
||||
type: 'position',
|
||||
position: {
|
||||
x: rect.x - 70,
|
||||
y: rect.y - offsetHeight - 240
|
||||
}
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
return {
|
||||
resetParentNodeSizeAndPosition
|
||||
};
|
||||
};
|
||||
|
@@ -31,7 +31,7 @@ import { getWorkflowGlobalVariables } from '@/web/core/workflow/utils';
|
||||
import { AppContext } from '../../../../context';
|
||||
import { isValidArrayReferenceValue } from '@fastgpt/global/core/workflow/utils';
|
||||
import { ReferenceArrayValueType } from '@fastgpt/global/core/workflow/type/io';
|
||||
import { useWorkflow } from '../../hooks/useWorkflow';
|
||||
import { useLoopNode } from '../../hooks/useWorkflow';
|
||||
import { useSize } from 'ahooks';
|
||||
|
||||
const NodeLoop = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
@@ -41,7 +41,7 @@ const NodeLoop = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
|
||||
const appDetail = useContextSelector(AppContext, (v) => v.appDetail);
|
||||
|
||||
const { resetParentNodeSizeAndPosition } = useWorkflow();
|
||||
const { resetParentNodeSizeAndPosition } = useLoopNode();
|
||||
|
||||
const {
|
||||
nodeWidth,
|
||||
@@ -50,8 +50,12 @@ const NodeLoop = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
loopNodeInputHeight = Input_Template_LOOP_NODE_OFFSET
|
||||
} = useMemo(() => {
|
||||
return {
|
||||
nodeWidth: inputs.find((input) => input.key === NodeInputKeyEnum.nodeWidth)?.value,
|
||||
nodeHeight: inputs.find((input) => input.key === NodeInputKeyEnum.nodeHeight)?.value,
|
||||
nodeWidth: Number(
|
||||
inputs.find((input) => input.key === NodeInputKeyEnum.nodeWidth)?.value?.toFixed(0)
|
||||
),
|
||||
nodeHeight: Number(
|
||||
inputs.find((input) => input.key === NodeInputKeyEnum.nodeHeight)?.value?.toFixed(0)
|
||||
),
|
||||
loopInputArray: inputs.find((input) => input.key === NodeInputKeyEnum.loopInputArray),
|
||||
loopNodeInputHeight: inputs.find(
|
||||
(input) => input.key === NodeInputKeyEnum.loopNodeInputHeight
|
||||
|
@@ -2,7 +2,6 @@ import { postWorkflowDebug } from '@/web/core/workflow/api';
|
||||
import {
|
||||
checkWorkflowNodeAndConnection,
|
||||
compareSnapshot,
|
||||
simplifyWorkflowNodes,
|
||||
storeEdgesRenderEdge,
|
||||
storeNode2FlowNode
|
||||
} from '@/web/core/workflow/utils';
|
||||
@@ -833,10 +832,10 @@ const WorkflowContextProvider = ({
|
||||
if (past.length > 1) {
|
||||
forbiddenSaveSnapshot.current = true;
|
||||
|
||||
const firstPast = past[0];
|
||||
const firstPast = past[1];
|
||||
resetSnapshot(firstPast);
|
||||
|
||||
setFuture((future) => [firstPast, ...future]);
|
||||
setFuture((future) => [past[0], ...future]);
|
||||
setPast((past) => past.slice(1));
|
||||
}
|
||||
});
|
||||
@@ -937,10 +936,10 @@ const WorkflowContextProvider = ({
|
||||
if (isInit && past.length === 0) {
|
||||
setPast([
|
||||
{
|
||||
nodes: nodes,
|
||||
edges: edges,
|
||||
title: t(`app:app.version_initial`),
|
||||
isSaved: true,
|
||||
nodes: simplifyWorkflowNodes(nodes),
|
||||
edges,
|
||||
chatConfig: e.chatConfig || appDetail.chatConfig
|
||||
}
|
||||
]);
|
||||
|
@@ -619,7 +619,6 @@ export const compareSnapshot = (
|
||||
return nodes
|
||||
.filter((node) => {
|
||||
if (!node) return;
|
||||
if (FlowNodeTypeEnum.systemConfig === node.type) return;
|
||||
|
||||
return true;
|
||||
})
|
||||
@@ -634,7 +633,8 @@ export const compareSnapshot = (
|
||||
key: input.key,
|
||||
selectedTypeIndex: input.selectedTypeIndex ?? 0,
|
||||
renderTypeLis: input.renderTypeList,
|
||||
valueType: input.valueType,
|
||||
// set to arrayAny for loopInputArray to skip valueType comparison
|
||||
valueType: input.key === NodeInputKeyEnum.loopInputArray ? 'arrayAny' : input.valueType,
|
||||
value: input.value ?? undefined
|
||||
})),
|
||||
outputs: node.data.outputs.map((item: FlowNodeOutputItemType) => ({
|
||||
@@ -661,13 +661,3 @@ export const compareSnapshot = (
|
||||
|
||||
return isEqual(node1, node2);
|
||||
};
|
||||
|
||||
// remove node size
|
||||
export const simplifyWorkflowNodes = (nodes: Node[]) => {
|
||||
return nodes.map((node) => ({
|
||||
id: node.id,
|
||||
type: node.type,
|
||||
position: node.position,
|
||||
data: node.data
|
||||
}));
|
||||
};
|
||||
|
Reference in New Issue
Block a user