mirror of
				https://github.com/langgenius/dify.git
				synced 2025-11-04 04:43:09 +00:00 
			
		
		
		
	Signed-off-by: -LAN- <laipz8200@outlook.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: -LAN- <laipz8200@outlook.com>
		
			
				
	
	
		
			166 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { useCallback } from 'react'
 | 
						|
import {
 | 
						|
  useNodes,
 | 
						|
  useStoreApi,
 | 
						|
} from 'reactflow'
 | 
						|
import { uniqBy } from 'lodash-es'
 | 
						|
import produce from 'immer'
 | 
						|
import {
 | 
						|
  useIsChatMode,
 | 
						|
  useNodeDataUpdate,
 | 
						|
  useWorkflow,
 | 
						|
  useWorkflowVariables,
 | 
						|
} from '../../hooks'
 | 
						|
import type {
 | 
						|
  Node,
 | 
						|
  ValueSelector,
 | 
						|
  Var,
 | 
						|
} from '../../types'
 | 
						|
import { useWorkflowStore } from '../../store'
 | 
						|
import type {
 | 
						|
  VarGroupItem,
 | 
						|
  VariableAssignerNodeType,
 | 
						|
} from './types'
 | 
						|
 | 
						|
export const useVariableAssigner = () => {
 | 
						|
  const store = useStoreApi()
 | 
						|
  const workflowStore = useWorkflowStore()
 | 
						|
  const { handleNodeDataUpdate } = useNodeDataUpdate()
 | 
						|
 | 
						|
  const handleAssignVariableValueChange = useCallback((nodeId: string, value: ValueSelector, varDetail: Var, groupId?: string) => {
 | 
						|
    const { getNodes } = store.getState()
 | 
						|
    const nodes = getNodes()
 | 
						|
    const node: Node<VariableAssignerNodeType> = nodes.find(node => node.id === nodeId)!
 | 
						|
 | 
						|
    let payload
 | 
						|
    if (groupId && groupId !== 'target') {
 | 
						|
      payload = {
 | 
						|
        advanced_settings: {
 | 
						|
          ...node.data.advanced_settings,
 | 
						|
          groups: node.data.advanced_settings?.groups.map((group: VarGroupItem & { groupId: string }) => {
 | 
						|
            if (group.groupId === groupId && !group.variables.some(item => item.join('.') === (value as ValueSelector).join('.'))) {
 | 
						|
              return {
 | 
						|
                ...group,
 | 
						|
                variables: [...group.variables, value],
 | 
						|
                output_type: varDetail.type,
 | 
						|
              }
 | 
						|
            }
 | 
						|
            return group
 | 
						|
          }),
 | 
						|
        },
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if (node.data.variables.some(item => item.join('.') === (value as ValueSelector).join('.')))
 | 
						|
        return
 | 
						|
      payload = {
 | 
						|
        variables: [...node.data.variables, value],
 | 
						|
        output_type: varDetail.type,
 | 
						|
      }
 | 
						|
    }
 | 
						|
    handleNodeDataUpdate({
 | 
						|
      id: nodeId,
 | 
						|
      data: payload,
 | 
						|
    })
 | 
						|
  }, [store, handleNodeDataUpdate])
 | 
						|
 | 
						|
  const handleAddVariableInAddVariablePopupWithPosition = useCallback((
 | 
						|
    nodeId: string,
 | 
						|
    variableAssignerNodeId: string,
 | 
						|
    variableAssignerNodeHandleId: string,
 | 
						|
    value: ValueSelector,
 | 
						|
    varDetail: Var,
 | 
						|
  ) => {
 | 
						|
    const {
 | 
						|
      getNodes,
 | 
						|
      setNodes,
 | 
						|
    } = store.getState()
 | 
						|
    const {
 | 
						|
      setShowAssignVariablePopup,
 | 
						|
    } = workflowStore.getState()
 | 
						|
 | 
						|
    const newNodes = produce(getNodes(), (draft) => {
 | 
						|
      draft.forEach((node) => {
 | 
						|
        if (node.id === nodeId || node.id === variableAssignerNodeId) {
 | 
						|
          node.data = {
 | 
						|
            ...node.data,
 | 
						|
            _showAddVariablePopup: false,
 | 
						|
            _holdAddVariablePopup: false,
 | 
						|
          }
 | 
						|
        }
 | 
						|
      })
 | 
						|
    })
 | 
						|
    setNodes(newNodes)
 | 
						|
    setShowAssignVariablePopup(undefined)
 | 
						|
    handleAssignVariableValueChange(variableAssignerNodeId, value, varDetail, variableAssignerNodeHandleId)
 | 
						|
  }, [store, workflowStore, handleAssignVariableValueChange])
 | 
						|
 | 
						|
  const handleGroupItemMouseEnter = useCallback((groupId: string) => {
 | 
						|
    const {
 | 
						|
      setHoveringAssignVariableGroupId,
 | 
						|
    } = workflowStore.getState()
 | 
						|
 | 
						|
    setHoveringAssignVariableGroupId(groupId)
 | 
						|
  }, [workflowStore])
 | 
						|
 | 
						|
  const handleGroupItemMouseLeave = useCallback(() => {
 | 
						|
    const {
 | 
						|
      connectingNodePayload,
 | 
						|
      setHoveringAssignVariableGroupId,
 | 
						|
    } = workflowStore.getState()
 | 
						|
 | 
						|
    if (connectingNodePayload)
 | 
						|
      setHoveringAssignVariableGroupId(undefined)
 | 
						|
  }, [workflowStore])
 | 
						|
 | 
						|
  return {
 | 
						|
    handleAddVariableInAddVariablePopupWithPosition,
 | 
						|
    handleGroupItemMouseEnter,
 | 
						|
    handleGroupItemMouseLeave,
 | 
						|
    handleAssignVariableValueChange,
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export const useGetAvailableVars = () => {
 | 
						|
  const nodes: Node[] = useNodes()
 | 
						|
  const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow()
 | 
						|
  const { getNodeAvailableVars } = useWorkflowVariables()
 | 
						|
  const isChatMode = useIsChatMode()
 | 
						|
  const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => {
 | 
						|
    const availableNodes: Node[] = []
 | 
						|
    const currentNode = nodes.find(node => node.id === nodeId)!
 | 
						|
 | 
						|
    if (!currentNode)
 | 
						|
      return []
 | 
						|
 | 
						|
    const beforeNodes = getBeforeNodesInSameBranchIncludeParent(nodeId)
 | 
						|
    availableNodes.push(...beforeNodes)
 | 
						|
    const parentNode = nodes.find(node => node.id === currentNode.parentId)
 | 
						|
 | 
						|
    if (hideEnv) {
 | 
						|
      return getNodeAvailableVars({
 | 
						|
        parentNode,
 | 
						|
        beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId),
 | 
						|
        isChatMode,
 | 
						|
        hideEnv,
 | 
						|
        hideChatVar: hideEnv,
 | 
						|
        filterVar,
 | 
						|
      })
 | 
						|
        .map(node => ({
 | 
						|
          ...node,
 | 
						|
          vars: node.isStartNode ? node.vars.filter(v => !v.variable.startsWith('sys.')) : node.vars,
 | 
						|
        }))
 | 
						|
        .filter(item => item.vars.length > 0)
 | 
						|
    }
 | 
						|
 | 
						|
    return getNodeAvailableVars({
 | 
						|
      parentNode,
 | 
						|
      beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId),
 | 
						|
      isChatMode,
 | 
						|
      filterVar,
 | 
						|
    })
 | 
						|
  }, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
 | 
						|
 | 
						|
  return getAvailableVars
 | 
						|
}
 |