mirror of
https://github.com/langgenius/dify.git
synced 2026-05-01 22:47:15 +08:00
fix
This commit is contained in:
parent
8ae46a8a14
commit
547df0b5fe
@ -155,6 +155,7 @@ export const NODES_INITIAL_DATA = {
|
|||||||
|
|
||||||
export const NODE_WIDTH = 220
|
export const NODE_WIDTH = 220
|
||||||
export const X_OFFSET = 64
|
export const X_OFFSET = 64
|
||||||
|
export const NODE_WIDTH_X_OFFSET = NODE_WIDTH + X_OFFSET
|
||||||
export const Y_OFFSET = 39
|
export const Y_OFFSET = 39
|
||||||
export const TREE_DEEPTH = 20
|
export const TREE_DEEPTH = 20
|
||||||
|
|
||||||
|
|||||||
@ -14,20 +14,21 @@ import {
|
|||||||
Position,
|
Position,
|
||||||
getConnectedEdges,
|
getConnectedEdges,
|
||||||
getIncomers,
|
getIncomers,
|
||||||
|
getOutgoers,
|
||||||
useReactFlow,
|
useReactFlow,
|
||||||
useStoreApi,
|
useStoreApi,
|
||||||
} from 'reactflow'
|
} from 'reactflow'
|
||||||
import type {
|
import type { Node } from './types'
|
||||||
BlockEnum,
|
|
||||||
Node,
|
|
||||||
} from './types'
|
|
||||||
import {
|
import {
|
||||||
|
BlockEnum,
|
||||||
NodeRunningStatus,
|
NodeRunningStatus,
|
||||||
WorkflowRunningStatus,
|
WorkflowRunningStatus,
|
||||||
} from './types'
|
} from './types'
|
||||||
import {
|
import {
|
||||||
NODES_EXTRA_DATA,
|
NODES_EXTRA_DATA,
|
||||||
NODES_INITIAL_DATA,
|
NODES_INITIAL_DATA,
|
||||||
|
NODE_WIDTH_X_OFFSET,
|
||||||
|
Y_OFFSET,
|
||||||
} from './constants'
|
} from './constants'
|
||||||
import { getLayoutByDagre } from './utils'
|
import { getLayoutByDagre } from './utils'
|
||||||
import { useStore } from './store'
|
import { useStore } from './store'
|
||||||
@ -468,6 +469,8 @@ export const useWorkflow = () => {
|
|||||||
} = store.getState()
|
} = store.getState()
|
||||||
const nodes = getNodes()
|
const nodes = getNodes()
|
||||||
const currentNode = nodes.find(node => node.id === currentNodeId)!
|
const currentNode = nodes.find(node => node.id === currentNodeId)!
|
||||||
|
const outgoers = getOutgoers(currentNode, nodes, edges).sort((a, b) => a.position.y - b.position.y)
|
||||||
|
const lastOutgoer = outgoers[outgoers.length - 1]
|
||||||
const nextNode: Node = {
|
const nextNode: Node = {
|
||||||
id: `${Date.now()}`,
|
id: `${Date.now()}`,
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
@ -477,8 +480,8 @@ export const useWorkflow = () => {
|
|||||||
selected: true,
|
selected: true,
|
||||||
},
|
},
|
||||||
position: {
|
position: {
|
||||||
x: currentNode.position.x + 304,
|
x: lastOutgoer ? lastOutgoer.position.x : currentNode.position.x + NODE_WIDTH_X_OFFSET,
|
||||||
y: currentNode.position.y,
|
y: lastOutgoer ? lastOutgoer.position.y + lastOutgoer.height! + Y_OFFSET : currentNode.position.y,
|
||||||
},
|
},
|
||||||
targetPosition: Position.Left,
|
targetPosition: Position.Left,
|
||||||
}
|
}
|
||||||
@ -504,6 +507,69 @@ export const useWorkflow = () => {
|
|||||||
handleSyncWorkflowDraft()
|
handleSyncWorkflowDraft()
|
||||||
}, [store, nodesInitialData, handleSyncWorkflowDraft])
|
}, [store, nodesInitialData, handleSyncWorkflowDraft])
|
||||||
|
|
||||||
|
const handleNodeAddPrev = useCallback((
|
||||||
|
currentNodeId: string,
|
||||||
|
nodeType: BlockEnum,
|
||||||
|
targetHandle: string,
|
||||||
|
toolDefaultValue?: ToolDefaultValue,
|
||||||
|
) => {
|
||||||
|
const { runningStatus } = useStore.getState()
|
||||||
|
|
||||||
|
if (runningStatus)
|
||||||
|
return
|
||||||
|
|
||||||
|
const {
|
||||||
|
getNodes,
|
||||||
|
setNodes,
|
||||||
|
edges,
|
||||||
|
setEdges,
|
||||||
|
} = store.getState()
|
||||||
|
const nodes = getNodes()
|
||||||
|
const currentNodeIndex = nodes.findIndex(node => node.id === currentNodeId)
|
||||||
|
const currentNode = nodes[currentNodeIndex]
|
||||||
|
const prevNode: Node = {
|
||||||
|
id: `${Date.now()}`,
|
||||||
|
type: 'custom',
|
||||||
|
data: {
|
||||||
|
...nodesInitialData[nodeType],
|
||||||
|
...(toolDefaultValue || {}),
|
||||||
|
selected: true,
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
x: currentNode.position.x,
|
||||||
|
y: currentNode.position.y,
|
||||||
|
},
|
||||||
|
targetPosition: Position.Left,
|
||||||
|
}
|
||||||
|
const newNodes = produce(nodes, (draft) => {
|
||||||
|
draft.forEach((node, index) => {
|
||||||
|
node.data.selected = false
|
||||||
|
|
||||||
|
if (index === currentNodeIndex)
|
||||||
|
node.position.x += NODE_WIDTH_X_OFFSET
|
||||||
|
})
|
||||||
|
draft.push(prevNode)
|
||||||
|
})
|
||||||
|
setNodes(newNodes)
|
||||||
|
|
||||||
|
if (prevNode.type !== BlockEnum.IfElse && prevNode.type !== BlockEnum.QuestionClassifier) {
|
||||||
|
const newEdge = {
|
||||||
|
id: `${prevNode.id}-${currentNode.id}`,
|
||||||
|
type: 'custom',
|
||||||
|
source: prevNode.id,
|
||||||
|
sourceHandle: 'source',
|
||||||
|
target: currentNode.id,
|
||||||
|
targetHandle,
|
||||||
|
}
|
||||||
|
const newEdges = produce(edges, (draft) => {
|
||||||
|
draft.push(newEdge)
|
||||||
|
})
|
||||||
|
setEdges(newEdges)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSyncWorkflowDraft()
|
||||||
|
}, [store, nodesInitialData, handleSyncWorkflowDraft])
|
||||||
|
|
||||||
const handleNodeChange = useCallback((
|
const handleNodeChange = useCallback((
|
||||||
currentNodeId: string,
|
currentNodeId: string,
|
||||||
nodeType: BlockEnum,
|
nodeType: BlockEnum,
|
||||||
@ -691,6 +757,7 @@ export const useWorkflow = () => {
|
|||||||
handleNodeDelete,
|
handleNodeDelete,
|
||||||
handleNodeDataUpdate,
|
handleNodeDataUpdate,
|
||||||
handleNodeAddNext,
|
handleNodeAddNext,
|
||||||
|
handleNodeAddPrev,
|
||||||
handleNodeChange,
|
handleNodeChange,
|
||||||
|
|
||||||
handleEdgeEnter,
|
handleEdgeEnter,
|
||||||
|
|||||||
@ -4,21 +4,23 @@ import {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useWorkflow } from '../../../hooks'
|
import { useWorkflow } from '../../../hooks'
|
||||||
import type { Node } from '../../../types'
|
import type { Node } from '../../../types'
|
||||||
import { canRunBySingle } from '../../../utils'
|
import { canRunBySingle } from '../../../utils'
|
||||||
import PanelOperator from './panel-operator'
|
import PanelOperator from './panel-operator'
|
||||||
import { Loading02 } from '@/app/components/base/icons/src/vender/line/general'
|
|
||||||
import {
|
import {
|
||||||
Play,
|
Play,
|
||||||
Stop,
|
Stop,
|
||||||
} from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
} from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
||||||
|
import TooltipPlus from '@/app/components/base/tooltip-plus'
|
||||||
|
|
||||||
type NodeControlProps = Pick<Node, 'id' | 'data'>
|
type NodeControlProps = Pick<Node, 'id' | 'data'>
|
||||||
const NodeControl: FC<NodeControlProps> = ({
|
const NodeControl: FC<NodeControlProps> = ({
|
||||||
id,
|
id,
|
||||||
data,
|
data,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { handleNodeDataUpdate } = useWorkflow()
|
const { handleNodeDataUpdate } = useWorkflow()
|
||||||
|
|
||||||
@ -38,14 +40,6 @@ const NodeControl: FC<NodeControlProps> = ({
|
|||||||
className='flex items-center px-0.5 h-6 bg-white rounded-lg border-[0.5px] border-gray-100 shadow-xs text-gray-500'
|
className='flex items-center px-0.5 h-6 bg-white rounded-lg border-[0.5px] border-gray-100 shadow-xs text-gray-500'
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
{
|
|
||||||
data._isSingleRun && (
|
|
||||||
<div className='flex items-center mr-1 px-1 h-5 rounded-md bg-primary-50 text-xs font-medium text-primary-600'>
|
|
||||||
<Loading02 className='mr-1 w-3 h-3 animate-spin' />
|
|
||||||
RUNNING
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
canRunBySingle(data.type) && (
|
canRunBySingle(data.type) && (
|
||||||
<div
|
<div
|
||||||
@ -53,14 +47,22 @@ const NodeControl: FC<NodeControlProps> = ({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleNodeDataUpdate({
|
handleNodeDataUpdate({
|
||||||
id,
|
id,
|
||||||
data: { _isSingleRun: !data._isSingleRun },
|
data: {
|
||||||
|
_isSingleRun: !data._isSingleRun,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
data._isSingleRun
|
data._isSingleRun
|
||||||
? <Stop className='w-3 h-3' />
|
? <Stop className='w-3 h-3' />
|
||||||
: <Play className='w-3 h-3' />
|
: (
|
||||||
|
<TooltipPlus
|
||||||
|
popupContent={t('workflow.panel.runThisStep')}
|
||||||
|
>
|
||||||
|
<Play className='w-3 h-3' />
|
||||||
|
</TooltipPlus>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -30,6 +30,7 @@ export const NodeTargetHandle = ({
|
|||||||
nodeSelectorClassName,
|
nodeSelectorClassName,
|
||||||
}: NodeHandleProps) => {
|
}: NodeHandleProps) => {
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
const { handleNodeAddPrev } = useWorkflow()
|
||||||
const edges = useEdges()
|
const edges = useEdges()
|
||||||
const connectedEdges = getConnectedEdges([{ id } as Node], edges)
|
const connectedEdges = getConnectedEdges([{ id } as Node], edges)
|
||||||
const connected = connectedEdges.find(edge => edge.targetHandle === handleId && edge.target === id)
|
const connected = connectedEdges.find(edge => edge.targetHandle === handleId && edge.target === id)
|
||||||
@ -42,6 +43,9 @@ export const NodeTargetHandle = ({
|
|||||||
if (!connected)
|
if (!connected)
|
||||||
setOpen(v => !v)
|
setOpen(v => !v)
|
||||||
}, [connected])
|
}, [connected])
|
||||||
|
const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => {
|
||||||
|
handleNodeAddPrev(id, type, handleId, toolDefaultValue)
|
||||||
|
}, [handleNodeAddPrev, id, handleId])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -64,7 +68,7 @@ export const NodeTargetHandle = ({
|
|||||||
<BlockSelector
|
<BlockSelector
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={handleOpenChange}
|
onOpenChange={handleOpenChange}
|
||||||
onSelect={() => {}}
|
onSelect={handleSelect}
|
||||||
asChild
|
asChild
|
||||||
placement='left'
|
placement='left'
|
||||||
triggerClassName={open => `
|
triggerClassName={open => `
|
||||||
|
|||||||
@ -106,12 +106,12 @@ const BaseNode: FC<BaseNodeProps> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className='mb-1'>
|
<div className='pb-1'>
|
||||||
{cloneElement(children, { id, data })}
|
{cloneElement(children, { id, data })}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
data.desc && (
|
data.desc && (
|
||||||
<div className='px-3 pt-s1 pb-2 text-xs leading-[18px] text-gray-500 whitespace-pre-line break-words'>
|
<div className='px-3 pt-1 pb-2 text-xs leading-[18px] text-gray-500 whitespace-pre-line break-words'>
|
||||||
{data.desc}
|
{data.desc}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -33,24 +33,28 @@ const Node: FC<NodeProps<QuestionClassifierNodeType>> = (props) => {
|
|||||||
readonly
|
readonly
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className='mt-2 space-y-0.5'>
|
{
|
||||||
{topics.map((topic, index) => (
|
!!topics.length && (
|
||||||
<div
|
<div className='mt-2 space-y-0.5'>
|
||||||
key={index}
|
{topics.map((topic, index) => (
|
||||||
className='relative'
|
<div
|
||||||
>
|
key={index}
|
||||||
<InfoPanel
|
className='relative'
|
||||||
title={`${t(`${i18nPrefix}.class`)} ${index + 1}`}
|
>
|
||||||
content={topic.name}
|
<InfoPanel
|
||||||
/>
|
title={`${t(`${i18nPrefix}.class`)} ${index + 1}`}
|
||||||
<NodeSourceHandle
|
content={topic.name}
|
||||||
{...props}
|
/>
|
||||||
handleId={topic.id}
|
<NodeSourceHandle
|
||||||
handleClassName='!top-1/2 !-translate-y-1/2 !-right-[21px]'
|
{...props}
|
||||||
/>
|
handleId={topic.id}
|
||||||
|
handleClassName='!top-1/2 !-translate-y-1/2 !-right-[21px]'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
)
|
||||||
</div>
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -171,6 +171,6 @@ export const canRunBySingle = (nodeType: BlockEnum) => {
|
|||||||
|| nodeType === BlockEnum.Tool
|
|| nodeType === BlockEnum.Tool
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getVariables = () => {
|
export const getVariables = (currentNodeId: string) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user