ソースを参照

feat: Edge节点受外部流程配置下一环节控制

lanjianrong 3 年 前
コミット
cdebc1939a

+ 6 - 4
src/pages/Project/Verification/Detail/Flow/components/Drawer/index.tsx

@@ -93,10 +93,12 @@ const FlowDrawer = () => {
     })
     if (code === consts.RET_CODE.SUCCESS) {
       message.success('保存成功')
-      dispatch({
-        type: Actions.SET_FLOW_NODE,
-        payload
-      })
+      setTimeout(() => {
+        dispatch({
+          type: Actions.SET_FLOW_NODE,
+          payload
+        })
+      }, 80)
       handleCancel()
     }
   }

+ 70 - 112
src/pages/Project/Verification/Detail/Flow/components/Edge/index.tsx

@@ -2,8 +2,9 @@ import { buildUUID } from '@/utils/uuid'
 import { SolutionOutlined } from '@ant-design/icons'
 import { Button, Popover } from 'antd'
 import React, { useMemo, useState, useContext } from 'react'
+import type { EdgeProps } from 'react-flow-renderer'
 import { getBezierPath, getEdgeCenter, getMarkerEnd, useStoreState } from 'react-flow-renderer'
-import { Actions, FlowContext } from '../../context'
+import { Actions, eId, FlowContext } from '../../context'
 import { generateElements, genreateElementEnum, getEdgeParams } from '../../utils'
 import { addApprovalNode } from '@/services/api/project'
 import styles from './index.less'
@@ -19,105 +20,7 @@ export enum SectorType {
   CONDITION = 'condition'
 }
 
