mirror of
https://github.com/langgenius/dify.git
synced 2026-04-27 02:36:29 +08:00
fix
This commit is contained in:
parent
ae9e7acd77
commit
8b2a63e545
@ -3,10 +3,51 @@
|
|||||||
import { memo } from 'react'
|
import { memo } from 'react'
|
||||||
import Workflow from '@/app/components/workflow'
|
import Workflow from '@/app/components/workflow'
|
||||||
|
|
||||||
|
// export function createNodesAndEdges(xNodes = 10, yNodes = 10) {
|
||||||
|
// const nodes = []
|
||||||
|
// const edges = []
|
||||||
|
// let nodeId = 1
|
||||||
|
// let recentNodeId = null
|
||||||
|
|
||||||
|
// for (let y = 0; y < yNodes; y++) {
|
||||||
|
// for (let x = 0; x < xNodes; x++) {
|
||||||
|
// const position = { x: x * 200, y: y * 50 }
|
||||||
|
// const node = {
|
||||||
|
// id: `stress-${nodeId.toString()}`,
|
||||||
|
// type: 'custom',
|
||||||
|
// data: { type: 'start', title: '开始', variables: [] },
|
||||||
|
// position,
|
||||||
|
// }
|
||||||
|
// nodes.push(node)
|
||||||
|
|
||||||
|
// if (recentNodeId && nodeId <= xNodes * yNodes) {
|
||||||
|
// edges.push({
|
||||||
|
// id: `${x}-${y}`,
|
||||||
|
// type: 'custom',
|
||||||
|
// source: `stress-${recentNodeId.toString()}`,
|
||||||
|
// target: `stress-${nodeId.toString()}`,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// recentNodeId = nodeId
|
||||||
|
// nodeId++
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return { nodes, edges }
|
||||||
|
// }
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
|
// const {
|
||||||
|
// nodes,
|
||||||
|
// edges,
|
||||||
|
// } = createNodesAndEdges()
|
||||||
return (
|
return (
|
||||||
<div className='w-full h-full overflow-x-auto'>
|
<div className='w-full h-full overflow-x-auto'>
|
||||||
<Workflow />
|
<Workflow
|
||||||
|
// nodes={nodes}
|
||||||
|
// edges={edges}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import type {
|
|||||||
} from 'reactflow'
|
} from 'reactflow'
|
||||||
import { useStoreApi } from 'reactflow'
|
import { useStoreApi } from 'reactflow'
|
||||||
import { useStore } from '../store'
|
import { useStore } from '../store'
|
||||||
|
import type { Node } from '../types'
|
||||||
import { useNodesSyncDraft } from './use-nodes-sync-draft'
|
import { useNodesSyncDraft } from './use-nodes-sync-draft'
|
||||||
|
|
||||||
export const useEdgesInteractions = () => {
|
export const useEdgesInteractions = () => {
|
||||||
@ -55,14 +56,26 @@ export const useEdgesInteractions = () => {
|
|||||||
return
|
return
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
getNodes,
|
||||||
|
setNodes,
|
||||||
edges,
|
edges,
|
||||||
setEdges,
|
setEdges,
|
||||||
} = store.getState()
|
} = store.getState()
|
||||||
const newEdges = produce(edges, (draft) => {
|
const currentEdgeIndex = edges.findIndex(edge => edge.source === nodeId && edge.sourceHandle === branchId)
|
||||||
const index = draft.findIndex(edge => edge.source === nodeId && edge.sourceHandle === branchId)
|
const currentEdge = edges[currentEdgeIndex]
|
||||||
|
const newNodes = produce(getNodes(), (draft: Node[]) => {
|
||||||
|
const sourceNode = draft.find(node => node.id === currentEdge.source)
|
||||||
|
const targetNode = draft.find(node => node.id === currentEdge.target)
|
||||||
|
|
||||||
if (index > -1)
|
if (sourceNode)
|
||||||
draft.splice(index, 1)
|
sourceNode.data._connectedSourceHandleIds = sourceNode.data._connectedSourceHandleIds?.filter(handleId => handleId !== currentEdge.sourceHandle)
|
||||||
|
|
||||||
|
if (targetNode)
|
||||||
|
targetNode.data._connectedTargetHandleIds = targetNode.data._connectedTargetHandleIds?.filter(handleId => handleId !== currentEdge.targetHandle)
|
||||||
|
})
|
||||||
|
setNodes(newNodes)
|
||||||
|
const newEdges = produce(edges, (draft) => {
|
||||||
|
draft.splice(currentEdgeIndex, 1)
|
||||||
})
|
})
|
||||||
setEdges(newEdges)
|
setEdges(newEdges)
|
||||||
handleSyncWorkflowDraft()
|
handleSyncWorkflowDraft()
|
||||||
@ -75,14 +88,26 @@ export const useEdgesInteractions = () => {
|
|||||||
return
|
return
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
getNodes,
|
||||||
|
setNodes,
|
||||||
edges,
|
edges,
|
||||||
setEdges,
|
setEdges,
|
||||||
} = store.getState()
|
} = store.getState()
|
||||||
const newEdges = produce(edges, (draft) => {
|
const currentEdgeIndex = edges.findIndex(edge => edge.selected)
|
||||||
const index = draft.findIndex(edge => edge.selected)
|
const currentEdge = edges[currentEdgeIndex]
|
||||||
|
const newNodes = produce(getNodes(), (draft: Node[]) => {
|
||||||
|
const sourceNode = draft.find(node => node.id === currentEdge.source)
|
||||||
|
const targetNode = draft.find(node => node.id === currentEdge.target)
|
||||||
|
|
||||||
if (index > -1)
|
if (sourceNode)
|
||||||
draft.splice(index, 1)
|
sourceNode.data._connectedSourceHandleIds = sourceNode.data._connectedSourceHandleIds?.filter(handleId => handleId !== currentEdge.sourceHandle)
|
||||||
|
|
||||||
|
if (targetNode)
|
||||||
|
targetNode.data._connectedTargetHandleIds = targetNode.data._connectedTargetHandleIds?.filter(handleId => handleId !== currentEdge.targetHandle)
|
||||||
|
})
|
||||||
|
setNodes(newNodes)
|
||||||
|
const newEdges = produce(edges, (draft) => {
|
||||||
|
draft.splice(currentEdgeIndex, 1)
|
||||||
})
|
})
|
||||||
setEdges(newEdges)
|
setEdges(newEdges)
|
||||||
handleSyncWorkflowDraft()
|
handleSyncWorkflowDraft()
|
||||||
|
|||||||
@ -260,9 +260,8 @@ export const useNodesInteractions = () => {
|
|||||||
edges,
|
edges,
|
||||||
setEdges,
|
setEdges,
|
||||||
} = store.getState()
|
} = store.getState()
|
||||||
|
|
||||||
const newEdges = produce(edges, (draft) => {
|
const newEdges = produce(edges, (draft) => {
|
||||||
const filtered = draft.filter(edge => edge.source !== source && edge.target !== target)
|
const filtered = draft.filter(edge => (edge.source !== source && edge.sourceHandle !== sourceHandle) || (edge.target !== target && edge.targetHandle !== targetHandle))
|
||||||
|
|
||||||
filtered.push({
|
filtered.push({
|
||||||
id: `${source}-${target}`,
|
id: `${source}-${target}`,
|
||||||
@ -292,14 +291,25 @@ export const useNodesInteractions = () => {
|
|||||||
setEdges,
|
setEdges,
|
||||||
} = store.getState()
|
} = store.getState()
|
||||||
|
|
||||||
const newNodes = produce(getNodes(), (draft) => {
|
const nodes = getNodes()
|
||||||
const index = draft.findIndex(node => node.id === nodeId)
|
const currentNodeIndex = nodes.findIndex(node => node.id === nodeId)
|
||||||
|
const currentNode = nodes[currentNodeIndex]
|
||||||
|
const incomersIds = getIncomers(currentNode, nodes, edges).map(incomer => incomer.id)
|
||||||
|
const outgoersIds = getOutgoers(currentNode, nodes, edges).map(outgoer => outgoer.id)
|
||||||
|
const connectedEdges = getConnectedEdges([{ id: nodeId } as Node], edges)
|
||||||
|
const sourceEdgesHandleIds = connectedEdges.filter(edge => edge.target === nodeId).map(edge => edge.sourceHandle)
|
||||||
|
const targetEdgesHandleIds = connectedEdges.filter(edge => edge.source === nodeId).map(edge => edge.targetHandle)
|
||||||
|
const newNodes = produce(nodes, (draft: Node[]) => {
|
||||||
|
draft.forEach((node) => {
|
||||||
|
if (incomersIds.includes(node.id))
|
||||||
|
node.data._connectedSourceHandleIds = node.data._connectedSourceHandleIds?.filter(handleId => !sourceEdgesHandleIds.includes(handleId))
|
||||||
|
|
||||||
if (index > -1)
|
if (outgoersIds.includes(node.id))
|
||||||
draft.splice(index, 1)
|
node.data._connectedTargetHandleIds = node.data._connectedTargetHandleIds?.filter(handleId => !targetEdgesHandleIds.includes(handleId))
|
||||||
|
})
|
||||||
|
draft.splice(currentNodeIndex, 1)
|
||||||
})
|
})
|
||||||
setNodes(newNodes)
|
setNodes(newNodes)
|
||||||
const connectedEdges = getConnectedEdges([{ id: nodeId } as Node], edges)
|
|
||||||
const newEdges = produce(edges, (draft) => {
|
const newEdges = produce(edges, (draft) => {
|
||||||
return draft.filter(edge => !connectedEdges.find(connectedEdge => connectedEdge.id === edge.id))
|
return draft.filter(edge => !connectedEdges.find(connectedEdge => connectedEdge.id === edge.id))
|
||||||
})
|
})
|
||||||
@ -325,7 +335,8 @@ export const useNodesInteractions = () => {
|
|||||||
setEdges,
|
setEdges,
|
||||||
} = store.getState()
|
} = store.getState()
|
||||||
const nodes = getNodes()
|
const nodes = getNodes()
|
||||||
const currentNode = nodes.find(node => node.id === currentNodeId)!
|
const currentNodeIndex = nodes.findIndex(node => node.id === currentNodeId)
|
||||||
|
const currentNode = nodes[currentNodeIndex]
|
||||||
const outgoers = getOutgoers(currentNode, nodes, edges).sort((a, b) => a.position.y - b.position.y)
|
const outgoers = getOutgoers(currentNode, nodes, edges).sort((a, b) => a.position.y - b.position.y)
|
||||||
const lastOutgoer = outgoers[outgoers.length - 1]
|
const lastOutgoer = outgoers[outgoers.length - 1]
|
||||||
const nextNode: Node = {
|
const nextNode: Node = {
|
||||||
@ -334,6 +345,7 @@ export const useNodesInteractions = () => {
|
|||||||
data: {
|
data: {
|
||||||
...nodesInitialData[nodeType],
|
...nodesInitialData[nodeType],
|
||||||
...(toolDefaultValue || {}),
|
...(toolDefaultValue || {}),
|
||||||
|
_connectedTargetHandleIds: ['target'],
|
||||||
selected: true,
|
selected: true,
|
||||||
},
|
},
|
||||||
position: {
|
position: {
|
||||||
@ -350,9 +362,12 @@ export const useNodesInteractions = () => {
|
|||||||
target: nextNode.id,
|
target: nextNode.id,
|
||||||
targetHandle: 'target',
|
targetHandle: 'target',
|
||||||
}
|
}
|
||||||
const newNodes = produce(nodes, (draft) => {
|
const newNodes = produce(nodes, (draft: Node[]) => {
|
||||||
draft.forEach((node) => {
|
draft.forEach((node, index) => {
|
||||||
node.data.selected = false
|
node.data.selected = false
|
||||||
|
|
||||||
|
if (index === currentNodeIndex)
|
||||||
|
node.data._connectedSourceHandleIds?.push(sourceHandle)
|
||||||
})
|
})
|
||||||
draft.push(nextNode)
|
draft.push(nextNode)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -182,7 +182,7 @@ const WorkflowWrap: FC<WorkflowProps> = ({
|
|||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
return initialNodes(data.graph.nodes)
|
return initialNodes(data.graph.nodes, data.graph.edges)
|
||||||
|
|
||||||
return [startNode]
|
return [startNode]
|
||||||
}, [data, nodes, startNode])
|
}, [data, nodes, startNode])
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
import type { MouseEvent } from 'react'
|
import type { MouseEvent } from 'react'
|
||||||
import {
|
import {
|
||||||
|
memo,
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import type { NodeProps } from 'reactflow'
|
|
||||||
import {
|
import {
|
||||||
Handle,
|
Handle,
|
||||||
Position,
|
Position,
|
||||||
getConnectedEdges,
|
|
||||||
useEdges,
|
|
||||||
} from 'reactflow'
|
} from 'reactflow'
|
||||||
import { BlockEnum } from '../../../types'
|
import { BlockEnum } from '../../../types'
|
||||||
import type { Node } from '../../../types'
|
import type { Node } from '../../../types'
|
||||||
@ -22,9 +20,9 @@ type NodeHandleProps = {
|
|||||||
handleId: string
|
handleId: string
|
||||||
handleClassName?: string
|
handleClassName?: string
|
||||||
nodeSelectorClassName?: string
|
nodeSelectorClassName?: string
|
||||||
} & Pick<NodeProps, 'id' | 'data'>
|
} & Pick<Node, 'id' | 'data'>
|
||||||
|
|
||||||
export const NodeTargetHandle = ({
|
export const NodeTargetHandle = memo(({
|
||||||
id,
|
id,
|
||||||
data,
|
data,
|
||||||
handleId,
|
handleId,
|
||||||
@ -33,9 +31,7 @@ export const NodeTargetHandle = ({
|
|||||||
}: NodeHandleProps) => {
|
}: NodeHandleProps) => {
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { handleNodeAddPrev } = useNodesInteractions()
|
const { handleNodeAddPrev } = useNodesInteractions()
|
||||||
const edges = useEdges()
|
const connected = data._connectedTargetHandleIds?.includes(handleId)
|
||||||
const connectedEdges = getConnectedEdges([{ id } as Node], edges)
|
|
||||||
const connected = connectedEdges.find(edge => edge.targetHandle === handleId && edge.target === id)
|
|
||||||
|
|
||||||
const handleOpenChange = useCallback((v: boolean) => {
|
const handleOpenChange = useCallback((v: boolean) => {
|
||||||
setOpen(v)
|
setOpen(v)
|
||||||
@ -85,9 +81,10 @@ export const NodeTargetHandle = ({
|
|||||||
</Handle>
|
</Handle>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
NodeTargetHandle.displayName = 'NodeTargetHandle'
|
||||||
|
|
||||||
export const NodeSourceHandle = ({
|
export const NodeSourceHandle = memo(({
|
||||||
id,
|
id,
|
||||||
data,
|
data,
|
||||||
handleId,
|
handleId,
|
||||||
@ -97,9 +94,7 @@ export const NodeSourceHandle = ({
|
|||||||
const notInitialWorkflow = useStore(s => s.notInitialWorkflow)
|
const notInitialWorkflow = useStore(s => s.notInitialWorkflow)
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { handleNodeAddNext } = useNodesInteractions()
|
const { handleNodeAddNext } = useNodesInteractions()
|
||||||
const edges = useEdges()
|
const connected = data._connectedSourceHandleIds?.includes(handleId)
|
||||||
const connectedEdges = getConnectedEdges([{ id } as Node], edges)
|
|
||||||
const connected = connectedEdges.find(edge => edge.sourceHandle === handleId && edge.source === id)
|
|
||||||
const handleOpenChange = useCallback((v: boolean) => {
|
const handleOpenChange = useCallback((v: boolean) => {
|
||||||
setOpen(v)
|
setOpen(v)
|
||||||
}, [])
|
}, [])
|
||||||
@ -150,4 +145,5 @@ export const NodeSourceHandle = ({
|
|||||||
</Handle>
|
</Handle>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
NodeSourceHandle.displayName = 'NodeSourceHandle'
|
||||||
|
|||||||
@ -47,6 +47,7 @@ const BaseNode: FC<BaseNodeProps> = ({
|
|||||||
${data._runningStatus === NodeRunningStatus.Running && '!border-primary-500'}
|
${data._runningStatus === NodeRunningStatus.Running && '!border-primary-500'}
|
||||||
${data._runningStatus === NodeRunningStatus.Succeeded && '!border-[#12B76A]'}
|
${data._runningStatus === NodeRunningStatus.Succeeded && '!border-[#12B76A]'}
|
||||||
${data._runningStatus === NodeRunningStatus.Failed && '!border-[#F04438]'}
|
${data._runningStatus === NodeRunningStatus.Failed && '!border-[#F04438]'}
|
||||||
|
${data._runningStatus === NodeRunningStatus.Waiting && 'opacity-70'}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -94,7 +94,10 @@ const ZoomInOut: FC = () => {
|
|||||||
placement='top-start'
|
placement='top-start'
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={setOpen}
|
onOpenChange={setOpen}
|
||||||
offset={4}
|
offset={{
|
||||||
|
mainAxis: 4,
|
||||||
|
crossAxis: -2,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<PortalToFollowElemTrigger asChild onClick={handleTrigger}>
|
<PortalToFollowElemTrigger asChild onClick={handleTrigger}>
|
||||||
<div className={`
|
<div className={`
|
||||||
|
|||||||
@ -25,6 +25,8 @@ export type Branch = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type CommonNodeType<T = {}> = {
|
export type CommonNodeType<T = {}> = {
|
||||||
|
_connectedSourceHandleIds?: string[]
|
||||||
|
_connectedTargetHandleIds?: string[]
|
||||||
_targetBranches?: Branch[]
|
_targetBranches?: Branch[]
|
||||||
_isSingleRun?: boolean
|
_isSingleRun?: boolean
|
||||||
_runningStatus?: NodeRunningStatus
|
_runningStatus?: NodeRunningStatus
|
||||||
|
|||||||
@ -80,10 +80,14 @@ export const nodesLevelOrderTraverse = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialNodes = (nodes: Node[]) => {
|
export const initialNodes = (nodes: Node[], edges: Edge[]) => {
|
||||||
return nodes.map((node) => {
|
return nodes.map((node) => {
|
||||||
node.type = 'custom'
|
node.type = 'custom'
|
||||||
|
|
||||||
|
const connectedEdges = getConnectedEdges([node], edges)
|
||||||
|
node.data._connectedSourceHandleIds = connectedEdges.filter(edge => edge.source === node.id).map(edge => edge.sourceHandle || 'source')
|
||||||
|
node.data._connectedTargetHandleIds = connectedEdges.filter(edge => edge.target === node.id).map(edge => edge.targetHandle || 'target')
|
||||||
|
|
||||||
if (node.data.type === BlockEnum.IfElse) {
|
if (node.data.type === BlockEnum.IfElse) {
|
||||||
node.data._targetBranches = [
|
node.data._targetBranches = [
|
||||||
{
|
{
|
||||||
@ -170,3 +174,10 @@ export const canRunBySingle = (nodeType: BlockEnum) => {
|
|||||||
|| nodeType === BlockEnum.HttpRequest
|
|| nodeType === BlockEnum.HttpRequest
|
||||||
|| nodeType === BlockEnum.Tool
|
|| nodeType === BlockEnum.Tool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConnectedSourceOrTargetNodesChange = {
|
||||||
|
type: 'add' | 'remove'
|
||||||
|
edge: Edge
|
||||||
|
}[]
|
||||||
|
export const getConnectedSourceOrTargetNodesChangeList = (changes: ConnectedSourceOrTargetNodesChange, nodes: Node[], edges: Edge[]) => {
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user