import { getFlowById } from "@/api/device/register"; const loadNodeRedData = async (id) => { const data = await getFlowById(id); return Array.isArray(data?.nodes) ? data.nodes : []; }; export const convertNodeRedToVueFlow = async (id) => { const source = await loadNodeRedData(id); const nodes = source.map((node) => { const isGroup = node.type === "group"; const width = isGroup ? Number(node.w || 300) + 80 : 200; const height = isGroup ? Number(node.h || 180) + 80 : 100; const center = { x: Number(node.x || 0) * 2, y: Number(node.y || 0) * 2 }; return { id: node.id, type: isGroup ? "runtime-group" : "runtime-node", position: { x: center.x - width / 2, y: center.y - height / 2 }, width, height, draggable: false, selectable: true, connectable: false, deletable: false, zIndex: isGroup ? -1 : 1, data: { text: node.name || node.type, properties: { ...node, state: "unexecuted" }, children: isGroup ? node.nodes || [] : [], }, }; }); const edges = []; source.forEach((node) => { (node.wires || []).forEach((targets) => { (targets || []).forEach((targetId) => { edges.push({ id: `edge-${node.id}-${targetId}`, source: node.id, target: targetId, sourceHandle: `${node.id}_1`, targetHandle: `${targetId}_3`, type: "bezier", animated: true, selectable: true, focusable: true, interactionWidth: 32, markerEnd: { type: "arrowclosed", color: "#2f80ed", width: 20, height: 20, }, style: { stroke: "#2f80ed", strokeWidth: 2 }, }); }); }); }); return { nodes, edges }; }; export const updateDerivedNodeStates = (nodes, getProperties, setProperties) => { const ignored = ["inject", "cmvrLoop", "startCamera", "getImage", "stopCamera", "startVideo", "stopVideo", "end"]; nodes.filter((node) => !ignored.includes(node.data.properties.type)).forEach((current) => { nodes.forEach((target) => { if (current.data.properties.wires?.[0]?.includes(target.id) && getProperties(target.id).state !== "unexecuted") { setProperties(current.id, { state: "success" }); } if (current.data.properties.wires?.[1]?.includes(target.id)) { setProperties(current.id, { state: getProperties(target.id).state === "failed" ? "failed" : "running" }); } }); }); };