Forráskód Böngészése

fix: 步骤配置各项异步数据来源调优处理

lanjianrong 3 éve
szülő
commit
4f87b1e6f2

+ 3 - 3
src/pages/Business/Inventory/hooks/useRowScript.tsx

@@ -144,11 +144,11 @@ export function useRowScript(modal: ModalAction) {
       cancelText: '取消',
       initialValues:
         mode === 'add'
-          ? { parentID: state.record?.ID, enable: 0, required: 1 }
+          ? { parentID: state.record?.ID, enable: 1, required: 1 }
           : {
               ...state.record,
-              enable: Number(!!state.record?.enable),
-              required: Number(!!state.record?.required)
+              enable: Number(state.record?.enable),
+              required: Number(state.record?.required)
             },
       children: (
         <ProForm submitter={false} layout="horizontal" labelCol={{ span: 4 }} isKeyPressSubmit>

+ 2 - 5
src/pages/Business/Inventory/index.less

@@ -1,8 +1,5 @@
-.modeBox {
-  span {
+.modeBox:not(:first-child) {
+  & > :not(:first-of-type) {
     margin-left: 0.25rem;
   }
-  span:first-child {
-    margin-left: 0;
-  }
 }

+ 0 - 1
src/pages/Business/Matter/hooks/useRowScript.tsx

@@ -46,7 +46,6 @@ export function useRowScript(modal: ModalAction) {
         treeList: result,
         expandTreeIds: expandTreeList(result)
       })
-      // setState({ ...state, treeList: result || [] })
     }
   })
 

+ 2 - 2
src/pages/Business/Process/hooks/useScripts.tsx

@@ -61,10 +61,10 @@ export default function useScripts(modal: ModalAction, subject: string) {
       const { gatherID, businessType } = params[0]
       seState({ total: result.data.total })
       dispatch({
-        type: 'business/updateProcessMap',
+        type: 'business/updateExecutorMap',
         payload: {
           ID: `${gatherID}_${businessType}`,
-          process: result.data.items
+          list: result.data.items
         }
       })
     }

+ 11 - 26
src/pages/Business/Step/components/Flow/components/Drawer/Condition/index.tsx

@@ -1,9 +1,8 @@
 import consts from '@/utils/consts'
 import { isString } from '@/utils/is'
 import { FormItem, Editable, Input, Select, Radio, DatePicker, ArrayItems, Space } from '@formily/antd'
-import { createForm, FormPathPattern, onFieldMount, onFieldReact, Field as FieldType } from '@formily/core'
+import { createForm, onFieldMount, onFieldReact } from '@formily/core'
 import { FormProvider, createSchemaField, Schema } from '@formily/react'
-import { action } from '@formily/reactive'
 import { request, useStore } from '@umijs/max'
 import { Button } from 'antd'
 import { useContext, useMemo } from 'react'
@@ -36,21 +35,6 @@ type ConditionProps = {
   >
 }
 
-const useAsyncDataSource = (
-  pattern: FormPathPattern,
-  service: (field: FieldType) => Promise<{ label: string; value: any }[]>
-) => {
-  onFieldReact(pattern, field => {
-    field.loading = true
-    service(field).then(
-      action.bound(data => {
-        field.dataSource = data
-        field.loading = false
-      })
-    )
-  })
-}
-
 const Condition: React.FC<ConditionProps> = ({ nodeId, nodeData }) => {
   const { flowStore, dispatch } = useContext(FlowContext)
   // const dvaDispatch = useDispatch()
@@ -78,17 +62,14 @@ const Condition: React.FC<ConditionProps> = ({ nodeId, nodeData }) => {
         }
         field.dataSource = fieldOptions
       })
