From 77950e48c76f4a3b29d01831d43039caba29888a Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期二, 18 十一月 2025 14:12:42 +0800
Subject: [PATCH] 修改
---
app/components/workflow/hooks/use-workflow.ts | 179 +++++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 130 insertions(+), 49 deletions(-)
diff --git a/app/components/workflow/hooks/use-workflow.ts b/app/components/workflow/hooks/use-workflow.ts
index 99dce4d..2eafb4a 100644
--- a/app/components/workflow/hooks/use-workflow.ts
+++ b/app/components/workflow/hooks/use-workflow.ts
@@ -1,9 +1,13 @@
import {
useCallback,
+ useEffect,
useMemo,
+ useState,
} from 'react'
+import dayjs from 'dayjs'
import { uniqBy } from 'lodash-es'
import { useTranslation } from 'react-i18next'
+import { useContext } from 'use-context-selector'
import {
getIncomers,
getOutgoers,
@@ -36,17 +40,24 @@
import { CUSTOM_NOTE_NODE } from '../note-node/constants'
import { findUsedVarNodes, getNodeOutputVars, updateNodeVars } from '../nodes/_base/components/variable/utils'
import { useNodesExtraData } from './use-nodes-data'
+import { useWorkflowTemplate } from './use-workflow-template'
import { useStore as useAppStore } from '@/app/components/app/store'
+import {
+ fetchNodesDefaultConfigs,
+ fetchPublishedWorkflow,
+ fetchWorkflowDraft,
+ syncWorkflowDraft,
+} from '@/service/workflow'
+import type { FetchWorkflowDraftResponse } from '@/types/workflow'
import {
fetchAllBuiltInTools,
fetchAllCustomTools,
fetchAllWorkflowTools,
} from '@/service/tools'
+import I18n from '@/context/i18n'
import { CollectionType } from '@/app/components/tools/types'
import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants'
-import { CUSTOM_LOOP_START_NODE } from '@/app/components/workflow/nodes/loop-start/constants'
-import { basePath } from '@/utils/var'
-import { canFindTool } from '@/utils'
+import { useWorkflowConfig } from '@/service/use-workflow'
export const useIsChatMode = () => {
const appDetail = useAppStore(s => s.appDetail)
@@ -56,9 +67,12 @@
export const useWorkflow = () => {
const { t } = useTranslation()
+ const { locale } = useContext(I18n)
const store = useStoreApi()
const workflowStore = useWorkflowStore()
+ const appId = useStore(s => s.appId)
const nodesExtraData = useNodesExtraData()
+ const { data: workflowConfig } = useWorkflowConfig(appId)
const setPanelWidth = useCallback((width: number) => {
localStorage.setItem('workflow-node-panel-width', `${width}`)
workflowStore.setState({ panelWidth: width })
@@ -74,7 +88,7 @@
const currentNode = nodes.find(node => node.id === nodeId)
if (currentNode?.parentId)
- startNode = nodes.find(node => node.parentId === currentNode.parentId && (node.type === CUSTOM_ITERATION_START_NODE || node.type === CUSTOM_LOOP_START_NODE))
+ startNode = nodes.find(node => node.parentId === currentNode.parentId && node.type === CUSTOM_ITERATION_START_NODE)
if (!startNode)
return []
@@ -103,7 +117,7 @@
list.push(...incomers)
- return uniqBy(list, 'id').filter((item: Node) => {
+ return uniqBy(list, 'id').filter((item) => {
return SUPPORT_OUTPUT_VARS_NODE.includes(item.data.type)
})
}, [store])
@@ -150,7 +164,7 @@
const length = list.length
if (length) {
- return uniqBy(list, 'id').reverse().filter((item: Node) => {
+ return uniqBy(list, 'id').reverse().filter((item) => {
return SUPPORT_OUTPUT_VARS_NODE.includes(item.data.type)
})
}
@@ -224,15 +238,6 @@
return nodes.filter(node => node.parentId === nodeId)
}, [store])
- const getLoopNodeChildren = useCallback((nodeId: string) => {
- const {
- getNodes,
- } = store.getState()
- const nodes = getNodes()
-
- return nodes.filter(node => node.parentId === nodeId)
- }, [store])
-
const isFromStartNode = useCallback((nodeId: string) => {
const { getNodes } = store.getState()
const nodes = getNodes()
@@ -274,7 +279,7 @@
setNodes(newNodes)
}
- // eslint-disable-next-line react-hooks/exhaustive-deps
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [store])
const isVarUsedInNodes = useCallback((varSelector: ValueSelector) => {
@@ -327,7 +332,6 @@
parallelList,
hasAbnormalEdges,
} = getParallelInfo(nodes, edges, parentNodeId)
- const { workflowConfig } = workflowStore.getState()
if (hasAbnormalEdges)
return false
@@ -343,7 +347,7 @@
}
return true
- }, [t, workflowStore])
+ }, [t, workflowStore, workflowConfig?.parallel_depth_limit])
const isValidConnection = useCallback(({ source, sourceHandle, target }: Connection) => {
const {
@@ -391,6 +395,10 @@
return !hasCycle(targetNode)
}, [store, nodesExtraData, checkParallelLimit])
+ const formatTimeFromNow = useCallback((time: number) => {
+ return dayjs(time).locale(locale === 'zh-Hans' ? 'zh-cn' : locale).fromNow()
+ }, [locale])
+
const getNode = useCallback((nodeId?: string) => {
const { getNodes } = store.getState()
const nodes = getNodes()
@@ -412,10 +420,10 @@
checkNestedParallelLimit,
isValidConnection,
isFromStartNode,
+ formatTimeFromNow,
getNode,
getBeforeNodeById,
getIterationNodeChildren,
- getLoopNodeChildren,
}
}
@@ -426,12 +434,6 @@
if (type === 'builtin') {
const buildInTools = await fetchAllBuiltInTools()
- if (basePath) {
- buildInTools.forEach((item) => {
- if (typeof item.icon == 'string' && !item.icon.includes(basePath))
- item.icon = `${basePath}${item.icon}`
- })
- }
workflowStore.setState({
buildInTools: buildInTools || [],
})
@@ -454,6 +456,108 @@
return {
handleFetchAllTools,
+ }
+}
+
+export const useWorkflowInit = () => {
+ const workflowStore = useWorkflowStore()
+ const {
+ nodes: nodesTemplate,
+ edges: edgesTemplate,
+ } = useWorkflowTemplate()
+ const { handleFetchAllTools } = useFetchToolsData()
+ const appDetail = useAppStore(state => state.appDetail)!
+ const setSyncWorkflowDraftHash = useStore(s => s.setSyncWorkflowDraftHash)
+ const [data, setData] = useState<FetchWorkflowDraftResponse>()
+ const [isLoading, setIsLoading] = useState(true)
+ useEffect(() => {
+ workflowStore.setState({ appId: appDetail.id })
+ }, [appDetail.id, workflowStore])
+
+ const handleGetInitialWorkflowData = useCallback(async () => {
+ try {
+ const res = await fetchWorkflowDraft(`/apps/${appDetail.id}/workflows/draft`)
+ setData(res)
+ workflowStore.setState({
+ envSecrets: (res.environment_variables || []).filter(env => env.value_type === 'secret').reduce((acc, env) => {
+ acc[env.id] = env.value
+ return acc
+ }, {} as Record<string, string>),
+ environmentVariables: res.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [],
+ // #TODO chatVar sync#
+ conversationVariables: res.conversation_variables || [],
+ })
+ setSyncWorkflowDraftHash(res.hash)
+ setIsLoading(false)
+ }
+ catch (error: any) {
+ if (error && error.json && !error.bodyUsed && appDetail) {
+ error.json().then((err: any) => {
+ if (err.code === 'draft_workflow_not_exist') {
+ workflowStore.setState({ notInitialWorkflow: true })
+ syncWorkflowDraft({
+ url: `/apps/${appDetail.id}/workflows/draft`,
+ params: {
+ graph: {
+ nodes: nodesTemplate,
+ edges: edgesTemplate,
+ },
+ features: {
+ retriever_resource: { enabled: true },
+ },
+ environment_variables: [],
+ conversation_variables: [],
+ },
+ }).then((res) => {
+ workflowStore.getState().setDraftUpdatedAt(res.updated_at)
+ handleGetInitialWorkflowData()
+ })
+ }
+ })
+ }
+ }
+ }, [appDetail, nodesTemplate, edgesTemplate, workflowStore, setSyncWorkflowDraftHash])
+
+ useEffect(() => {
+ handleGetInitialWorkflowData()
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
+
+ const handleFetchPreloadData = useCallback(async () => {
+ try {
+ const nodesDefaultConfigsData = await fetchNodesDefaultConfigs(`/apps/${appDetail?.id}/workflows/default-workflow-block-configs`)
+ const publishedWorkflow = await fetchPublishedWorkflow(`/apps/${appDetail?.id}/workflows/publish`)
+ workflowStore.setState({
+ nodesDefaultConfigs: nodesDefaultConfigsData.reduce((acc, block) => {
+ if (!acc[block.type])
+ acc[block.type] = { ...block.config }
+ return acc
+ }, {} as Record<string, any>),
+ })
+ workflowStore.getState().setPublishedAt(publishedWorkflow?.created_at)
+ }
+ catch (e) {
+
+ }
+ }, [workflowStore, appDetail])
+
+ useEffect(() => {
+ handleFetchPreloadData()
+ handleFetchAllTools('builtin')
+ handleFetchAllTools('custom')
+ handleFetchAllTools('workflow')
+ }, [handleFetchPreloadData, handleFetchAllTools])
+
+ useEffect(() => {
+ if (data) {
+ workflowStore.getState().setDraftUpdatedAt(data.updated_at)
+ workflowStore.getState().setToolPublished(data.tool_published)
+ }
+ }, [data, workflowStore])
+
+ return {
+ data,
+ isLoading,
}
}
@@ -505,7 +609,7 @@
targetTools = customTools
else
targetTools = workflowTools
- return targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.icon
+ return targetTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.icon
}
}, [data, buildInTools, customTools, workflowTools])
@@ -532,28 +636,5 @@
}, [iterationId, store])
return {
isNodeInIteration,
- }
-}
-
-export const useIsNodeInLoop = (loopId: string) => {
- const store = useStoreApi()
-
- const isNodeInLoop = useCallback((nodeId: string) => {
- const {
- getNodes,
- } = store.getState()
- const nodes = getNodes()
- const node = nodes.find(node => node.id === nodeId)
-
- if (!node)
- return false
-
- if (node.parentId === loopId)
- return true
-
- return false
- }, [loopId, store])
- return {
- isNodeInLoop,
}
}
--
Gitblit v1.8.0