-const RenderMenu = ({ dataID, source, dispatch, elements, togglePopver, id, flowInstance }) => {
-  const { run: showLoading } = useLoading()
-  const setElements = els => {
-    dispatch({
-      type: Actions.SET_ELEMENTS,
-      payload: els
-    })
-  }
-  // const edit = () => {
-  // togglePopver(false)
-  // dispatch({
-  //   type: Actions.OPEN_MODAL,
-  //   payload: {
-  //     id: node.id,
-  //     type: 'relation'
-  //   }
-  // })
-  // }
-  // const remove = () => {
-  //   dispatch({
-  //     type: Actions.REMOVE_FLOW_NODE,
-  //     payload: node
-  //   })
-  // }
-
-  const addAuditor = async () => {
-    const uid = buildUUID()
-    const newNode = {
-      id: uid,
-      type: 'input',
-      data: {}
-    }
-    const currentEdge = elements.find(item => item.id === id)
-    const newElements = generateElements(genreateElementEnum.ADD, elements)(newNode, currentEdge)
-
-    const { code = -1 } = await addApprovalNode({
-      ID: dataID,
-      segmentBrotherID: source,
-      flowProcess: newElements,
-      segment: {
-        ID: uid,
-        name: '审批人',
-        sectorType: SectorType.APPROVAL
-      }
-    })
-    if (code === consts.RET_CODE.SUCCESS) {
-      setElements(newElements)
-      dispatch({
-        type: Actions.SET_FLOW_NODE,
-        payload: {
-          id: uid,
-          node: null
-        }
-      })
-      togglePopver(false)
-      setTimeout(() => {
-        showLoading()
-        flowInstance?.fitView()
-      }, 80)
-    }
-  }
-
-  return (
-    // <Menu>
-    //   <Menu.Item key="1" onClick={addAuditor}>
-    //     <ClusterOutlined />
-    //     <span className="ml-1">审批人</span>
-    //   </Menu.Item>
-    //   {/* <Menu.Item key="2" onClick={remove}>
-    //     <ApartmentOutlined />
-    //     <span className="ml-1">条件分支</span>
-    //   </Menu.Item> */}
-    // </Menu>
-    <ul className="m-0 p-0 ">
-      <li>
-        <Button type="dashed" onClick={addAuditor} icon={<SolutionOutlined />}>
-          审批人
-        </Button>
-      </li>
-      {/* <li className="mt-2 condition">
-        <Button type="dashed" onClick={addAuditor} icon={<BranchesOutlined />}>
-          条件分支
-        </Button>
-      </li> */}
-    </ul>
-    //   <ul className="m-0 p-0">
-    //   <li className="rounded-2px border border-hex-d9d9d9 border-dashed text-hex-1890ff px-17px py-9px cursor-pointer">
-    //     <SolutionOutlined />
-    //     <span className="ml-9px">审批人</span>
-    //   </li>
-    //   <li className="mt-2 rounded-2px border border-hex-d9d9d9 border-dashed text-hex-52c41a px-17px py-9px cursor-pointer">
-    //     <BranchesOutlined />
-    //     <span className="ml-9px">条件分支</span>
-    //   </li>
-    // </ul>
-  )
-}
-
-export function CommonEdge(props) {
+export function CommonEdge(props: EdgeProps) {
   const {
     id,
     sourceX,
@@ -133,8 +36,21 @@ export function CommonEdge(props) {
 
   const [visible, setVisible] = useState(false)
   const { flowState, dispatch } = useContext(FlowContext)
-  const { elements, flowInstance, dataID, readPretty } = flowState
-  // source连接的node节点
+  const { elements, flowInstance, flowData, dataID, readPretty } = flowState
+  const { run: showLoading } = useLoading()
+  const setElements = els => {
+    dispatch({
+      type: Actions.SET_ELEMENTS,
+      payload: els
+    })
+  }
+  const showBtn =
+    target === eId
+      ? flowData
+          .get(source)
+          ?.accounts.every(item => !item.configure.includes(ConfigureType.NEXTSECTOR))
+      : true
+
   const nodes = useStoreState(store => store.nodes)
   const markerEnd = getMarkerEnd(arrowHeadType, markerEndId)
 
@@ -172,10 +88,47 @@ export function CommonEdge(props) {
     // alert(`remove ${id}`)
   }
 
+  const addAuditor = async () => {
+    const uid = buildUUID()
+    const newNode = {
+      id: uid,
+      type: 'input',
+      data: {}
+    }
+    const currentEdge = elements.find(item => item.id === id)
+    const newElements = generateElements(genreateElementEnum.ADD, elements)(newNode, currentEdge)
+
+    const { code = -1 } = await addApprovalNode({
+      ID: dataID,
+      segmentBrotherID: source,
+      flowProcess: newElements,
+      segment: {
+        ID: uid,
+        name: '审批人',
+        sectorType: SectorType.APPROVAL
+      }
+    })
+    if (code === consts.RET_CODE.SUCCESS) {
+      setElements(newElements)
+      dispatch({
+        type: Actions.SET_FLOW_NODE,
+        payload: {
+          id: uid,
+          node: null
+        }
+      })
+      togglePopver(false)
+      setTimeout(() => {
+        showLoading()
+        flowInstance?.fitView()
+      }, 80)
+    }
+  }
+
   return (
     <>
       <path id={id} style={style} className={styles.flowPath} d={d} markerEnd={markerEnd} />
-      {!readPretty && (
+      {showBtn && !readPretty && (
         <foreignObject
           width={foreignObjectSize}
           height={foreignObjectSize}
@@ -183,15 +136,20 @@ export function CommonEdge(props) {
           y={edgeCenterY - foreignObjectSize / 2}>
           <div className={styles.addIcon}>
             <Popover
-              content={RenderMenu({
-                elements,
-                dispatch,
-                source,
-                togglePopver,
-                id,
-                flowInstance,
-                dataID
-              })}
+              content={
+                <ul className="m-0 p-0 ">
+                  <li>
+                    <Button type="dashed" onClick={addAuditor} icon={<SolutionOutlined />}>
+                      审批人
+                    </Button>
+                  </li>
+                  {/* <li className="mt-2 condition">
+        <Button type="dashed" onClick={addAuditor} icon={<BranchesOutlined />}>
+          条件分支
+        </Button>
+      </li> */}
+                </ul>
+              }
               trigger="click"
               placement="right"
               visible={visible}

+ 18 - 39
src/pages/Project/Verification/Detail/Flow/components/Graph/index.tsx

@@ -38,15 +38,18 @@ const FlowGroph: React.FC<FlowGrophProps> = ({
     []
   )
 
-  useEffect(() => {
-    if (flowProcess?.length) {
-      dispatch({
-        type: Actions.SET_ELEMENTS,
-        payload: flowProcess
-      })
-      dispatch({
-        type: Actions.SET_FLOW_NODE,
-        payload: new Map(
+  const { elements } = flowState
+
+  const defaultOptions = {
+    nodesDraggable: false, // 不可拖拽
+    // zoomOnScroll: false, // 使用鼠标滚轮或触控板放大和缩小图形
+    zoomOnPinch: false, // 使用捏合放大和缩小图形
+    // snapToGrid: true,
+    onLoad: reactFlowInstance => {
+      const payload = {}
+      if (flowProcess?.length) {
+        payload.elements = flowProcess
+        payload.flowData = new Map(
           Object.entries(
             flowProcessData.reduce((prev, curr) => {
               if (curr.ID) {
@@ -56,39 +59,15 @@ const FlowGroph: React.FC<FlowGrophProps> = ({
             }, {})
           )
         )
-      })
-    } else {
-      dispatch({
-        type: Actions.SET_ELEMENTS,
-        payload: initialElements
-      })
+      }
+      payload.flowInstance = reactFlowInstance
+      payload.dataID = dataID
+      payload.readPretty = readPretty
 
       dispatch({
-        type: Actions.SET_FLOW_NODE,
-        payload: new Map()
+        type: Actions.INIT_FLOW_CONTEXT,
+        payload
       })
-    }
-  }, [])
-  const { elements } = flowState
-
-  const defaultOptions = {
-    nodesDraggable: false, // 不可拖拽
-    // zoomOnScroll: false, // 使用鼠标滚轮或触控板放大和缩小图形
-    zoomOnPinch: false, // 使用捏合放大和缩小图形
-    // snapToGrid: true,
-    onLoad: reactFlowInstance => {
-      dispatch({
-        type: Actions.SET_FLOW_INSTANCE,
-        payload: reactFlowInstance
-      })
-      dispatch({
-        type: Actions.SET_FOLW_PROPS,
-        payload: {
-          dataID,
-          readPretty
-        }
-      })
-
       setTimeout(() => {
         reactFlowInstance?.fitView()
       }, 0)

+ 6 - 1
src/pages/Project/Verification/Detail/Flow/context/reducer.ts

@@ -70,6 +70,10 @@ const closeModal = state => ({
   }
 })
 
+const onStoreLoad = (state, payload) => ({
+  ...state,
+  ...payload
+})
 // 管理所有处理函数
 const handlerMap = {
   [Actions.SET_FLOW_NODE]: setFlowNode,
@@ -78,7 +82,8 @@ const handlerMap = {
   [Actions.CLOSE_MODAL]: closeModal,
   [Actions.SET_ELEMENTS]: setElements,
   [Actions.SET_FLOW_INSTANCE]: setFlowInstance,
-  [Actions.SET_FOLW_PROPS]: setFlowProps
+  [Actions.SET_FOLW_PROPS]: setFlowProps,
+  [Actions.INIT_FLOW_CONTEXT]: onStoreLoad
 }
 
 const reducer = (state: InitialState, action: Actions) => {

+ 1 - 0
src/pages/Project/Verification/Detail/Flow/enum/index.ts

@@ -1,4 +1,5 @@
 export enum Actions {
+  INIT_FLOW_CONTEXT = 'init_flow_context',
   SET_ELEMENTS = 'set_elements',
   SET_FLOW_NODE = 'set_flow_node',
   SET_FLOW_INSTANCE = 'set_flow_instance',

+ 7 - 3
src/pages/Project/Verification/Detail/Flow/hooks/useLoading.tsx

@@ -1,6 +1,6 @@
 import { isDef } from '@/utils/is'
 import { useDebounceFn } from 'ahooks'
-import { useContext } from 'react'
+import { useContext, useEffect } from 'react'
 import { FlowContext } from '../context'
 import { Actions } from '../enum'
 type LoadingOptions = {
@@ -17,8 +17,12 @@ const useLoading = (opt: LoadingOptions = { delay: 500 }) => {
       }
     })
   }
-  const { run: resetLoading } = useDebounceFn(cancel, { wait: opt.delay })
-
+  const { run: resetLoading, cancel: tryCancelDebounceFn } = useDebounceFn(cancel, {
+    wait: opt.delay
+  })
+  useEffect(() => {
+    return () => tryCancelDebounceFn()
+  }, [])
   const run = () => {
     // 若当前loading为true停止执行
     if (isDef(flowState.canvasLoading) && flowState.canvasLoading) {