import { v4 as uuid } from 'uuid' ; import { IRegisterNode , AbstractNodeType , INode } from '@/index' ; export const createUuid = ( prefix ? ) => { return `${ prefix || 'node' }-${ uuid ( ) }` ; } ; export const getRegisterNode = ( registerNodes , type ? ) => registerNodes . find ( ( node ) => type && node . type === type ) ; export const getIsStartNode = ( registerNodes , type ? ) => registerNodes . find ( ( item ) => item . type === type ) ?. isStart ; export const getIsEndNode = ( registerNodes , type ? ) => registerNodes . find ( ( item ) => item . type === type ) ?. isEnd ; export const getIsConditionNode = ( registerNodes , type ? ) => { const conditionNode = getRegisterNode ( registerNodes , type ) ; const branchNode = registerNodes . find ( ( item ) => type && item . conditionNodeType === type ) ; return ( conditionNode && branchNode && branchNode ?. type !== branchNode ?. conditionNodeType ) ; } ; export const getIsBranchNode = ( registerNodes , type ? ) => { const branchNode = getRegisterNode ( registerNodes , type ) ; const conditionNode = getRegisterNode ( registerNodes , branchNode ?. conditionNodeType ) ; return ( branchNode && conditionNode && branchNode ?. type !== branchNode ?. conditionNodeType ) ; } ; export const getAbstractNodeType = ( registerNodes , type ? ) => { if ( getIsStartNode ( registerNodes , type ) ) { return 'start' ; } else if ( getIsEndNode ( registerNodes , type ) ) { return 'end' ; } else if ( getIsBranchNode ( registerNodes , type ) ) { return 'branch' ; } else if ( getIsConditionNode ( registerNodes , type ) ) { return 'condition' ; } else { return 'common' ; } } ; export const createNewNode = ( registerNodes , type ? ) => { const registerNode = getRegisterNode ( registerNodes , type ) ; if ( ! registerNode ) return ; const isBranchNode = getIsBranchNode ( registerNodes , type ) ; const isConditionNode = getIsConditionNode ( registerNodes , type ) ; const initialNodeData = registerNode ?. initialNodeData || { } ; const extraProps = isBranchNode ? { children : [ createNewNode ( registerNodes , registerNode . conditionNodeType ) , createNewNode ( registerNodes , registerNode . conditionNodeType ) , ] , ... initialNodeData , } : isConditionNode ? { children : [ ] , ... initialNodeData , } : initialNodeData ; return { id : createUuid ( ) , type : registerNode . type , name : registerNode . name , ... extraProps , } ; } ; export const DFS = ( nodes , allNodes = [ ] ) => { for ( const node of nodes ) { allNodes . push ( node ) ; if ( Array . isArray ( node . children ) ) { DFS ( node . children , allNodes ) ; } } return allNodes ; } ; const getNextNode = ( node , allNodes ) => { const path = node . path || [ ] ; const nextPath = [ ... path . slice ( 0 , path . length - 1 ) , String ( Number ( path [ path . length - 1 ] ) + 1 ) , ] ; return allNodes . find ( ( item ) => ( item . path || [ ] ) . join ( '-' ) === nextPath . join ( '-' ) ) ; } ; const getNextIdsByBranchNode = ( node , allNodes , registerNodes ) => { const path = node . path || [ ] ; let branchPath ; if ( getIsConditionNode ( registerNodes , node . type ) ) { branchPath = path . slice ( 0 , path . length - 2 ) ; } else { branchPath = path . slice ( 0 , path . length - 4 ) ; } const branchNode = allNodes . find ( ( item ) => ( item . path || [ ] ) . join ( '-' ) === branchPath . join ( '-' ) ) ; if ( ! branchNode ) { return [ ] ; } const nextNode = getNextNode ( branchNode , allNodes ) ; if ( ! nextNode ) { return getNextIdsByBranchNode ( branchNode , allNodes , registerNodes ) ; } return [ nextNode . id ] ; } ; const getNextIds = ( node , allNodes , registerNodes ) => { if ( getIsBranchNode ( registerNodes , node . type ) ) { return ( node . children || [ ] ) . map ( ( item ) => item . id ) ; } else if ( getIsConditionNode ( registerNodes , node . type ) ) { const nextNode = node . children ?. [ 0 ] ; if ( ! nextNode ) { return getNextIdsByBranchNode ( node , allNodes , registerNodes ) ; } return [ nextNode . id ] ; } else if ( node . type === 'end' ) { return [ ] ; } else { const nextNode = getNextNode ( node , allNodes ) ; if ( ! nextNode ) { return getNextIdsByBranchNode ( node , allNodes , registerNodes ) ; } return [ nextNode . id ] ; } } ; export const buildFlatNodes = ( params ) => { const { registerNodes , nodes } = params ; const cloneNodes = JSON . parse ( JSON . stringify ( nodes ) ) ; const allNodes = DFS ( cloneNodes ) ; for ( const node of allNodes ) { node . next = node . next || [ ] ; const nextIds = getNextIds ( node , allNodes , registerNodes ) ; node . next . push ( ... nextIds . filter ( ( item ) => ! node . next ?. includes ( item ) ) ) ; } return allNodes . map ( ( { children , ... node } ) => node ) ; } ; const getParentByPath = ( path , treeNodes ) => { let parent = treeNodes ; for ( let index = 0 ; index < path . length ; index ++ ) { const item = path [ index ] ; if ( ! parent [ item ] ) { if ( index % 2 === 0 ) { parent [ item ] = { } ; } else { parent [ item ] = [ ] ; } } parent = parent [ item ] ; } return parent ; } ; export const buildTreeNodes = ( params ) => { const { nodes } = params ; const treeNodes = [ ] ; const cloneNodes = JSON . parse ( JSON . stringify ( nodes . map ( ( { next , ... node } ) => node ) ) ) ; for ( const node of cloneNodes ) { const path = node . path . slice ( ) ; const index = path . pop ( ) ; const parent = getParentByPath ( path , treeNodes ) ; if ( ! parent [ index ] ) { parent [ index ] = node ; } else { parent [ index ] = { ... parent [ index ] , ... node , } ; } } return treeNodes ; } ;