mirror of
				https://github.com/langgenius/dify.git
				synced 2025-10-31 10:53:02 +00:00 
			
		
		
		
	 935e72d449
			
		
	
	
		935e72d449
		
			
		
	
	
	
	
		
			
			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
 | |
| }
 |