diff --git a/packages/web/hooks/useI18n.ts b/packages/web/hooks/useI18n.ts index aaf0617ff..bbe049d2c 100644 --- a/packages/web/hooks/useI18n.ts +++ b/packages/web/hooks/useI18n.ts @@ -34,7 +34,7 @@ export const useI18nLng = () => { const currentLng = i18n?.language; await i18n?.changeLanguage?.(lang); - if (currentLng !== lang) { + if (currentLng !== lang && currentLng) { window?.location?.reload?.(); } }; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx index 638334fce..383191d25 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx @@ -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 | 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(); @@ -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 | 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 }; }; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx index b79eed6de..cec01948d 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx @@ -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) => { @@ -41,7 +41,7 @@ const NodeLoop = ({ data, selected }: NodeProps) => { 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) => { 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 diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/context/index.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/context/index.tsx index dd753dba3..72e9acb14 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/context/index.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/context/index.tsx @@ -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 } ]); diff --git a/projects/app/src/web/core/workflow/utils.ts b/projects/app/src/web/core/workflow/utils.ts index 7e0612d44..fa9f68fc0 100644 --- a/projects/app/src/web/core/workflow/utils.ts +++ b/projects/app/src/web/core/workflow/utils.ts @@ -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 - })); -};