mirror of
				https://github.com/langgenius/dify.git
				synced 2025-10-31 02:42:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			149 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { useCallback } from 'react'
 | |
| import produce from 'immer'
 | |
| import { useStoreApi } from 'reactflow'
 | |
| import { useParams } from 'next/navigation'
 | |
| import {
 | |
|   useWorkflowStore,
 | |
| } from '@/app/components/workflow/store'
 | |
| import { BlockEnum } from '@/app/components/workflow/types'
 | |
| import {
 | |
|   useNodesReadOnly,
 | |
| } from '@/app/components/workflow/hooks/use-workflow'
 | |
| import { syncWorkflowDraft } from '@/service/workflow'
 | |
| import { useFeaturesStore } from '@/app/components/base/features/hooks'
 | |
| import { API_PREFIX } from '@/config'
 | |
| import { useWorkflowRefreshDraft } from '.'
 | |
| 
 | |
| export const useNodesSyncDraft = () => {
 | |
|   const store = useStoreApi()
 | |
|   const workflowStore = useWorkflowStore()
 | |
|   const featuresStore = useFeaturesStore()
 | |
|   const { getNodesReadOnly } = useNodesReadOnly()
 | |
|   const { handleRefreshWorkflowDraft } = useWorkflowRefreshDraft()
 | |
|   const params = useParams()
 | |
| 
 | |
|   const getPostParams = useCallback(() => {
 | |
|     const {
 | |
|       getNodes,
 | |
|       edges,
 | |
|       transform,
 | |
|     } = store.getState()
 | |
|     const [x, y, zoom] = transform
 | |
|     const {
 | |
|       appId,
 | |
|       conversationVariables,
 | |
|       environmentVariables,
 | |
|       syncWorkflowDraftHash,
 | |
|     } = workflowStore.getState()
 | |
| 
 | |
|     if (appId) {
 | |
|       const nodes = getNodes()
 | |
|       const hasStartNode = nodes.find(node => node.data.type === BlockEnum.Start)
 | |
| 
 | |
|       if (!hasStartNode)
 | |
|         return
 | |
| 
 | |
|       const features = featuresStore!.getState().features
 | |
|       const producedNodes = produce(nodes, (draft) => {
 | |
|         draft.forEach((node) => {
 | |
|           Object.keys(node.data).forEach((key) => {
 | |
|             if (key.startsWith('_'))
 | |
|               delete node.data[key]
 | |
|           })
 | |
|         })
 | |
|       })
 | |
|       const producedEdges = produce(edges, (draft) => {
 | |
|         draft.forEach((edge) => {
 | |
|           Object.keys(edge.data).forEach((key) => {
 | |
|             if (key.startsWith('_'))
 | |
|               delete edge.data[key]
 | |
|           })
 | |
|         })
 | |
|       })
 | |
|       return {
 | |
|         url: `/apps/${appId}/workflows/draft`,
 | |
|         params: {
 | |
|           graph: {
 | |
|             nodes: producedNodes,
 | |
|             edges: producedEdges,
 | |
|             viewport: {
 | |
|               x,
 | |
|               y,
 | |
|               zoom,
 | |
|             },
 | |
|           },
 | |
|           features: {
 | |
|             opening_statement: features.opening?.enabled ? (features.opening?.opening_statement || '') : '',
 | |
|             suggested_questions: features.opening?.enabled ? (features.opening?.suggested_questions || []) : [],
 | |
|             suggested_questions_after_answer: features.suggested,
 | |
|             text_to_speech: features.text2speech,
 | |
|             speech_to_text: features.speech2text,
 | |
|             retriever_resource: features.citation,
 | |
|             sensitive_word_avoidance: features.moderation,
 | |
|             file_upload: features.file,
 | |
|           },
 | |
|           environment_variables: environmentVariables,
 | |
|           conversation_variables: conversationVariables,
 | |
|           hash: syncWorkflowDraftHash,
 | |
|         },
 | |
|       }
 | |
|     }
 | |
|   }, [store, featuresStore, workflowStore])
 | |
| 
 | |
|   const syncWorkflowDraftWhenPageClose = useCallback(() => {
 | |
|     if (getNodesReadOnly())
 | |
|       return
 | |
|     const postParams = getPostParams()
 | |
| 
 | |
|     if (postParams) {
 | |
|       navigator.sendBeacon(
 | |
|         `${API_PREFIX}/apps/${params.appId}/workflows/draft?_token=${localStorage.getItem('console_token')}`,
 | |
|         JSON.stringify(postParams.params),
 | |
|       )
 | |
|     }
 | |
|   }, [getPostParams, params.appId, getNodesReadOnly])
 | |
| 
 | |
|   const doSyncWorkflowDraft = useCallback(async (
 | |
|     notRefreshWhenSyncError?: boolean,
 | |
|     callback?: {
 | |
|       onSuccess?: () => void
 | |
|       onError?: () => void
 | |
|       onSettled?: () => void
 | |
|     },
 | |
|   ) => {
 | |
|     if (getNodesReadOnly())
 | |
|       return
 | |
|     const postParams = getPostParams()
 | |
| 
 | |
|     if (postParams) {
 | |
|       const {
 | |
|         setSyncWorkflowDraftHash,
 | |
|         setDraftUpdatedAt,
 | |
|       } = workflowStore.getState()
 | |
|       try {
 | |
|         const res = await syncWorkflowDraft(postParams)
 | |
|         setSyncWorkflowDraftHash(res.hash)
 | |
|         setDraftUpdatedAt(res.updated_at)
 | |
|         callback?.onSuccess && callback.onSuccess()
 | |
|       }
 | |
|       catch (error: any) {
 | |
|         if (error && error.json && !error.bodyUsed) {
 | |
|           error.json().then((err: any) => {
 | |
|             if (err.code === 'draft_workflow_not_sync' && !notRefreshWhenSyncError)
 | |
|               handleRefreshWorkflowDraft()
 | |
|           })
 | |
|         }
 | |
|         callback?.onError && callback.onError()
 | |
|       }
 | |
|       finally {
 | |
|         callback?.onSettled && callback.onSettled()
 | |
|       }
 | |
|     }
 | |
|   }, [workflowStore, getPostParams, getNodesReadOnly, handleRefreshWorkflowDraft])
 | |
| 
 | |
|   return {
 | |
|     doSyncWorkflowDraft,
 | |
|     syncWorkflowDraftWhenPageClose,
 | |
|   }
 | |
| }
 | 
