fix(web): update add node
This commit is contained in:
@@ -55,6 +55,7 @@ const Chat = forwardRef<ChatRef, { appId: string; graphRef: GraphRef }>(({ appId
|
|||||||
setOpen(false)
|
setOpen(false)
|
||||||
setChatList([])
|
setChatList([])
|
||||||
setVariables([])
|
setVariables([])
|
||||||
|
setConversationId(null)
|
||||||
}
|
}
|
||||||
const handleEditVariables = () => {
|
const handleEditVariables = () => {
|
||||||
variableConfigModalRef.current?.handleOpen(variables)
|
variableConfigModalRef.current?.handleOpen(variables)
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
const handleNodeSelect = (selectedNodeType: any) => {
|
const handleNodeSelect = (selectedNodeType: any) => {
|
||||||
const parentBBox = node.getBBox();
|
const parentBBox = node.getBBox();
|
||||||
const cycleId = data.cycle;
|
const cycleId = data.cycle;
|
||||||
|
const horizontalSpacing = 20;
|
||||||
|
|
||||||
const id = `${selectedNodeType.type.replace(/-/g, '_') }_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
const id = `${selectedNodeType.type.replace(/-/g, '_') }_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||||||
const newNode = graph.addNode({
|
const newNode = graph.addNode({
|
||||||
...(graphNodeLibrary[selectedNodeType.type] || graphNodeLibrary.default),
|
...(graphNodeLibrary[selectedNodeType.type] || graphNodeLibrary.default),
|
||||||
x: parentBBox.x,
|
x: parentBBox.x + horizontalSpacing,
|
||||||
y: parentBBox.y,
|
y: parentBBox.y,
|
||||||
id,
|
id,
|
||||||
data: {
|
data: {
|
||||||
@@ -35,7 +36,7 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
if (cycleId) {
|
if (cycleId) {
|
||||||
const parentNode = graph.getNodes().find((n: any) => n.getData()?.id === cycleId);
|
const parentNode = graph.getNodes().find((n: any) => n.getData()?.id === cycleId);
|
||||||
if (parentNode) {
|
if (parentNode) {
|
||||||
parentNode.addChild(newNode);
|
parentNode.insertChild(newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
source: { cell: edge.getSourceCellId(), port: edge.getSourcePortId() },
|
source: { cell: edge.getSourceCellId(), port: edge.getSourcePortId() },
|
||||||
target: { cell: newNode.id, port: newNode.getPorts().find((port: any) => port.group === 'left')?.id || 'left' },
|
target: { cell: newNode.id, port: newNode.getPorts().find((port: any) => port.group === 'left')?.id || 'left' },
|
||||||
attrs: edge.getAttrs(),
|
attrs: edge.getAttrs(),
|
||||||
zIndex: 3
|
zIndex: 1,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
source: { cell: newNode.id, port: newNode.getPorts().find((port: any) => port.group === 'right')?.id || 'right' },
|
source: { cell: newNode.id, port: newNode.getPorts().find((port: any) => port.group === 'right')?.id || 'right' },
|
||||||
target: { cell: edge.getTargetCellId(), port: targetPortId },
|
target: { cell: edge.getTargetCellId(), port: targetPortId },
|
||||||
attrs: edge.getAttrs(),
|
attrs: edge.getAttrs(),
|
||||||
zIndex: 3
|
zIndex: 1,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initNodes()
|
// 使用setTimeout确保在所有节点都添加完成后再创建连线
|
||||||
// 检查是否需要添加add-node
|
const timer = setTimeout(() => {
|
||||||
checkAndAddAddNode()
|
initNodes()
|
||||||
|
checkAndAddAddNode()
|
||||||
|
}, 50)
|
||||||
|
|
||||||
|
return () => clearTimeout(timer)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const checkAndAddAddNode = () => {
|
const checkAndAddAddNode = () => {
|
||||||
@@ -29,7 +33,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
|
|
||||||
const addNode = graph.addNode({
|
const addNode = graph.addNode({
|
||||||
...graphNodeLibrary.addStart,
|
...graphNodeLibrary.addStart,
|
||||||
x: cycleStartBBox.x + 64,
|
x: cycleStartBBox.x + 84,
|
||||||
y: cycleStartBBox.y,
|
y: cycleStartBBox.y,
|
||||||
data: {
|
data: {
|
||||||
type: 'add-node',
|
type: 'add-node',
|
||||||
@@ -40,7 +44,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
node.addChild(addNode);
|
node.insertChild(addNode);
|
||||||
|
|
||||||
// 连接cycle-start和add-node
|
// 连接cycle-start和add-node
|
||||||
const sourcePorts = cycleStartNode.getPorts();
|
const sourcePorts = cycleStartNode.getPorts();
|
||||||
@@ -48,6 +52,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
const sourcePort = sourcePorts.find((port: any) => port.group === 'right')?.id || 'right';
|
const sourcePort = sourcePorts.find((port: any) => port.group === 'right')?.id || 'right';
|
||||||
const targetPort = targetPorts.find((port: any) => port.group === 'left')?.id || 'left';
|
const targetPort = targetPorts.find((port: any) => port.group === 'left')?.id || 'left';
|
||||||
|
|
||||||
|
// 直接创建连线,不使用异步
|
||||||
graph.addEdge({
|
graph.addEdge({
|
||||||
source: { cell: cycleStartNode.id, port: sourcePort },
|
source: { cell: cycleStartNode.id, port: sourcePort },
|
||||||
target: { cell: addNode.id, port: targetPort },
|
target: { cell: addNode.id, port: targetPort },
|
||||||
@@ -61,7 +66,6 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
zIndex: 10
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +97,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
});
|
});
|
||||||
const addNode = graph.addNode({
|
const addNode = graph.addNode({
|
||||||
...graphNodeLibrary.addStart,
|
...graphNodeLibrary.addStart,
|
||||||
x: centerX + 64,
|
x: centerX + 84,
|
||||||
y: centerY,
|
y: centerY,
|
||||||
data: {
|
data: {
|
||||||
type: 'add-node',
|
type: 'add-node',
|
||||||
@@ -103,8 +107,8 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
cycle: data.id,
|
cycle: data.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
node.addChild(cycleStartNode)
|
node.insertChild(cycleStartNode)
|
||||||
node.addChild(addNode)
|
node.insertChild(addNode)
|
||||||
const sourcePorts = cycleStartNode.getPorts()
|
const sourcePorts = cycleStartNode.getPorts()
|
||||||
const targetPorts = addNode.getPorts()
|
const targetPorts = addNode.getPorts()
|
||||||
let sourcePort = sourcePorts.find((port: any) => port.group === 'right')?.id || 'right';
|
let sourcePort = sourcePorts.find((port: any) => port.group === 'right')?.id || 'right';
|
||||||
@@ -124,11 +128,10 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
|||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
targetMarker: {
|
targetMarker: {
|
||||||
name: 'block',
|
name: 'block',
|
||||||
size: 8,
|
size: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
zIndex: 10
|
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.addEdge(edgeConfig)
|
graph.addEdge(edgeConfig)
|
||||||
|
|||||||
@@ -36,11 +36,77 @@ const PortClickHandler: React.FC<PortClickHandlerProps> = ({ graph }) => {
|
|||||||
if (!sourceNode || !graph) return;
|
if (!sourceNode || !graph) return;
|
||||||
|
|
||||||
const sourceNodeData = sourceNode.getData();
|
const sourceNodeData = sourceNode.getData();
|
||||||
|
const sourceNodeType = sourceNodeData?.type;
|
||||||
|
|
||||||
// 计算新节点位置(在源节点右侧)
|
// 如果是cycle-start节点,需要处理add-node节点
|
||||||
|
let addNodePosition = null;
|
||||||
|
if (sourceNodeType === 'cycle-start' && sourceNodeData.cycle) {
|
||||||
|
const cycleId = sourceNodeData.cycle;
|
||||||
|
const addNodes = graph.getNodes().filter((n: any) =>
|
||||||
|
n.getData()?.type === 'add-node' && n.getData()?.cycle === cycleId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (addNodes.length > 0) {
|
||||||
|
const addNode = addNodes[0];
|
||||||
|
addNodePosition = addNode.getBBox();
|
||||||
|
addNode.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算新节点位置,避免重叠
|
||||||
const sourceBBox = sourceNode.getBBox();
|
const sourceBBox = sourceNode.getBBox();
|
||||||
const newX = sourceBBox.x + sourceBBox.width + 50;
|
const nodeWidth = graphNodeLibrary[selectedNodeType.type]?.width || 120;
|
||||||
const newY = sourceBBox.y;
|
const nodeHeight = graphNodeLibrary[selectedNodeType.type]?.height || 88;
|
||||||
|
const horizontalSpacing = sourceNodeType === 'cycle-start' ? 40 : 80;
|
||||||
|
const verticalSpacing = 10;
|
||||||
|
|
||||||
|
// 获取源连接桩的group信息
|
||||||
|
const sourcePortInfo = sourceNode.getPorts().find((p: any) => p.id === sourcePort);
|
||||||
|
const sourcePortGroup = sourcePortInfo?.group || sourcePort;
|
||||||
|
console.log('sourcePortGroup', sourcePortGroup, sourcePortInfo)
|
||||||
|
|
||||||
|
// 如果有add-node位置,使用该位置,否则计算新位置
|
||||||
|
let newX, newY;
|
||||||
|
if (addNodePosition) {
|
||||||
|
newX = addNodePosition.x;
|
||||||
|
newY = addNodePosition.y;
|
||||||
|
} else {
|
||||||
|
// 根据连接桩位置决定节点放置方向
|
||||||
|
if (sourcePortGroup === 'left') {
|
||||||
|
// 左侧连接桩,在左侧添加节点
|
||||||
|
newX = sourceBBox.x - nodeWidth*2 - horizontalSpacing;
|
||||||
|
newY = sourceBBox.y;
|
||||||
|
} else {
|
||||||
|
// 右侧连接桩,在右侧添加节点
|
||||||
|
newX = sourceBBox.x + sourceBBox.width + horizontalSpacing;
|
||||||
|
newY = sourceBBox.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查位置是否与现有节点重叠(只考虑与当前节点相连的节点)
|
||||||
|
const checkOverlap = (x: number, y: number) => {
|
||||||
|
// 获取与源节点相连的节点
|
||||||
|
const connectedNodes = new Set();
|
||||||
|
graph.getConnectedEdges(sourceNode).forEach((edge: any) => {
|
||||||
|
const sourceId = edge.getSourceCellId();
|
||||||
|
const targetId = edge.getTargetCellId();
|
||||||
|
if (sourceId !== sourceNode.id) connectedNodes.add(sourceId);
|
||||||
|
if (targetId !== sourceNode.id) connectedNodes.add(targetId);
|
||||||
|
});
|
||||||
|
|
||||||
|
return graph.getNodes().some((node: any) => {
|
||||||
|
if (node.id === sourceNode.id) return false;
|
||||||
|
if (!connectedNodes.has(node.id)) return false; // 只考虑相连的节点
|
||||||
|
const bbox = node.getBBox();
|
||||||
|
return !(x + nodeWidth < bbox.x || x > bbox.x + bbox.width ||
|
||||||
|
y + nodeHeight < bbox.y || y > bbox.y + bbox.height);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果位置被占用,向下寻找空位
|
||||||
|
while (checkOverlap(newX, newY)) {
|
||||||
|
newY += nodeHeight + verticalSpacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 创建新节点
|
// 创建新节点
|
||||||
const id = `${selectedNodeType.type.replace(/-/g, '_')}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
const id = `${selectedNodeType.type.replace(/-/g, '_')}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||||||
@@ -63,14 +129,22 @@ const PortClickHandler: React.FC<PortClickHandlerProps> = ({ graph }) => {
|
|||||||
if (sourceNodeData.cycle) {
|
if (sourceNodeData.cycle) {
|
||||||
const parentNode = graph.getNodes().find((n: any) => n.getData()?.id === sourceNodeData.cycle);
|
const parentNode = graph.getNodes().find((n: any) => n.getData()?.id === sourceNodeData.cycle);
|
||||||
if (parentNode) {
|
if (parentNode) {
|
||||||
parentNode.addChild(newNode);
|
parentNode.insertChild(newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建连线
|
// 创建连线
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const targetPorts = newNode.getPorts();
|
const targetPorts = newNode.getPorts();
|
||||||
const targetPort = targetPorts.find((port: any) => port.group === 'left')?.id || 'left';
|
let targetPort;
|
||||||
|
|
||||||
|
if (sourcePortGroup === 'left') {
|
||||||
|
// 从左侧连接桩连出,连接到新节点的右侧
|
||||||
|
targetPort = targetPorts.find((port: any) => port.group === 'right')?.id || 'right';
|
||||||
|
} else {
|
||||||
|
// 从右侧连接桩连出,连接到新节点的左侧
|
||||||
|
targetPort = targetPorts.find((port: any) => port.group === 'left')?.id || 'left';
|
||||||
|
}
|
||||||
|
|
||||||
graph.addEdge({
|
graph.addEdge({
|
||||||
source: { cell: sourceNode.id, port: sourcePort },
|
source: { cell: sourceNode.id, port: sourcePort },
|
||||||
@@ -85,7 +159,7 @@ const PortClickHandler: React.FC<PortClickHandlerProps> = ({ graph }) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
zIndex: 0
|
zIndex: sourceNodeData.cycle && sourceNodeType == 'cycle-start' ? 1 : sourceNodeData.cycle ? 2 : 0
|
||||||
});
|
});
|
||||||
|
|
||||||
// 循环节点内子节点通过连接桩添加时,调整循环节点大小
|
// 循环节点内子节点通过连接桩添加时,调整循环节点大小
|
||||||
@@ -108,8 +182,9 @@ const PortClickHandler: React.FC<PortClickHandlerProps> = ({ graph }) => {
|
|||||||
}, { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity });
|
}, { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity });
|
||||||
|
|
||||||
const padding = 20;
|
const padding = 20;
|
||||||
|
const bottomPadding = 50;
|
||||||
const newWidth = Math.max(240, bounds.maxX - bounds.minX + padding * 2);
|
const newWidth = Math.max(240, bounds.maxX - bounds.minX + padding * 2);
|
||||||
const newHeight = Math.max(120, bounds.maxY - bounds.minY + padding * 2);
|
const newHeight = Math.max(120, bounds.maxY - bounds.minY + padding + bottomPadding);
|
||||||
|
|
||||||
parentNode.prop('size', { width: newWidth, height: newHeight });
|
parentNode.prop('size', { width: newWidth, height: newHeight });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ export const useWorkflowGraph = ({
|
|||||||
if (parentNode) {
|
if (parentNode) {
|
||||||
const addedChild = graphRef.current?.addNode(childNode)
|
const addedChild = graphRef.current?.addNode(childNode)
|
||||||
if (addedChild) {
|
if (addedChild) {
|
||||||
parentNode.addChild(addedChild)
|
parentNode.insertChild(addedChild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,6 +275,11 @@ export const useWorkflowGraph = ({
|
|||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
if (edges.length) {
|
if (edges.length) {
|
||||||
|
// 计算loop和iteration类型节点的数量
|
||||||
|
const loopIterationCount = nodes.filter(node =>
|
||||||
|
node.type === 'loop' || node.type === 'iteration'
|
||||||
|
).length;
|
||||||
|
|
||||||
// 去重处理:对于if-else和question-classifier节点,不同连接桩允许连接到相同节点
|
// 去重处理:对于if-else和question-classifier节点,不同连接桩允许连接到相同节点
|
||||||
const uniqueEdges = edges.filter((edge, index, arr) => {
|
const uniqueEdges = edges.filter((edge, index, arr) => {
|
||||||
return arr.findIndex(e => {
|
return arr.findIndex(e => {
|
||||||
@@ -349,7 +354,7 @@ export const useWorkflowGraph = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
zIndex: targetCell.getData()?.cycle ? 3 : 0
|
zIndex: loopIterationCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return edgeConfig
|
return edgeConfig
|
||||||
@@ -725,7 +730,6 @@ export const useWorkflowGraph = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
zIndex: 0,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
validateConnection({ sourceCell, targetCell, targetMagnet }) {
|
validateConnection({ sourceCell, targetCell, targetMagnet }) {
|
||||||
@@ -762,9 +766,8 @@ export const useWorkflowGraph = ({
|
|||||||
},
|
},
|
||||||
embedding: {
|
embedding: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
validate (this, { parent }) {
|
validate (this) {
|
||||||
const parentData = parent.getData()
|
return false
|
||||||
return parentData.type === 'iteration' || parentData.type === 'loop'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
translating: {
|
translating: {
|
||||||
|
|||||||
Reference in New Issue
Block a user