Jelajahi Sumber

feat: 增加useFlipOver hook处理抽屉内的上下翻页

lanjianrong 5 tahun lalu
induk
melakukan
1a2f5237d4

+ 48 - 0
src/hooks/web/useFlipOver.ts

@@ -0,0 +1,48 @@
+import { useCallback } from 'react'
+import { useEffect } from 'react'
+import { useState, useMemo } from 'react'
+
+export const FlipOverEnum = {
+  UP: 'up',
+  DOWN: 'down'
+}
+
+/**
+ * @description 用于处理抽屉/弹窗详情中左上角的上下翻页
+ */
+export function useFlipOver(
+  fn: (id: string) => Promise<void>,
+  targetId: string,
+  targetIds: string[] = []
+) {
+  const [curId, setCurId] = useState('')
+  useEffect(() => {
+    setCurId(targetId)
+  }, [targetId])
+  const flipConsts = useMemo(() => {
+    // eslint-disable-next-line react-hooks/rules-of-hooks
+    const curIndex = targetIds.findIndex(item => item === curId)
+
+    if (curIndex !== -1) {
+      const disableUpBtn = curIndex === 0
+      const disableDownBtn = curIndex === targetIds.length - 1
+      const prevId = targetIds[curIndex - 1]
+      const nextId = targetIds[curIndex + 1]
+      return { disableUpBtn, disableDownBtn, prevId, nextId, curId }
+    }
+    return { disableUpBtn: true, disableDownBtn: true, prevId: '', nextId: '', curId }
+  }, [curId, targetIds])
+
+  const flipFn = async (type: 'up' | 'down') => {
+    if (type === FlipOverEnum.UP && !flipConsts.disableUpBtn) {
+      await fn(flipConsts.prevId)
+      setCurId(flipConsts.prevId)
+    }
+    if (type === FlipOverEnum.DOWN && !flipConsts.disableDownBtn) {
+      await fn(flipConsts.nextId)
+      setCurId(flipConsts.nextId)
+    }
+  }
+
+  return { flipFn, flipConsts }
+}

+ 37 - 13
src/pages/Customer/Company/components/CompanyDetail/index.jsx

@@ -1,14 +1,16 @@
-import React, { useState, useEffect } from 'react'
-import { Row, Col, Spin } from 'antd'
+import React, { useState, useEffect, useMemo } from 'react'
+import { Row, Col, Spin, Tooltip } from 'antd'
 import consts from '@/consts'
 import { apiCompanyDetail } from '@/services/company'
 import CompanyForm from '@/pages/customer/Company/components/CompanyDetail/CompanyForm'
 import CompanyLowerList from '@/pages/customer/Company/components/CompanyDetail/CompanyLowerList'
 import CompanyTabList from '@/pages/customer/Company/components/CompanyDetail/CompanyTabList'
 import { connect } from 'dva'
