Selaa lähdekoodia

feat: [flow] 增加useLoading hook管理流程画布的loading状态

lanjianrong 3 vuotta sitten
vanhempi
commit
63e5209c3a

+ 0 - 3
src/pages/Project/Verification/Detail/Flow/components/Drawer/index.tsx

@@ -74,9 +74,6 @@ const FlowDrawer = () => {
       })
       return
     }
-    // if (!validate(accounts)) {
-    //   return message.error('当前流程信息配置不完整,请检查!')
-    // }
     const payload = {
       id: nodeID,
       node: {

+ 5 - 4
src/pages/Project/Verification/Detail/Flow/components/Edge/index.tsx

@@ -9,6 +9,7 @@ import { addApprovalNode } from '@/services/api/project'
 import styles from './index.less'
 import 'antd/lib/button/style/css'
 import consts from '@/utils/consts'
+import useLoading from '../../hooks/useLoading'
 const foreignObjectSize = 50
 
 export enum SectorType {
@@ -16,7 +17,8 @@ export enum SectorType {
   CONDITION = 'condition'
 }
 
-const renderMenu = ({ dataID, source, dispatch, elements, togglePopver, id, flowInstance }) => {
+const RenderMenu = ({ dataID, source, dispatch, elements, togglePopver, id, flowInstance }) => {
+  const { run: showLoading } = useLoading()
   const setElements = els => {
     dispatch({
       type: Actions.SET_ELEMENTS,
@@ -69,6 +71,7 @@ const renderMenu = ({ dataID, source, dispatch, elements, togglePopver, id, flow
           node: null
         }
       })
+      showLoading()
       togglePopver(false)
       setTimeout(() => {
         flowInstance?.fitView()
@@ -166,8 +169,6 @@ export function CommonEdge(props) {
     // alert(`remove ${id}`)
   }
 
-  console.log(readPretty)
-
   return (
     <>
       <path id={id} style={style} className={styles.flowPath} d={d} markerEnd={markerEnd} />
@@ -179,7 +180,7 @@ export function CommonEdge(props) {
         <div className={styles.addIcon}>
           {!readPretty ? (
             <Popover
-              content={renderMenu({
+              content={RenderMenu({
                 elements,
                 dispatch,
                 source,

+ 4 - 3
src/pages/Project/Verification/Detail/Flow/components/Node/index.tsx

@@ -6,6 +6,7 @@ import { removeApprovalNode } from '@/services/api/project'
 import consts from '@/utils/consts'
 import { generateElements, genreateElementEnum } from '../../utils'
 import { message } from 'antd'
+import useLoading from '../../hooks/useLoading'
 export const InputNode = () => {
   return (
     <>
@@ -34,11 +35,10 @@ export const OutputNode = () => {
   )
 }
 
-export const CommonNode = props => {
-  const { id, data } = props
-
+export const CommonNode = ({ id, data }) => {
   const { flowState, dispatch } = useContext(FlowContext)
   const { flowInstance, flowData, readPretty } = flowState
+  const { run: showLoading } = useLoading()
   const removeNode = async () => {
     const node = { id, data }
     const newElements = generateElements(genreateElementEnum.DEL, flowState.elements)(node)
@@ -53,6 +53,7 @@ export const CommonNode = props => {
         type: Actions.REMOVE_FLOW_NODE,
         payload: { ...node, newElements }
       })
+      showLoading()
       setTimeout(() => {
         flowInstance?.fitView()
       }, 80)

+ 12 - 1
src/pages/Project/Verification/Detail/Flow/components/Toolbar/index.tsx

@@ -1,7 +1,7 @@
 import { CloudUploadOutlined } from '@ant-design/icons'
 import { useContext } from 'react'
 import { Button, message, Modal } from 'antd'
-import { FlowContext } from '../../context'
+import { FlowContext, InitialState } from '../../context'
 import { addApprovalFlow } from '@/services/api/project'
 import consts from '@/utils/consts'
 import { isNode } from 'react-flow-renderer'
@@ -51,3 +51,14 @@ export default function ToolBar(props: {
     </div>
   )
 }
+
+export const LoadingBar = () => {
+  const {
+    flowState: { canvasLoading = false }
+  } = useContext(FlowContext)
+  return (
+    <div className="absolute bottom-3">
+      {canvasLoading && <span className="text-gray-500">正在保存...</span>}
+    </div>
+  )
+}

+ 11 - 11
src/pages/Project/Verification/Detail/Flow/context/index.tsx

@@ -5,17 +5,21 @@ import { Actions } from '../enum'
 import type { Elements, OnLoadParams } from 'react-flow-renderer'
 import { ArrowHeadType } from 'react-flow-renderer'
 
-const FlowContext = createContext()
-
-type InitialState = {
+const FlowContext = createContext<Partial<InitialState>>({})
+export type InitialState = {
   elements: Elements
   flowInstance?: OnLoadParams | null
   flowData: Map<string, any>
+  /** @name 抽屉控制器 */
   modalConfig: {
     visible: boolean
-    nodeType: string
-    nodeType: string
+    nodeType?: string | null
+    nodeId?: string | null
   }
+  /** @name 只读态 */
+  readPretty?: boolean
+  /** @name 画布loading控制器 */
+  canvasLoading?: boolean
 }
 
 export const initialElements = [
@@ -42,15 +46,11 @@ export const initialElements = [
   }
 ]
 const initialState: InitialState = {
-  // node节点或者是edge
   elements: initialElements,
   flowData: new Map(),
   modalConfig: {
-    visible: false,
-    nodeType: '',
-    nodeId: ''
-  },
-  flowInstance: null
+    visible: false
+  }
 }
 
 const FlowContextProvider = props => {

+ 2 - 7
src/pages/Project/Verification/Detail/Flow/context/reducer.ts

@@ -1,12 +1,7 @@
-// context/reducer.js
-// import { removeElements } from 'react-flow-renderer'
-
-import { removeApprovalNode } from '@/services/api/project'
-import consts from '@/utils/consts'
 import { isNullOrUnDef } from '@/utils/is'
 import type { Elements } from 'react-flow-renderer'
 import { Actions } from '../enum'
-import { generateElements, genreateElementEnum } from '../utils'
+import type { InitialState } from '.'
 
 export enum ProcessType {
   NODE = '1'
@@ -86,7 +81,7 @@ const handlerMap = {
   [Actions.SET_FOLW_PROPS]: setFlowProps
 }
 
-const reducer = (state, action) => {
+const reducer = (state: InitialState, action: Actions) => {
   const { type, payload } = action
   const handler = handlerMap[type]
   const res = typeof handler === 'function' && handler(state, payload)

+ 37 - 0
src/pages/Project/Verification/Detail/Flow/hooks/useLoading.tsx

@@ -0,0 +1,37 @@
+import { isDef } from '@/utils/is'
+import { useDebounceFn } from 'ahooks'
+import { useContext } from 'react'
+import { FlowContext } from '../context'
+import { Actions } from '../enum'
+type LoadingOptions = {
+  /** @name 延迟时间 */
+  delay?: number
+}
+const useLoading = (opt: LoadingOptions = { delay: 500 }) => {
+  const { flowState, dispatch } = useContext(FlowContext)
+  const cancel = () => {
+    dispatch({
+      type: Actions.SET_FOLW_PROPS,
+      payload: {
+        canvasLoading: false
+      }
+    })
+  }
+  const { run: resetLoading } = useDebounceFn(cancel, { wait: opt.delay })
+
+  const run = () => {
+    // 若当前loading为true停止执行
+    if (isDef(flowState.canvasLoading) && flowState.canvasLoading) {
+      return
+    }
+    dispatch({
+      type: Actions.SET_FOLW_PROPS,
+      payload: {
+        canvasLoading: true
+      }
+    })
+    resetLoading()
+  }
+  return { run }
+}
+export default useLoading

+ 2 - 0
src/pages/Project/Verification/Detail/Flow/index.tsx

@@ -6,6 +6,7 @@ import FlowDrawer from './components/Drawer'
 import { useRequest } from 'umi'
 import { queryApprovalDetail } from '@/services/api/project'
 import './index.less'
+import { LoadingBar } from './components/Toolbar'
 
 type ApprovalFlowProps = {
   dataID: string
@@ -44,6 +45,7 @@ const ApprovalFlow: React.FC<ApprovalFlowProps> = ({ readPretty, dataID }) => {
               />
             ) : null}
           </div>
+          <LoadingBar />
           <FlowDrawer />
         </ReactFlowProvider>
       </FlowContextProvider>