浏览代码

fix: workflow restore (#3711)

tags/0.6.5
zxhlyh 1年前
父节点
当前提交
83caffe000
没有帐户链接到提交者的电子邮件

+ 2
- 0
web/app/components/workflow/constants.ts 查看文件

@@ -402,3 +402,5 @@ export const TOOL_OUTPUT_STRUCT: Var[] = [
type: VarType.arrayFile,
},
]

export const WORKFLOW_DATA_UPDATE = 'WORKFLOW_DATA_UPDATE'

+ 1
- 0
web/app/components/workflow/header/index.tsx 查看文件

@@ -73,6 +73,7 @@ const Header: FC = () => {

const handleRestore = useCallback(() => {
workflowStore.setState({ isRestoring: false })
workflowStore.setState({ backupDraft: undefined })
handleSyncWorkflowDraft(true)
}, [handleSyncWorkflowDraft, workflowStore])


+ 16
- 5
web/app/components/workflow/hooks/use-workflow.ts 查看文件

@@ -19,6 +19,7 @@ import type {
Viewport,
} from 'reactflow'
import {
changeNodesAndEdgesId,
getLayoutByDagre,
initialEdges,
initialNodes,
@@ -39,6 +40,7 @@ import {
import {
AUTO_LAYOUT_OFFSET,
SUPPORT_OUTPUT_VARS_NODE,
WORKFLOW_DATA_UPDATE,
} from '../constants'
import { findUsedVarNodes, getNodeOutputVars, updateNodeVars } from '../nodes/_base/components/variable/utils'
import { useNodesExtraData } from './use-nodes-data'
@@ -56,6 +58,8 @@ import {
fetchAllCustomTools,
} from '@/service/tools'
import I18n from '@/context/i18n'
import { useEventEmitterContextContext } from '@/context/event-emitter'

export const useIsChatMode = () => {
const appDetail = useAppStore(s => s.appDetail)

@@ -69,6 +73,7 @@ export const useWorkflow = () => {
const workflowStore = useWorkflowStore()
const nodesExtraData = useNodesExtraData()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const { eventEmitter } = useEventEmitterContextContext()

const handleLayout = useCallback(async () => {
workflowStore.setState({ nodeAnimation: true })
@@ -314,15 +319,21 @@ export const useWorkflow = () => {
}, [locale])

const renderTreeFromRecord = useCallback((nodes: Node[], edges: Edge[], viewport?: Viewport) => {
const { setNodes } = store.getState()
const { setViewport, setEdges } = reactflow
const { setViewport } = reactflow

const [newNodes, newEdges] = changeNodesAndEdgesId(nodes, edges)

setNodes(initialNodes(nodes, edges))
setEdges(initialEdges(edges, nodes))
eventEmitter?.emit({
type: WORKFLOW_DATA_UPDATE,
payload: {
nodes: initialNodes(newNodes, newEdges),
edges: initialEdges(newEdges, newNodes),
},
} as any)

if (viewport)
setViewport(viewport)
}, [store, reactflow])
}, [reactflow, eventEmitter])

const getNode = useCallback((nodeId?: string) => {
const { getNodes } = store.getState()

+ 17
- 2
web/app/components/workflow/index.tsx 查看文件

@@ -14,6 +14,8 @@ import {
import ReactFlow, {
Background,
ReactFlowProvider,
useEdgesState,
useNodesState,
useOnViewportChange,
} from 'reactflow'
import type { Viewport } from 'reactflow'
@@ -46,9 +48,11 @@ import {
initialEdges,
initialNodes,
} from './utils'
import { WORKFLOW_DATA_UPDATE } from './constants'
import Loading from '@/app/components/base/loading'
import { FeaturesProvider } from '@/app/components/base/features'
import type { Features as FeaturesData } from '@/app/components/base/features/types'
import { useEventEmitterContextContext } from '@/context/event-emitter'

const nodeTypes = {
custom: CustomNode,
@@ -63,10 +67,12 @@ type WorkflowProps = {
viewport?: Viewport
}
const Workflow: FC<WorkflowProps> = memo(({
nodes,
edges,
nodes: originalNodes,
edges: originalEdges,
viewport,
}) => {
const [nodes, setNodes] = useNodesState(originalNodes)
const [edges, setEdges] = useEdgesState(originalEdges)
const showFeaturesPanel = useStore(state => state.showFeaturesPanel)
const nodeAnimation = useStore(s => s.nodeAnimation)
const {
@@ -76,6 +82,15 @@ const Workflow: FC<WorkflowProps> = memo(({
const { workflowReadOnly } = useWorkflowReadOnly()
const { nodesReadOnly } = useNodesReadOnly()

const { eventEmitter } = useEventEmitterContextContext()

eventEmitter?.useSubscription((v: any) => {
if (v.type === WORKFLOW_DATA_UPDATE) {
setNodes(v.payload.nodes)
setEdges(v.payload.edges)
}
})

useEffect(() => {
setAutoFreeze(false)


+ 5
- 2
web/app/components/workflow/nodes/_base/components/node-handle.tsx 查看文件

@@ -16,6 +16,7 @@ import type { ToolDefaultValue } from '../../../block-selector/types'
import {
useNodesExtraData,
useNodesInteractions,
useNodesReadOnly,
} from '../../../hooks'
import { useStore } from '../../../store'

@@ -35,6 +36,7 @@ export const NodeTargetHandle = memo(({
const [open, setOpen] = useState(false)
const { handleNodeAdd } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const { getNodesReadOnly } = useNodesReadOnly()
const connected = data._connectedTargetHandleIds?.includes(handleId)
const availablePrevNodes = nodesExtraData[data.type].availablePrevNodes
const isConnectable = !!availablePrevNodes.length
@@ -78,7 +80,7 @@ export const NodeTargetHandle = memo(({
onClick={handleHandleClick}
>
{
!connected && isConnectable && !data._isInvalidConnection && (
!connected && isConnectable && !data._isInvalidConnection && !getNodesReadOnly() && (
<BlockSelector
open={open}
onOpenChange={handleOpenChange}
@@ -113,6 +115,7 @@ export const NodeSourceHandle = memo(({
const [open, setOpen] = useState(false)
const { handleNodeAdd } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const { getNodesReadOnly } = useNodesReadOnly()
const availableNextNodes = nodesExtraData[data.type].availableNextNodes
const isConnectable = !!availableNextNodes.length
const connected = data._connectedSourceHandleIds?.includes(handleId)
@@ -159,7 +162,7 @@ export const NodeSourceHandle = memo(({
onClick={handleHandleClick}
>
{
!connected && isConnectable && !data._isInvalidConnection && (
!connected && isConnectable && !data._isInvalidConnection && !getNodesReadOnly() && (
<BlockSelector
open={open}
onOpenChange={handleOpenChange}

+ 2
- 2
web/app/components/workflow/nodes/_base/node.tsx 查看文件

@@ -58,7 +58,7 @@ const BaseNode: FC<BaseNodeProps> = ({
`}
>
{
data.type !== BlockEnum.VariableAssigner && !data._runningStatus && !nodesReadOnly && (
data.type !== BlockEnum.VariableAssigner && !data._runningStatus && (
<NodeTargetHandle
id={id}
data={data}
@@ -68,7 +68,7 @@ const BaseNode: FC<BaseNodeProps> = ({
)
}
{
data.type !== BlockEnum.IfElse && data.type !== BlockEnum.QuestionClassifier && !data._runningStatus && !nodesReadOnly && (
data.type !== BlockEnum.IfElse && data.type !== BlockEnum.QuestionClassifier && !data._runningStatus && (
<NodeSourceHandle
id={id}
data={data}

+ 26
- 0
web/app/components/workflow/utils.ts 查看文件

@@ -4,6 +4,7 @@ import {
getOutgoers,
} from 'reactflow'
import dagre from 'dagre'
import { v4 as uuid4 } from 'uuid'
import {
cloneDeep,
uniqBy,
@@ -331,3 +332,28 @@ export const getToolCheckParams = (
language,
}
}

export const changeNodesAndEdgesId = (nodes: Node[], edges: Edge[]) => {
const idMap = nodes.reduce((acc, node) => {
acc[node.id] = uuid4()

return acc
}, {} as Record<string, string>)

const newNodes = nodes.map((node) => {
return {
...node,
id: idMap[node.id],
}
})

const newEdges = edges.map((edge) => {
return {
...edge,
source: idMap[edge.source],
target: idMap[edge.target],
}
})

return [newNodes, newEdges] as [Node[], Edge[]]
}

+ 2
- 0
web/package.json 查看文件

@@ -83,6 +83,7 @@
"sortablejs": "^1.15.0",
"swr": "^2.1.0",
"use-context-selector": "^1.4.1",
"uuid": "^9.0.1",
"zustand": "^4.5.1"
},
"devDependencies": {
@@ -104,6 +105,7 @@
"@types/react-window-infinite-loader": "^1.0.6",
"@types/recordrtc": "^5.6.11",
"@types/sortablejs": "^1.15.1",
"@types/uuid": "^9.0.8",
"autoprefixer": "^10.4.14",
"cross-env": "^7.0.3",
"eslint": "^8.36.0",

+ 583
- 307
web/yarn.lock
文件差异内容过多而无法显示
查看文件


正在加载...
取消
保存