@@ -210,7 +210,7 @@ const XFlow: FC<FlowProps> = memo(props => {
210210 ) ;
211211
212212 const { eventEmitter } = useEventEmitterContextContext ( ) ;
213- eventEmitter ?. useSubscription ( ( v : any ) => {
213+ eventEmitter ?. useSubscription ( async ( v : any ) => {
214214 // 整理画布
215215 if ( v . type === 'auto-layout-nodes' ) {
216216 const newNodes : any = autoLayoutNodes (
@@ -219,6 +219,12 @@ const XFlow: FC<FlowProps> = memo(props => {
219219 layout
220220 ) ;
221221 setNodes ( newNodes , false ) ;
222+
223+ // 整理画布完成后执行回调
224+ const onAutoLayoutCompleted = globalConfig ?. controls ?. onAutoLayoutCompleted ;
225+ if ( onAutoLayoutCompleted ) {
226+ await onAutoLayoutCompleted ( newNodes ) ;
227+ }
222228 }
223229
224230 if ( v . type === 'deleteNode' ) {
@@ -244,18 +250,32 @@ const XFlow: FC<FlowProps> = memo(props => {
244250 setCandidateNode ( newNode ) ;
245251 } ;
246252
247- // edge 移入/移出效果
248- const getUpdateEdgeConfig = useMemoizedFn ( ( edge : any , color : string ) => {
249- const newEdges = produce ( edges , draft => {
250- const currEdge : any = draft . find ( e => e . id === edge . id ) ;
251- currEdge . style = {
252- ...edge . style ,
253- stroke : color ,
254- } ;
255- currEdge . markerEnd = {
256- ...edge ?. markerEnd ,
257- color,
258- } ;
253+
254+ const hoveredEdgeIdRef = useRef < string | null > ( null ) ; // edge 移入/移出效果
255+
256+ const getUpdateEdgeConfig = useMemoizedFn ( ( edgeId : string , color : string , shouldCheckColor = false , allowedColors ?: string [ ] ) => {
257+ const currentEdges = storeApi . getState ( ) . edges ;
258+ const currEdge = currentEdges . find ( e => e . id === edgeId ) ;
259+
260+ // 如果需要检查颜色,只有在允许的颜色范围内才更新
261+ if ( shouldCheckColor && allowedColors && currEdge ?. style ?. stroke ) {
262+ if ( ! allowedColors . includes ( currEdge . style . stroke ) ) {
263+ return ; // 如果是自定义颜色,不更新
264+ }
265+ }
266+
267+ const newEdges = produce ( currentEdges , draft => {
268+ const draftEdge : any = draft . find ( e => e . id === edgeId ) ;
269+ if ( draftEdge ) {
270+ draftEdge . style = {
271+ ...draftEdge . style ,
272+ stroke : color ,
273+ } ;
274+ draftEdge . markerEnd = {
275+ ...draftEdge . markerEnd ,
276+ color,
277+ } ;
278+ }
259279 } ) ;
260280 setEdges ( newEdges ) ;
261281 } ) ;
@@ -340,6 +360,40 @@ const XFlow: FC<FlowProps> = memo(props => {
340360 const strokeWidth = globalConfig ?. edge ?. strokeWidth ?? 1.5 ;
341361 const panelonClose = globalConfig ?. nodePanel ?. onClose ;
342362
363+ const handleClosePanel = useMemoizedFn ( async ( ) => {
364+ // 面板关闭校验表单
365+ const result = await nodeEditorRef ?. current ?. validateForm ( ) ;
366+ if ( ! result ) {
367+ return ;
368+ }
369+ setOpenPanel ( false ) ;
370+ workflowContainerRef . current ?. focus ( ) ;
371+
372+ // 如果日志面板关闭
373+ if ( ! isTruthy ( activeNode ?. _status ) || ! openLogPanel ) {
374+ setActiveNode ( null ) ;
375+ }
376+ if ( isFunction ( panelonClose ) ) {
377+ panelonClose ( activeNode ?. id ) ;
378+ }
379+ } ) ;
380+
381+ const handleCloseLogPanel = useMemoizedFn ( ( ) => {
382+ setOpenLogPanel ( false ) ;
383+ ! openPanel && setActiveNode ( null ) ;
384+ workflowContainerRef . current ?. focus ( ) ;
385+ } ) ;
386+
387+ // 点击空白处关闭抽屉
388+ const handlePaneClick = useMemoizedFn ( ( ) => {
389+ if ( openPanel && activeNode ) {
390+ handleClosePanel ( ) ;
391+ }
392+ if ( openLogPanel && activeNode ) {
393+ handleCloseLogPanel ( ) ;
394+ }
395+ } ) ;
396+
343397 return (
344398 < div
345399 id = "xflow-container"
@@ -357,6 +411,7 @@ const XFlow: FC<FlowProps> = memo(props => {
357411 panOnScroll = { panOnScroll } // 禁用滚动平移
358412 preventScrolling = { preventScrolling } // 允许页面滚动
359413 connectionLineComponent = { connectionLineComponent }
414+ connectionRadius = { 100 }
360415 defaultEdgeOptions = { {
361416 type : 'buttonedge' ,
362417 style : {
@@ -414,14 +469,26 @@ const XFlow: FC<FlowProps> = memo(props => {
414469 } ) ;
415470 } }
416471 onEdgeMouseEnter = { ( _ , edge : any ) => {
417- if ( ! edge . style . stroke || edge . style . stroke === '#c9c9c9' ) {
418- getUpdateEdgeConfig ( edge , '#2970ff' ) ;
472+ // 如果之前有 hover 的 edge,先重置它的颜色(只重置我们设置过的颜色)
473+ if ( hoveredEdgeIdRef . current && hoveredEdgeIdRef . current !== edge . id ) {
474+ getUpdateEdgeConfig ( hoveredEdgeIdRef . current , '#c9c9c9' , true , [ '#2970ff' , '#c9c9c9' ] ) ;
475+ }
476+ hoveredEdgeIdRef . current = edge . id ;
477+ // 设置当前 edge 为高亮色(只有当没有自定义颜色时才更新)
478+ const currentEdges = storeApi . getState ( ) . edges ;
479+ const currentEdge = currentEdges . find ( e => e . id === edge . id ) ;
480+ const currentStroke = currentEdge ?. style ?. stroke ;
481+ // 只有当没有设置颜色或是默认灰色时才设置为高亮色
482+ if ( ! currentStroke || currentStroke === '#c9c9c9' ) {
483+ getUpdateEdgeConfig ( edge . id , '#2970ff' ) ;
419484 }
420485 } }
421486 onEdgeMouseLeave = { ( _ , edge ) => {
422- if ( [ '#2970ff' , '#c9c9c9' ] . includes ( edge . style . stroke ) ) {
423- getUpdateEdgeConfig ( edge , '#c9c9c9' ) ;
487+ if ( hoveredEdgeIdRef . current === edge . id ) {
488+ // 重置当前 edge 的颜色(只重置我们设置过的颜色)
489+ hoveredEdgeIdRef . current = null ;
424490 }
491+ getUpdateEdgeConfig ( edge . id , '#c9c9c9' , true , [ '#2970ff' , '#c9c9c9' ] ) ;
425492 } }
426493 onNodesDelete = { ( ) => {
427494 setActiveNode ( null ) ;
@@ -433,6 +500,7 @@ const XFlow: FC<FlowProps> = memo(props => {
433500 onEdgeClick = { ( event , edge ) => {
434501 onEdgeClick && onEdgeClick ( event , edge ) ;
435502 } }
503+ onPaneClick = { handlePaneClick }
436504 >
437505 < CandidateNode />
438506 < Operator addNode = { handleAddNode } xflowRef = { workflowContainerRef } />
@@ -446,23 +514,7 @@ const XFlow: FC<FlowProps> = memo(props => {
446514 < PanelContainer
447515 id = { activeNode ?. id }
448516 nodeType = { activeNode ?. _nodeType }
449- onClose = { async ( ) => {
450- // 面板关闭校验表单
451- const result = await nodeEditorRef ?. current ?. validateForm ( ) ;
452- if ( ! result ) {
453- return ;
454- }
455- setOpenPanel ( false ) ;
456- workflowContainerRef . current ?. focus ( ) ;
457-
458- // 如果日志面板关闭
459- if ( ! isTruthy ( activeNode ?. _status ) || ! openLogPanel ) {
460- setActiveNode ( null ) ;
461- }
462- if ( isFunction ( panelonClose ) ) {
463- panelonClose ( activeNode ?. id ) ;
464- }
465- } }
517+ onClose = { handleClosePanel }
466518 node = { activeNode }
467519 data = { activeNode ?. values }
468520 openLogPanel = { openLogPanel }
@@ -476,11 +528,7 @@ const XFlow: FC<FlowProps> = memo(props => {
476528 < PanelStatusLogContainer
477529 id = { activeNode ?. id }
478530 nodeType = { activeNode ?. _nodeType }
479- onClose = { ( ) => {
480- setOpenLogPanel ( false ) ;
481- ! openPanel && setActiveNode ( null ) ;
482- workflowContainerRef . current ?. focus ( ) ;
483- } }
531+ onClose = { handleCloseLogPanel }
484532 data = { activeNode ?. values }
485533 >
486534 { NodeLogWrap }
0 commit comments