feat: Variable click jumps to source node (#13623)

This commit is contained in:
wellCh4n
2025-05-19 23:17:18 +08:00
committed by GitHub
parent 6a9e0b1005
commit 276c02f341
9 changed files with 116 additions and 10 deletions

View File

@@ -91,6 +91,9 @@ const Editor: FC<Props> = ({
acc[node.id] = {
title: node.data.title,
type: node.data.type,
width: node.width,
height: node.height,
position: node.position,
}
if (node.data.type === BlockEnum.Start) {
acc.sys = {

View File

@@ -259,6 +259,9 @@ const Editor: FC<Props> = ({
acc[node.id] = {
title: node.data.title,
type: node.data.type,
width: node.width,
height: node.height,
position: node.position,
}
if (node.data.type === BlockEnum.Start) {
acc.sys = {

View File

@@ -1,5 +1,5 @@
import { useMemo } from 'react'
import { useNodes } from 'reactflow'
import { useCallback, useMemo } from 'react'
import { useNodes, useReactFlow, useStoreApi } from 'reactflow'
import { capitalize } from 'lodash-es'
import { useTranslation } from 'react-i18next'
import { RiErrorWarningFill } from '@remixicon/react'
@@ -48,12 +48,42 @@ const VariableTag = ({
const variableName = isSystemVar(valueSelector) ? valueSelector.slice(0).join('.') : valueSelector.slice(1).join('.')
const isException = isExceptionVariable(variableName, node?.data.type)
const reactflow = useReactFlow()
const store = useStoreApi()
const handleVariableJump = useCallback(() => {
const workflowContainer = document.getElementById('workflow-container')
const {
clientWidth,
clientHeight,
} = workflowContainer!
const {
setViewport,
} = reactflow
const { transform } = store.getState()
const zoom = transform[2]
const position = node.position
setViewport({
x: (clientWidth - 400 - node.width! * zoom) / 2 - position!.x * zoom,
y: (clientHeight - node.height! * zoom) / 2 - position!.y * zoom,
zoom: transform[2],
})
}, [node, reactflow, store])
const { t } = useTranslation()
return (
<Tooltip popupContent={!isValid && t('workflow.errorMsg.invalidVariable')}>
<div className={cn('border-[rgba(16, 2440,0.08)] inline-flex h-6 max-w-full items-center rounded-md border-[0.5px] border-divider-subtle bg-components-badge-white-to-dark px-1.5 text-xs shadow-xs',
!isValid && 'border-red-400 !bg-[#FEF3F2]',
)}>
)}
onClick={(e) => {
if (e.metaKey || e.ctrlKey) {
e.stopPropagation()
handleVariableJump()
}
}}
>
{(!isEnv && !isChatVar && <>
{node && (
<>

View File

@@ -9,7 +9,7 @@ import {
RiMoreLine,
} from '@remixicon/react'
import produce from 'immer'
import { useStoreApi } from 'reactflow'
import { useReactFlow, useStoreApi } from 'reactflow'
import RemoveButton from '../remove-button'
import useAvailableVarList from '../../hooks/use-available-var-list'
import VarReferencePopup from './var-reference-popup'
@@ -111,6 +111,9 @@ const VarReferencePicker: FC<Props> = ({
passedInAvailableNodes,
filterVar,
})
const reactflow = useReactFlow()
const startNode = availableNodes.find((node: any) => {
return node.data.type === BlockEnum.Start
})
@@ -172,7 +175,11 @@ const VarReferencePicker: FC<Props> = ({
if (isSystemVar(value as ValueSelector))
return startNode?.data
return getNodeInfoById(availableNodes, outputVarNodeId)?.data
const node = getNodeInfoById(availableNodes, outputVarNodeId)?.data
return {
...node,
id: outputVarNodeId,
}
}, [value, hasValue, isConstant, isIterationVar, iterationNode, availableNodes, outputVarNodeId, startNode, isLoopVar, loopNode])
const isShowAPart = (value as ValueSelector).length > 2
@@ -237,6 +244,28 @@ const VarReferencePicker: FC<Props> = ({
onChange([], varKindType)
}, [onChange, varKindType])
const handleVariableJump = useCallback((nodeId: string) => {
const currentNodeIndex = availableNodes.findIndex(node => node.id === nodeId)
const currentNode = availableNodes[currentNodeIndex]
const workflowContainer = document.getElementById('workflow-container')
const {
clientWidth,
clientHeight,
} = workflowContainer!
const {
setViewport,
} = reactflow
const { transform } = store.getState()
const zoom = transform[2]
const position = currentNode.position
setViewport({
x: (clientWidth - 400 - currentNode.width! * zoom) / 2 - position.x * zoom,
y: (clientHeight - currentNode.height! * zoom) / 2 - position.y * zoom,
zoom: transform[2],
})
}, [availableNodes, reactflow, store])
const type = getCurrentVariableType({
parentNode: isInIteration ? iterationNode : loopNode,
valueSelector: value as ValueSelector,
@@ -357,7 +386,12 @@ const VarReferencePicker: FC<Props> = ({
? (
<>
{isShowNodeName && !isEnv && !isChatVar && (
<div className='flex items-center'>
<div className='flex items-center' onClick={(e) => {
if (e.metaKey || e.ctrlKey) {
e.stopPropagation()
handleVariableJump(outputVarNode?.id)
}
}}>
<div className='h-3 px-[1px]'>
{outputVarNode?.type && <VarBlockIcon
className='!text-text-primary'

View File

@@ -37,6 +37,9 @@ const ConditionInput = ({
acc[node.id] = {
title: node.data.title,
type: node.data.type,
width: node.width,
height: node.height,
position: node.position,
}
if (node.data.type === BlockEnum.Start) {
acc.sys = {