+import { IconPark } from '@/components/SvgIcon'
+import { FlipOverEnum, useFlipOver } from '@/hooks/web/useFlipOver'
 
 const Index = props => {
-  const { dispatch, shouldUpdate, visible, id = '' } = props
+  const { dispatch, shouldUpdate, visible, id = '', orderIds = [] } = props
   const [state, setState] = useState({
     loading: false,
     customer: {},
@@ -16,12 +18,12 @@ const Index = props => {
     software: {},
     client: {}
   })
-  const initData = async () => {
+  const initData = async dataId => {
     setState({ ...state, loading: true })
     const {
       data: { customer = {}, log = [], software = {}, client = {} },
       code = -1
-    } = await apiCompanyDetail(id)
+    } = await apiCompanyDetail(dataId)
     if (code === consts.RET_CODE.SUCCESS) {
       if (shouldUpdate) {
         dispatch({
@@ -32,21 +34,43 @@ const Index = props => {
       setState({ ...state, customer, log, software, loading: false, client })
     }
   }
+  const { flipFn, flipConsts } = useFlipOver(initData, id, orderIds)
   useEffect(() => {
-    if (shouldUpdate) {
-      initData()
-    }
+    shouldUpdate && initData(id)
   }, [shouldUpdate])
   useEffect(() => {
-    if (visible) {
-      initData()
-    }
+    visible && initData(id)
   }, [visible])
   return (
     <Spin spinning={state.loading}>
       <div className="sheet-box">
         <Row>
-          <Col span={12} className="sheet-box-left">
+          <Col span={12} className="sheet-box-left text-gray-400">
+            <div className="mb-3">
+              <Tooltip title="上一条记录">
+                <IconPark
+                  type="up"
+                  fill={flipConsts.disableUpBtn ? '#BDBDBE' : '#886ab5'}
+                  size="20"
+                  onClick={() => flipFn(FlipOverEnum.UP)}
+                  className={[
+                    flipConsts.disableUpBtn ? 'cursor-not-allowed' : 'cursor-pointer'
+                  ].join(' ')}
+                />
+              </Tooltip>
+              <Tooltip title="下一条记录">
+                <IconPark
+                  type="down"
+                  fill={flipConsts.disableDownBtn ? '#BDBDBE' : '#886ab5'}
+                  size="20"
+                  onClick={() => flipFn(FlipOverEnum.DOWN)}
+                  className={[
+                    flipConsts.disableDownBtn ? 'cursor-not-allowed' : 'cursor-pointer',
+                    'ml-1'
+                  ].join(' ')}
+                />
+              </Tooltip>
+            </div>
             <div className="sheet-left-panel zh-pd-right-15">
               <CompanyForm customer={state.customer} />
             </div>
@@ -54,7 +78,7 @@ const Index = props => {
           <Col span={12} flex={{ flexDirection: 'column' }} className="sheet-box-right">
             <CompanyTabList
               initData={initData}
-              customerId={id}
+              customerId={flipConsts.curId}
               software={state.software}
               client={state.client}
             />

+ 4 - 2
src/pages/Customer/Company/index.jsx

@@ -67,7 +67,8 @@ const Company = props => {
   const [state, setState] = useState({
     id: '',
     params: {},
-    visible: false
+    visible: false,
+    orderIds: []
   })
   const [addCompany, setAddCompany] = useState({
     visible: false,
@@ -136,7 +137,7 @@ const Company = props => {
         height: '100vh',
         overflowY: 'hidden'
       },
-      children: <CompanyDetail id={id} />
+      children: <CompanyDetail id={id} orderIds={state.orderIds} />
     })
     toggleDrawer()
   }
@@ -428,6 +429,7 @@ const Company = props => {
           code = -1,
           data: { customer = [], total = 0 } = { customer: [], total: 0 }
         } = await queryCompany({ ...params, ...sort, ...filter })
+        setState({ ...state, orderIds: customer.map(item => item.id) })
         return {
           data: customer,
           success: code === consts.RET_CODE.SUCCESS,

+ 36 - 10
src/pages/Customer/Contact/components/ContactDetail/index.jsx

@@ -1,4 +1,4 @@
-import { Row, Col, Spin } from 'antd'
+import { Row, Col, Spin, Tooltip } from 'antd'
 import React, { useState, useEffect } from 'react'
 import ContanctForm from '@/pages/customer/Contact/components/ContactDetail/ContanctForm.jsx'
 import ContanctTabList from '@/pages/customer/Contact/components/ContactDetail/ContanctTabList.jsx'
@@ -6,9 +6,11 @@ import ContanctLowerList from '@/pages/customer/Contact/components/ContactDetail
 import { apiContactDetail } from '@/services/contact'
 import consts from '@/consts'
 import { connect } from 'dva'
+import { IconPark } from '@/components/SvgIcon'
+import { FlipOverEnum, useFlipOver } from '@/hooks/web/useFlipOver'
 
 const ContactDetail = props => {
-  const { dispatch, shouldUpdate, visible, dataId = '' } = props
+  const { dispatch, shouldUpdate, visible, dataId = '', orderIds = [] } = props
 
   const [state, setState] = useState({
     loading: false,
@@ -18,12 +20,12 @@ const ContactDetail = props => {
     software: {}
   })
 
-  const initData = async () => {
+  const initData = async id => {
     setState({ ...state, loading: true })
     const {
       data: { client = {}, log = [], serviceLog = [], software = {} },
       code = -1
-    } = await apiContactDetail(dataId)
+    } = await apiContactDetail(id)
     if (code === consts.RET_CODE.SUCCESS) {
       if (shouldUpdate) {
         dispatch({
@@ -34,16 +36,15 @@ const ContactDetail = props => {
       setState({ ...state, client, log, serviceLog, software, loading: false })
     }
   }
+
+  const { flipFn, flipConsts } = useFlipOver(initData, dataId, orderIds)
+
   useEffect(() => {
-    if (shouldUpdate) {
-      initData()
-    }
+    shouldUpdate && initData(dataId)
   }, [shouldUpdate])
 
   useEffect(() => {
-    if (visible) {
-      initData()
-    }
+    visible && initData(dataId)
   }, [visible])
 
   return (
@@ -51,6 +52,31 @@ const ContactDetail = props => {
       <div className="sheet-box">
         <Row>
           <Col span={12} className="sheet-box-left">
+            <div className="mb-3">
+              <Tooltip title="上一条记录">
+                <IconPark
+                  type="up"
+                  fill={flipConsts.disableUpBtn ? '#BDBDBE' : '#886ab5'}
+                  size="20"
+                  onClick={() => flipFn(FlipOverEnum.UP)}
+                  className={[
+                    flipConsts.disableUpBtn ? 'cursor-not-allowed' : 'cursor-pointer'
+                  ].join(' ')}
+                />
+              </Tooltip>
+              <Tooltip title="下一条记录">
+                <IconPark
+                  type="down"
+                  fill={flipConsts.disableDownBtn ? '#BDBDBE' : '#886ab5'}
+                  size="20"
+                  onClick={() => flipFn(FlipOverEnum.DOWN)}
+                  className={[
+                    flipConsts.disableDownBtn ? 'cursor-not-allowed' : 'cursor-pointer',
+                    'ml-1'
+                  ].join(' ')}
+                />
+              </Tooltip>
+            </div>
             <div className="sheet-left-panel zh-pd-right-15">
               <ContanctForm client={state.client} />
             </div>

+ 4 - 2
src/pages/Customer/Contact/index.jsx

@@ -77,7 +77,8 @@ const Contact = props => {
 
   const [state, setState] = useState({
     params: {},
-    id: ''
+    id: '',
+    orderIds: []
   })
 
   // 重置到默认值,包括表单
@@ -108,7 +109,7 @@ const Contact = props => {
         height: '100vh',
         overflowY: 'hidden'
       },
-      children: <ContactDetail dataId={id} />
+      children: <ContactDetail dataId={id} orderIds={state.orderIds} />
     })
     toggleDrawer()
   }
@@ -532,6 +533,7 @@ const Contact = props => {
             code = -1,
             data: { client = [], total = 0 }
           } = await queryContact({ ...params, ...sort, ...filter })
+          setState({ ...state, orderIds: client.map(item => item.id) })
           return {
             data: client,
             success: code === consts.RET_CODE.SUCCESS,