-      // eslint-disable-next-line react-hooks/rules-of-hooks
-      useAsyncDataSource('conditions.*.value', async field => {
+      onFieldReact('conditions.*.value', async field => {
         const value = field.query('conditions.*.field').value()
         if (value) {
           field.query('conditions.*.type').value = formSchema.properties[value].type
-          field.loading = true
-          // if (conditionMap?.[flowStore.dataID]?.value) {
-          //   console.log(conditionMap?.[flowStore.dataID]?.value)
-
-          //   return conditionMap?.[flowStore.dataID]?.value
-          // }
+          if (flowStore.conditionValueToMap?.[value]) {
+            field.dataSource = flowStore.conditionValueToMap?.[value] || []
+            return
+          }
           try {
             const { code = -1, data } = await request('/form/v1/ds/items', {
               params: { name: formSchema.properties[value].title }
@@ -100,8 +81,12 @@ const Condition: React.FC<ConditionProps> = ({ nodeId, nodeData }) => {
                   label: item.name,
                   value: item.ID
                 })) || []
-              return options
+              field.dataSource = options
             }
+            dispatch({
+              type: 'set_flow_condition_map',
+              payload: { [value]: options }
+            })
           } catch (error) {}
         }
         return []

+ 45 - 65
src/pages/Business/Step/components/Flow/components/Node/ConditionNode.tsx

@@ -1,7 +1,7 @@
 import { BusinessModelState } from '@/pages/Business/model'
 import { isString } from '@/utils/is'
 import { CloseOutlined, RightOutlined } from '@ant-design/icons'
-import { createForm, FormPathPattern, onFieldMount, onFieldReact } from '@formily/core'
+import { createForm, onFieldMount, onFieldReact } from '@formily/core'
 import { createSchemaField, FormProvider } from '@formily/react'
 import { Select, ArrayItems, FormItem, Space } from '@formily/antd'
 import { connect, request } from '@umijs/max'
@@ -12,7 +12,6 @@ import { FlowContext } from '../../context'
 import Condition from '../Drawer/Condition'
 import { prettySchema } from '../Drawer/Condition/schema'
 import { delNode, findNodeById } from '../Edge/utils'
-import { action } from '@formily/reactive'
 import consts from '@/utils/consts'
 const SchemaField = createSchemaField({
   components: {
@@ -26,20 +25,6 @@ type NodeConditionData = {
   parentId: string
   priority: number
 }
-const useAsyncDataSource = (
-  pattern: FormPathPattern,
-  service: (field: FieldType) => Promise<{ label: string; value: any }[]>
-) => {
-  onFieldReact(pattern, field => {
-    field.loading = true
-    service(field).then(
-      action.bound(data => {
-        field.dataSource = data
-        field.loading = false
-      })
-    )
-  })
-}
 
 export const ConditionNode = connect(({ business }: { business: BusinessModelState }) => ({
   conditionSchema: business.conditionSchema
@@ -106,58 +91,53 @@ export const ConditionNode = connect(({ business }: { business: BusinessModelSta
       return schema
     }, [flowStore.dataID, conditionSchema])
 
-    const form = createForm({
-      initialValues: conditions?.[0],
-      readPretty: true,
-      effects() {
-        onFieldMount('field', field => {
-          const properties = formSchema?.properties || {}
-          const fieldOptions = []
-          for (const key in properties) {
-            if (Object.prototype.hasOwnProperty.call(properties, key)) {
-              const element = properties[key]
-              fieldOptions.push({ label: element?.title, value: key })
+    const form = useMemo(() => {
+      return createForm({
+        initialValues: conditions?.[0],
+        readPretty: true,
+        effects() {
+          onFieldMount('field', field => {
+            const properties = formSchema?.properties || {}
+            const fieldOptions = []
+            for (const key in properties) {
+              if (Object.prototype.hasOwnProperty.call(properties, key)) {
+                const element = properties[key]
+                fieldOptions.push({ label: element?.title, value: key })
+              }
             }
-          }
-          field.dataSource = fieldOptions
-        })
-        // eslint-disable-next-line react-hooks/rules-of-hooks
-        useAsyncDataSource('value', async field => {
-          const value = field.query('field').value()
-          if (value) {
-            // field.query('type').value = formSchema.properties[value].type
-            field.loading = true
-            // if (conditionMap?.[flowStore.dataID]?.value) {
-            //   return conditionMap?.[flowStore.dataID]?.value
-            // }
-            try {
-              const { code = -1, data } = await request('/form/v1/ds/items', {
-                params: { name: formSchema.properties[value].title }
-              })
-              if (code === consts.RET_CODE.SUCCESS) {
-                const options =
-                  data?.map(item => ({
-                    label: item.name,
-                    value: item.ID
-                  })) || []
-                // dvaDispatch({
-                //   type: 'business/updateConditionMap',
-                //   payload: {
-                //     [flowStore.dataID]: {
-                //       [value]: options
-                //     }
-                //   }
-                // })
-                return options
+            field.dataSource = fieldOptions
+          })
+          onFieldReact('value', async field => {
+            const value = field.query('field').value()
+            if (value) {
+              if (flowStore.conditionValueToMap?.[value]) {
+                field.dataSource = flowStore.conditionValueToMap?.[value] || []
+                return
+              }
+              try {
+                const { code = -1, data } = await request('/form/v1/ds/items', {
+                  params: { name: formSchema.properties[value].title }
+                })
+                if (code === consts.RET_CODE.SUCCESS) {
+                  const options =
+                    data?.map(item => ({
+                      label: item.name,
+                      value: item.ID
+                    })) || []
+                  field.dataSource = options
+                  dispatch({
+                    type: 'set_flow_condition_map',
+                    payload: { [value]: options }
+                  })
+                }
+              } catch (error) {
+                console.log(error)
               }
-            } catch (error) {
-              console.log(error)
             }
-          }
-          return []
-        })
-      }
-    })
+          })
+        }
+      })
+    }, [conditions])
     return (
       <>
         <Handle type="target" position="top" />

+ 5 - 3
src/pages/Business/Step/components/Flow/context/index.tsx

@@ -13,14 +13,15 @@ export type FlowContextState = {
   flowInstance?: OnLoadParams
   drawer: DrawerAction
   executorList: API.ExecutorItem[]
-  matterList: any[]
+  matterList: API.MatterItem[]
+  conditionValueToMap: Record<string, string>
 }
 type FlowContextProviderProps = {
   children: React.ReactNode
   initialProcess: Elements
   dataID: string
   executorList: API.ExecutorItem[]
-  matterList: any[]
+  matterList: API.MatterItem[]
 }
 
 export type DispatchAction = Dispatch<{
@@ -37,7 +38,8 @@ const FlowContextProvider: React.FC<FlowContextProviderProps> = props => {
     elements: transformElements(initialProcess),
     dataID,
     executorList,
-    matterList
+    matterList,
+    conditionValueToMap: {}
   })
   return <FlowContext.Provider value={{ flowStore, dispatch }}>{children}</FlowContext.Provider>
 }

+ 9 - 58
src/pages/Business/Step/components/Flow/context/reducer.ts

@@ -1,4 +1,3 @@
-import { isNullOrUnDef } from '@/utils/is'
 import { Actions } from '../enum'
 import type { InitialState } from '.'
 import { FlowTreeNode } from '@/components/Flow/src/type'
@@ -16,19 +15,6 @@ const setFlowProcess = (state, process: FlowTreeNode[]) => {
   }
 }
 
-const setFlowNode = (state, payload) => {
-  const res = { ...state }
-  const { id, data } = payload
-  if (!id) return state
-  res.elements = res.elements.map(item => {
-    if (item.id === id) {
-      item.data = data
-    }
-    return item
-  })
-  return res
-}
-
 const setFlowInstance = (state, flowInstance) => {
   if (flowInstance) {
     return { ...state, flowInstance }
@@ -36,59 +22,24 @@ const setFlowInstance = (state, flowInstance) => {
   return state
 }
 
-const removeFlowNode = (state, node) => {
-  const { id, newElements } = node
-  const res = { ...state }
-  res.elements = newElements
-  if (res.flowData.get(id)) {
-    res.flowData.delete(id)
-  }
-  return res
-}
+const onStoreLoad = (state, payload) => ({
+  ...state,
+  ...payload
+})
 
-const setFlowProps = (state, props) => {
-  if (!isNullOrUnDef(props)) {
-    return { ...state, ...props }
+const setFlowCondition = (state, map) => {
+  if (map) {
+    return { ...state, conditionValueToMap: { ...state.conditionValueToMap, ...map } }
   }
   return state
 }
 
-const openModal = (state, node) => {
-  return node?.id
-    ? {
-        ...state,
-        modalConfig: {
-          visible: true,
-          nodeType: node.type,
-          nodeID: node.id
-        }
-      }
-    : state
-}
-
-const closeModal = state => ({
-  ...state,
-  modalConfig: {
-    visible: false,
-    nodeType: null,
-    nodeID: null
-  }
-})
-
-const onStoreLoad = (state, payload) => ({
-  ...state,
-  ...payload
-})
 // 管理所有处理函数
 const handlerMap = {
-  [Actions.SET_FLOW_NODE]: setFlowNode,
-  [Actions.REMOVE_FLOW_NODE]: removeFlowNode,
-  [Actions.OPEN_MODAL]: openModal,
-  [Actions.CLOSE_MODAL]: closeModal,
   [Actions.SET_FLOW_PROCESS]: setFlowProcess,
   [Actions.SET_FLOW_INSTANCE]: setFlowInstance,
-  [Actions.SET_FOLW_PROPS]: setFlowProps,
-  [Actions.INIT_FLOW_CONTEXT]: onStoreLoad
+  [Actions.INIT_FLOW_CONTEXT]: onStoreLoad,
+  [Actions.SET_FLOW_CONDITION_MAP]: setFlowCondition
 }
 
 const reducer = (state: InitialState, action: DispatchAction) => {

+ 1 - 5
src/pages/Business/Step/components/Flow/enum/index.ts

@@ -1,12 +1,8 @@
 export enum Actions {
   INIT_FLOW_CONTEXT = 'init_flow_context',
   SET_FLOW_PROCESS = 'set_flow_process',
-  SET_FLOW_NODE = 'set_flow_node',
   SET_FLOW_INSTANCE = 'set_flow_instance',
-  SET_FOLW_PROPS = 'set_flow_props',
-  REMOVE_FLOW_NODE = 'remove_flow_node',
-  OPEN_MODAL = 'open_modal',
-  CLOSE_MODAL = 'close_modal'
+  SET_FLOW_CONDITION_MAP = 'set_flow_condition_map'
 }
 
 /** 环节类型 */

+ 55 - 63
src/pages/Business/Step/index.tsx

@@ -1,22 +1,23 @@
 import useDrawer from '@/components/Drawer'
-// import { mockNodes } from '@/components/Flow/src/shared/transformer'
-import { queryMatterList } from '@/services/api/business'
 import { queryApprovalDetail } from '@/services/api/project'
 import consts from '@/utils/consts'
 import { PageContainer } from '@ant-design/pro-layout'
-import ProTable, { ActionType, ProColumns } from '@ant-design/pro-table'
+import ProTable, { ProColumns } from '@ant-design/pro-table'
 import { connect } from '@umijs/max'
 import { Button } from 'antd'
-import { Dispatch, useEffect, useMemo, useRef, useState } from 'react'
+import { Dispatch, useEffect, useState } from 'react'
 import { BusinessModelState } from '../model'
 import LeftMenu from '../RuleCode/components/LeftMenu'
 import ApprovalFlow from './components/Flow'
 import { transformToFlowNodes } from './components/Flow/shared/transformer'
 
 type StepProps = {
-  processMap: {
+  executorMap: {
     [key: string]: API.ExecutorItem[]
   }
+  matterMap: {
+    [key: string]: API.MatterItem[]
+  }
   conditionSchema: Record<
     string,
     {
@@ -29,45 +30,55 @@ type StepProps = {
 }
 type iState = {
   activeKey: string | null
-  process: API.ApprovalProcess[]
+  process: {
+    detail: API.ApprovalProcess[]
+    list: any[]
+  }
   subjectName?: string
 }
-const Step: React.FC<StepProps> = ({ processMap, conditionSchema, dispatch }) => {
+const Step: React.FC<StepProps> = ({ executorMap, matterMap, conditionSchema, dispatch }) => {
   const [drawer, DrawerDOM] = useDrawer()
-  const actionRef = useRef<ActionType>()
   const [state, setState] = useState<iState>({
     activeKey: null,
-    process: []
+    process: {}
   })
 
   useEffect(() => {
+    async function initData(params: { gatherID: string; businessType: string }) {
+      const {
+        code = -1,
+        data: { process = [], processList = [] }
+      } = await queryApprovalDetail(params)
+      if (code === consts.RET_CODE.SUCCESS) {
+        setState({ ...state, process: { detail: process, list: processList } })
+      }
+    }
     if (state.activeKey) {
       const [gatherID, businessType] = state.activeKey.split('_')
-      dispatch({
-        type: 'business/queryExecutor',
-        payload: { gatherID, businessType, pageSize: 214000 }
-      })
+      if (!executorMap?.[state.activeKey]) {
+        dispatch({
+          type: 'business/queryExecutor',
+          payload: { gatherID, businessType, pageSize: 214000 }
+        })
+      }
+      if (!matterMap?.[state.activeKey]) {
+        dispatch({
+          type: 'business/queryMatter',
+          payload: { gatherID, businessType, pageSize: 214000, matterType: 'matter' }
+        })
+      }
       if (!conditionSchema?.[state.activeKey]) {
         dispatch({
           type: 'business/queryCondition',
           payload: state.activeKey
         })
       }
+      initData({ gatherID, businessType })
     }
   }, [state.activeKey])
-  const params = useMemo(() => {
-    if (!state.activeKey) return {}
-    const [gatherID, businessType] = state.activeKey.split('_')
-    return { gatherID, businessType }
-  }, [state.activeKey])
 
-  const handleMenuChange = (key: string, option) => {
-    console.log(option)
-
-    setState({ ...state, activeKey: key })
-    actionRef.current?.reload()
-    // const [gatherID, businessType] = key.split('_')
-    //
+  const handleMenuChange = (key: string, option?: { value: string; label: string }) => {
+    setState({ ...state, activeKey: key, subjectName: option?.label || '' })
   }
   const columns: ProColumns = [
     {
@@ -76,38 +87,31 @@ const Step: React.FC<StepProps> = ({ processMap, conditionSchema, dispatch }) =>
       width: '50%'
     },
     {
-      dataIndex: 'executor',
+      dataIndex: 'executorName',
       title: '执行者',
       width: '20%'
     },
     {
-      dataIndex: 'matter',
+      dataIndex: 'matterNames',
       title: '事项名称',
       width: '30%'
     }
   ]
 
   const handleBtnClick = async () => {
-    const [gatherID, businessType] = state.activeKey.split('_')
-    queryMatterList({ gatherID, businessType, pageSize: 214000, matterType: 'matter' }).then(
-      ({ code = -1, data: { items: matters = [] } = {} }) => {
-        if (code === consts.RET_CODE.SUCCESS) {
-          drawer.open({
-            title: state.subjectName,
-            destroyOnClose: true,
-            children: (
-              <ApprovalFlow
-                executorList={processMap[state.activeKey]}
-                matterList={matters}
-                dataID={state.activeKey}
-                defaultValue={transformToFlowNodes(state.process)}
-                // defaultValue={mockNodes}
-              />
-            )
-          })
-        }
-      }
-    )
+    drawer.open({
+      title: state.subjectName,
+      destroyOnClose: true,
+      children: (
+        <ApprovalFlow
+          executorList={executorMap[state.activeKey]}
+          matterList={matterMap[state.activeKey]}
+          dataID={state.activeKey}
+          defaultValue={transformToFlowNodes(state.process.detail)}
+          // defaultValue={mockNodes}
+        />
+      )
+    })
   }
   return (
     <PageContainer title={false}>
@@ -115,11 +119,10 @@ const Step: React.FC<StepProps> = ({ processMap, conditionSchema, dispatch }) =>
         <LeftMenu title="业务主体" onChange={handleMenuChange} />
         <div className="w-6/7 ml-8 bg-white rounded-20px">
           <ProTable
-            manualRequest
-            actionRef={actionRef}
-            params={params}
             columns={columns}
             search={false}
+            rowKey="ID"
+            dataSource={state.process.list}
             toolbar={{
               actions: [
                 <Button key="step-config" type="primary" onClick={handleBtnClick}>
@@ -127,18 +130,6 @@ const Step: React.FC<StepProps> = ({ processMap, conditionSchema, dispatch }) =>
                 </Button>
               ]
             }}
-            request={async params => {
-              const {
-                code,
-                data: { subjectName, process = [], processList = [] }
-              } = await queryApprovalDetail(params)
-              setState({ ...state, process, subjectName })
-              return {
-                total: processList.length,
-                data: processList,
-                success: code === consts.RET_CODE.SUCCESS
-              }
-            }}
           />
         </div>
       </div>
@@ -148,6 +139,7 @@ const Step: React.FC<StepProps> = ({ processMap, conditionSchema, dispatch }) =>
 }
 
 export default connect(({ business }: { business: BusinessModelState }) => ({
-  processMap: business.processMap,
+  executorMap: business.executorMap,
+  matterMap: business.matterMap,
   conditionSchema: business.conditionSchema
 }))(Step)

+ 55 - 12
src/pages/Business/model.ts

@@ -1,4 +1,9 @@
-import { queryConditionSchema, queryExecutorList } from '@/services/api/business'
+import {
+  queryConditionSchema,
+  queryExecutorList,
+  queryMatterDetail,
+  queryMatterTree
+} from '@/services/api/business'
 import { queryInstitutionList } from '@/services/api/institution'
 import { querySubjectList } from '@/services/api/subject'
 import consts from '@/utils/consts'
@@ -7,9 +12,13 @@ import type { Effect, Reducer } from '@umijs/max'
 export interface BusinessModelState {
   institutionList: API.InstitutionList[]
   subjectList: API.SubjectParams[]
-  processMap: {
+  matterDetail: API.MatterTreeItem[]
+  executorMap: {
     [key: string]: API.ExecutorItem[]
   }
+  matterMap: {
+    [key: string]: API.MatterItem[]
+  }
   conditionSchema: Record<
     string,
     {
@@ -41,7 +50,9 @@ const BusinessModel: BusinessModelType = {
   state: {
     institutionList: [],
     subjectList: [],
-    processMap: {},
+    executorMap: {},
+    conditionMap: {},
+    matterMap: {},
     conditionSchema: {},
     matterDetail: {}
   },
@@ -68,15 +79,39 @@ const BusinessModel: BusinessModelType = {
         })
       }
     },
+    *queryMatterDetail({ payload }, { call, put }) {
+      const response = yield call(queryMatterDetail, payload)
+      if (response?.code === consts.RET_CODE.SUCCESS) {
+        yield put({
+          type: 'save',
+          payload: {
+            matterDetail: response.data
+          }
+        })
+      }
+    },
+    *queryMatter({ payload }, { call, put }) {
+      const response = yield call(queryMatterTree, payload)
+      if (response?.code === consts.RET_CODE.SUCCESS) {
+        const { gatherID, businessType } = payload
+        yield put({
+          type: 'saveExecutorMap',
+          payload: {
+            ID: `${gatherID}_${businessType}`,
+            list: response.data.items
+          }
+        })
+      }
+    },
     *queryExecutor({ payload }, { call, put }) {
       const response = yield call(queryExecutorList, payload)
       if (response?.code === consts.RET_CODE.SUCCESS) {
         const { gatherID, businessType } = payload
         yield put({
-          type: 'saveProcessMap',
+          type: 'saveExecutorMap',
           payload: {
             ID: `${gatherID}_${businessType}`,
-            process: response.data.items
+            list: response.data.items
           }
         })
       }
@@ -99,15 +134,19 @@ const BusinessModel: BusinessModelType = {
         payload
       })
     },
-    *updateProcessMap({ payload }, { put }) {
+    *updateMatterMap({ payload }, { put }) {
       yield put({
-        type: 'saveProcessMap',
+        type: 'saveMatterMap',
+        payload
+      })
+    },
+    *updateExecutorMap({ payload }, { put }) {
+      yield put({
+        type: 'saveExecutorMap',
         payload
       })
     },
     *updateConditionMap({ payload }, { put }) {
-      console.log(payload)
-
       yield put({
         type: 'saveConditionMap',
         payload
@@ -121,14 +160,18 @@ const BusinessModel: BusinessModelType = {
         ...action.payload
       }
     },
+    saveMatterMap(state: BusinessModelState, action) {
+      const { ID, list } = action.payload as { ID: string; list: API.MatterItem[] }
+      return { ...state, matterMap: { ...state.matterMap, [ID]: list } }
+    },
     saveConditionMap(state: BusinessModelState, action) {
       return { ...state, conditionMap: { ...state.conditionMap, ...action.payload } }
     },
-    saveProcessMap(state: BusinessModelState, action) {
-      const { ID, process } = action.payload as { ID: string; process: API.ExecutorItem }
+    saveExecutorMap(state: BusinessModelState, action) {
+      const { ID, list } = action.payload as { ID: string; list: API.ExecutorItem }
       return {
         ...state,
-        processMap: { ...state.processMap, [ID]: process }
+        executorMap: { ...state.executorMap, [ID]: list }
       }
     },
     saveConditionMap(state, action) {