auto layout

This commit is contained in:
StyleZhang 2024-03-15 19:34:31 +08:00
parent aff5ab933b
commit 129a68bb06
4 changed files with 24 additions and 6 deletions

View File

@ -99,7 +99,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
} }
</PortalToFollowElemTrigger> </PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'> <PortalToFollowElemContent className='z-[1000]'>
<div className={`w-[256px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg ${popupClassName}`}> <div className={`rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg ${popupClassName}`}>
<div className='px-2 pt-2'> <div className='px-2 pt-2'>
<div <div
className='flex items-center px-2 rounded-lg bg-gray-100' className='flex items-center px-2 rounded-lg bg-gray-100'

View File

@ -230,8 +230,12 @@ export const NODE_WIDTH = 220
export const X_OFFSET = 64 export const X_OFFSET = 64
export const NODE_WIDTH_X_OFFSET = NODE_WIDTH + X_OFFSET export const NODE_WIDTH_X_OFFSET = NODE_WIDTH + X_OFFSET
export const Y_OFFSET = 39 export const Y_OFFSET = 39
export const TREE_DEEPTH = 20 export const TREE_DEEPTH = 30
export const START_INITIAL_POSITION = { x: 80, y: 282 } export const START_INITIAL_POSITION = { x: 80, y: 282 }
export const AUTO_LAYOUT_OFFSET = {
x: -42,
y: 243,
}
export const RETRIEVAL_OUTPUT_STRUCT = `{ export const RETRIEVAL_OUTPUT_STRUCT = `{
"content": "", "content": "",

View File

@ -8,6 +8,7 @@ import produce from 'immer'
import { import {
getIncomers, getIncomers,
getOutgoers, getOutgoers,
useReactFlow,
useStoreApi, useStoreApi,
} from 'reactflow' } from 'reactflow'
import type { Connection } from 'reactflow' import type { Connection } from 'reactflow'
@ -20,6 +21,7 @@ import type { Node } from '../types'
import { BlockEnum } from '../types' import { BlockEnum } from '../types'
import { useWorkflowStore } from '../store' import { useWorkflowStore } from '../store'
import { import {
AUTO_LAYOUT_OFFSET,
START_INITIAL_POSITION, START_INITIAL_POSITION,
SUPPORT_OUTPUT_VARS_NODE, SUPPORT_OUTPUT_VARS_NODE,
} from '../constants' } from '../constants'
@ -27,6 +29,7 @@ import {
useNodesExtraData, useNodesExtraData,
useNodesInitialData, useNodesInitialData,
} from './use-nodes-data' } from './use-nodes-data'
import { useNodesSyncDraft } from './use-nodes-sync-draft'
import { useStore as useAppStore } from '@/app/components/app/store' import { useStore as useAppStore } from '@/app/components/app/store'
import { import {
fetchNodesDefaultConfigs, fetchNodesDefaultConfigs,
@ -43,7 +46,9 @@ export const useIsChatMode = () => {
export const useWorkflow = () => { export const useWorkflow = () => {
const store = useStoreApi() const store = useStoreApi()
const reactflow = useReactFlow()
const nodesExtraData = useNodesExtraData() const nodesExtraData = useNodesExtraData()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const handleLayout = useCallback(async () => { const handleLayout = useCallback(async () => {
const { const {
@ -51,6 +56,7 @@ export const useWorkflow = () => {
edges, edges,
setNodes, setNodes,
} = store.getState() } = store.getState()
const { setViewport } = reactflow
const nodes = getNodes() const nodes = getNodes()
const layout = getLayoutByDagre(nodes, edges) const layout = getLayoutByDagre(nodes, edges)
@ -58,13 +64,19 @@ export const useWorkflow = () => {
draft.forEach((node) => { draft.forEach((node) => {
const nodeWithPosition = layout.node(node.id) const nodeWithPosition = layout.node(node.id)
node.position = { node.position = {
x: nodeWithPosition.x, x: nodeWithPosition.x + AUTO_LAYOUT_OFFSET.x,
y: nodeWithPosition.y, y: nodeWithPosition.y + AUTO_LAYOUT_OFFSET.y,
} }
}) })
}) })
setNodes(newNodes) setNodes(newNodes)
}, [store]) setViewport({
x: 0,
y: 0,
zoom: 0.8,
})
setTimeout(() => handleSyncWorkflowDraft())
}, [store, reactflow, handleSyncWorkflowDraft])
const getTreeLeafNodes = useCallback((nodeId: string) => { const getTreeLeafNodes = useCallback((nodeId: string) => {
const { const {

View File

@ -146,10 +146,12 @@ export const getNodesPositionMap = (nodes: Node[], edges: Edge[]) => {
return positionMap return positionMap
} }
const dagreGraph = new dagre.graphlib.Graph()
dagreGraph.setDefaultEdgeLabel(() => ({}))
export const getLayoutByDagre = (originNodes: Node[], originEdges: Edge[]) => { export const getLayoutByDagre = (originNodes: Node[], originEdges: Edge[]) => {
const nodes = cloneDeep(originNodes) const nodes = cloneDeep(originNodes)
const edges = cloneDeep(originEdges) const edges = cloneDeep(originEdges)
const dagreGraph = new dagre.graphlib.Graph()
dagreGraph.setGraph({ dagreGraph.setGraph({
rankdir: 'LR', rankdir: 'LR',
align: 'UL', align: 'UL',