import { useState, useRef, useEffect, useMemo } from 'react'; import { Node, Edge } from '@xyflow/react'; import { debounce } from 'lodash'; import { useSelector, useDispatch, shallowEqual } from 'react-redux'; import { updateCanvasDataMap } from '@/store/ideContainer'; import { getCurrentAppKey } from '@/utils/flow/runtime'; import { Dispatch } from 'redux'; export const useFlowEditorState = (initialData?: any, readOnly?: boolean) => { const [nodes, setNodes] = useState([]); const [edges, setEdges] = useState([]); // 使用 shallowEqual 比较器来避免不必要的重新渲染 const ideContainerState = useSelector( (state: any) => ({ canvasDataMap: state.ideContainer.canvasDataMap, appRuntimeData: state.ideContainer.appRuntimeData, currentAppData: state.ideContainer.currentAppData, }), shallowEqual ); const { canvasDataMap, appRuntimeData, currentAppData } = ideContainerState; const dispatch = useDispatch(); // 获取当前应用的运行状态 const currentAppKey = getCurrentAppKey(currentAppData); const currentAppIsRunning = currentAppKey && appRuntimeData[currentAppKey] ? appRuntimeData[currentAppKey].isRunning : false; // 添加编辑弹窗相关状态 const [editingNode, setEditingNode] = useState(null); const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [isDelete, setIsDelete] = useState(false); // 添加节点选择弹窗状态 const [edgeForNodeAdd, setEdgeForNodeAdd] = useState(null); const [positionForNodeAdd, setPositionForNodeAdd] = useState<{ x: number; y: number; } | null>(null); // 在组件顶部添加历史记录相关状态 const [historyInitialized, setHistoryInitialized] = useState(false); const historyTimeoutRef = useRef(null); // 更新节点状态,将从store获取的状态应用到节点上 useEffect(() => { // 获取当前应用对应的节点状态映射 const currentNodeStatusMap = currentAppKey && appRuntimeData[currentAppKey] ? appRuntimeData[currentAppKey].nodeStatusMap : {}; // 检查 initialData 中是否包含节点状态(用于查看历史实例) const hasInitialDataStatus = initialData?.components && Object.values(initialData.components).some((comp: any) => comp.status); setNodes((prevNodes) => { return prevNodes.map((node) => { // 如果是只读模式(历史实例查看),优先使用节点自身的历史状态 // 如果是正常运行模式,只使用运行时状态 let nodeStatus = 'waiting'; let showStatus = false; if (readOnly) { // 只读模式:使用历史状态 nodeStatus = (node.data.status as string) || 'waiting'; showStatus = (hasInitialDataStatus as boolean) || (node.data.isStatusVisible as boolean) || false; } else { // 正常模式:只使用运行时状态 nodeStatus = currentNodeStatusMap[node.id] || 'waiting'; showStatus = currentAppIsRunning; } return { ...node, data: { ...node.data, status: nodeStatus, isStatusVisible: showStatus, }, }; }); }); }, [ appRuntimeData, currentAppKey, currentAppIsRunning, initialData?.id, initialData?.components, nodes.length, readOnly, ]); const updateCanvasDataMapDebounced = useRef( debounce( ( dispatch: Dispatch, canvasDataMap: any, id: string, nodes: Node[], edges: Edge[] ) => { dispatch( updateCanvasDataMap({ ...canvasDataMap, [id]: { nodes, edges }, }) ); }, 500 ) ).current; return { // State values nodes, setNodes, edges, setEdges, canvasDataMap, editingNode, setEditingNode, isEditModalOpen, setIsEditModalOpen, isDelete, setIsDelete, edgeForNodeAdd, setEdgeForNodeAdd, positionForNodeAdd, setPositionForNodeAdd, isRunning: currentAppIsRunning, // 使用当前应用的运行状态 historyInitialized, setHistoryInitialized, historyTimeoutRef, updateCanvasDataMapDebounced, // Redux dispatch, // Initial data initialData: initialData, }; };