Bläddra i källkod

feat: 将构建特殊格式的排序、筛选字段的逻辑内置于BasicTable

lanjianrong 4 år sedan
förälder
incheckning
5b072e1fa8

+ 43 - 38
src/components/Table/src/BasicTable.tsx

@@ -1,20 +1,22 @@
 /* eslint-disable react-hooks/rules-of-hooks */
 /* eslint-disable no-param-reassign */
-import React, { useRef, useState, useMemo } from 'react'
+import ProTable from '@ant-design/pro-table'
 import PermSelect from '@/pages/Customer/Company/components/PermSelect'
+import { useRef, useState, useMemo } from 'react'
 import { TABLE_COLUMNS_MAP, ColumnStateEnum } from '@/utils/cache/cacheEnum'
 import { isBoolean, isMobile, isNullOrUnDef, isObject, isUnDef } from '@/utils/is'
-import ProTable from '@ant-design/pro-table'
 import { useModel } from '@umijs/max'
 import { getAuthCache, getPermAuthCache, setAuthCache } from '@/utils/auth'
 import { useTableScroll } from './hooks/useTableScroll'
+import { useMemoizedFn, useUpdateLayoutEffect } from 'ahooks'
+import transformRequestParams from './share'
+
 import type { ColumnsState } from '@ant-design/pro-table'
 import type { BasicTableProps, PermStateEnum } from '@/types/typing'
 import type { ParamsType } from '@ant-design/pro-provider'
 import type { DensitySize } from '@ant-design/pro-table/lib/components/ToolBar/DensityIcon'
 
 import styles from './index.less'
-import { useMemoizedFn, useUpdateLayoutEffect } from 'ahooks'
 
 const BasicTable: {
   <T extends Record<string, any>, U extends ParamsType = ParamsType, ValueType = 'text'>(
@@ -36,6 +38,7 @@ const BasicTable: {
   bordered,
   rowSelection,
   onLoad,
+  onRequestError,
   revalidateOnFocus = false,
   ...resetProps
 }) => {
@@ -79,7 +82,7 @@ const BasicTable: {
   })
 
   useUpdateLayoutEffect(() => {
-      state.dataSource && redoHeight(state.dataSource)
+    state.dataSource && redoHeight(state.dataSource)
   }, [state.dataSource])
 
   /** 增加头部 */
@@ -143,18 +146,21 @@ const BasicTable: {
 
   const computedParams = mainMenuType ? { ...params, ...state.params } : params
 
-  const _request = useMemoizedFn(
-    async (_params, _sort, _filter) => {
-      if (isUnDef(request)) return undefined
-      const result = await request(_params, _sort, _filter)
-      if (!isBoolean(result?.success)) {
-        result.success = true
-      } else if (!result?.success) result.success = true
-      if (!Array.isArray(result?.data)) result.data = []
-      return result
-    },
-    [request]
-  )
+  const _request = useMemoizedFn(async (_params, _sort, _filter) => {
+    if (isUnDef(request)) return undefined
+    const result = await request(transformRequestParams(_params, _sort, _filter))
+    if (!isBoolean(result?.success)) {
+      result.success = true
+    } else if (!result?.success) result.success = true
+    if (!Array.isArray(result?.data)) result.data = []
+    return result
+  })
+
+  // TODO: 让redoHeight逻辑执行需要一次set
+  const _onRequestError = useMemoizedFn((e: Error) => {
+    onRequestError?.(e)
+    setState({ ...state, dataSource: [] })
+  })
 
   const _onLoad = useMemoizedFn(_dataSource => {
     onLoad?.(_dataSource)
@@ -166,30 +172,29 @@ const BasicTable: {
     if (Reflect.has(resetProps, 'dataSource')) {
       setState({ ...state, dataSource: resetProps.dataSource })
     }
-  })
+  }, [])
 
   return (
-    <React.StrictMode>
-      <div ref={tableElRef} className={styles.BasicTable}>
-        <ProTable
-          {...resetProps}
-          rowKey={rowKey || 'id'}
-          columns={originalColumns}
-          params={computedParams}
-          scroll={getScrollRef}
-          request={_request}
-          columnsState={{
-            defaultValue: state.columnsStateMap,
-            onChange: handleOnColumnsChange
-          }}
-          bordered={isNullOrUnDef(bordered) ? bordered : true}
-          onLoad={_onLoad}
-          onSizeChange={handleOnSizeChange}
-          rowSelection={rowSelectionOptions}
-          revalidateOnFocus={revalidateOnFocus}
-        />
-      </div>
-    </React.StrictMode>
+    <div ref={tableElRef} className={styles.BasicTable}>
+      <ProTable
+        {...resetProps}
+        rowKey={rowKey || 'id'}
+        columns={originalColumns}
+        params={computedParams}
+        scroll={getScrollRef}
+        request={_request}
+        columnsState={{
+          defaultValue: state.columnsStateMap,
+          onChange: handleOnColumnsChange
+        }}
+        bordered={isNullOrUnDef(bordered) ? bordered : true}
+        onLoad={_onLoad}
+        onSizeChange={handleOnSizeChange}
+        onRequestError={_onRequestError}
+        rowSelection={rowSelectionOptions}
+        revalidateOnFocus={revalidateOnFocus}
+      />
+    </div>
   )
 }
 

+ 2 - 6
src/components/Table/src/hooks/useTableScroll.ts

@@ -2,7 +2,7 @@
 import type { ProColumns } from '@ant-design/pro-table'
 import type { RefObject } from 'react'
 import { useState, useMemo, useTransition } from 'react'
-import { useDebounceFn, useUpdateEffect, useUpdateLayoutEffect } from 'ahooks'
+import { useUpdateLayoutEffect } from 'ahooks'
 import { getViewportOffset } from '@/utils/domUtils'
 import { useWindowSizeFn } from '@/hooks/event/useWindomSizeFn'
 import type { DensitySize } from '@ant-design/pro-table/lib/components/ToolBar/DensityIcon'
@@ -23,7 +23,6 @@ export function useTableScroll({
   const [, startTransition] = useTransition()
   const [_dataSource, setDataSource] = useState(null)
   function calcTableHeight(dataSource: any[]) {
-
     const tableEl = tableElRef.current?.querySelector('.ant-table-wrapper')
     if (!tableEl) return
 
@@ -76,18 +75,16 @@ export function useTableScroll({
     }
     const height = bottomIncludeBody - paddingHeight - paginationHeight - headerHeight
 
-    // setTableHeight(dataSource?.length ? height : null)
-
     if (!dataSource?.length) {
       // TODO:针对无数据的情况下,特别设置tboody
       tableContainerEl!.style.marginBottom = '16px'
+      tableContainerEl!.style.paddingBottom = '16px'
       const tbodyEl: HTMLElement = tableContainerEl?.querySelector('tbody.ant-table-tbody')
       const el = tableContainerEl?.querySelector('table')
       let hasScrollBar = el?.style.width !== '100%'
 
       if (el?.style.width !== '100%') {
         const contentWidth = tableContainerEl?.querySelector('div.ant-table-content')?.clientWidth || 0
-
         hasScrollBar = el?.clientWidth > contentWidth
       }
 
@@ -109,7 +106,6 @@ export function useTableScroll({
       calcTableHeight(dataSource || _dataSource)
     })
   }
-  // const { run: debounceRedoHeight } = useDebounceFn(redoHeight, { wait: 80 })
 
   // Greater than animation time 80
   useWindowSizeFn(() => redoHeight(), 80)

+ 40 - 0
src/components/Table/src/share.ts

@@ -0,0 +1,40 @@
+/** 处理表格排序字段 */
+export const transformSort = (sort?: { field: string; order: string }) => {
+  if (!sort) return {}
+  // 处理后的排序,格式{ field: 'xxxxx', order: 'desc/asc' }
+  const s = { field: null, order: null }
+  const keys = Object.keys(sort)
+  const val = keys[0]
+  if (val) {
+    s.field = val
+    s.order = sort[val].replace('end', '')
+    return s
+  }
+  return {}
+}
+
+/** 处理表格中的筛选(特殊情况) */
+export const transformFilter = (filter?: Recordable<string>) => {
+  if (!filter) return {}
+  const keys = Object.keys(filter)
+  const nFiter = { ...filter }
+  // 业务定制
+  const district = keys.find(item => item.startsWith('district'))
+  if (district?.length) {
+    const [province = null, city = null, area = null] = filter[district] || []
+    nFiter.province = province
+    nFiter.city = city
+    nFiter.area = area
+    delete nFiter[district]
+  }
+  return nFiter
+}
+
+const transformRequestParams = (params, sort, filter) => {
+  return {
+    ...params,
+    ...transformSort(sort),
+    ...transformFilter(filter)
+  }
+}
+export default transformRequestParams

+ 1 - 4
src/pages/Customer/Client/index.tsx

@@ -9,7 +9,6 @@ import { Add, Down, Check } from '@icon-park/react'
 import { apiAddClient, queryClient } from '@/services/customer'
 import { apiBatchLink } from '@/services/customer'
 import styles from './index.less'
-import { generateFilterField, generateSortField } from '@/utils/utils'
 import { PermDataTypeEunm } from '../Company/components/PermSelect'
 import BasicTable from '@/components/Table'
 import { getPermAuthCache } from '@/utils/auth'
@@ -547,12 +546,10 @@ const Client = props => {
           rowKey={record => record.id}
           columns={columns}
           request={async (params, sort, filter) => {
-            const srotOrder = generateSortField(sort)
-            const nFilter = generateFilterField(filter)
             const {
               code = -1,
               data: { client = [], total = 0 }
-            } = await queryClient({ ...params, ...srotOrder, ...nFilter })
+            } = await queryClient({ ...params, ...sort, ...filter })
             setState({ ...state, orderIds: client.map(item => item.id) })
             return {
               data: client,

+ 2 - 5
src/pages/Customer/Company/index.tsx

@@ -8,7 +8,6 @@ import PersonLabel from './components/PersonLabel'
 import { TagType, TagDataType, LabelModeType } from './components/PersonLabel/const'
 import { Add, Down, Check, Plus } from '@icon-park/react'
 import { apiBatchLink } from '@/services/customer'
-import { generateFilterField, generateSortField } from '@/utils/utils'
 import { PermDataTypeEunm } from './components/PermSelect'
 import BasicTable from '@/components/Table'
 import { getPermAuthCache } from '@/utils/auth'
@@ -470,13 +469,11 @@ const Company = props => {
           columnStateType="COMPANY"
           params={state.params}
           request={async (params, sort, filter) => {
-            const srotOrder = generateSortField(sort)
-            const nFilter = generateFilterField(filter)
             const { code = -1, data: { customer = [], total = 0 } = { customer: [], total: 0 } } =
               await queryCompany({
                 ...params,
-                ...srotOrder,
-                ...nFilter
+                ...sort,
+                ...filter
               })
             setState({ ...state, orderIds: customer.map(item => item.id) })
             return {

+ 1 - 2
src/pages/Product/Lock/LockStore/index.jsx

@@ -282,7 +282,6 @@ const LockStore = ({ prodList = [], dispatch, shouldUpdate }) => {
         params={state.params}
         columns={columns}
         request={async (params, sort, filter) => {
-          const srotOrder = generateSortField(sort)
           const {
             code = -1,
             data: { longle = [], total = 0, totalOld = 0, totalNew = 0 } = {
@@ -291,7 +290,7 @@ const LockStore = ({ prodList = [], dispatch, shouldUpdate }) => {
               totalOld: 0,
               totalNew: 0
             }
-          } = await queryLock({ ...params, ...srotOrder, ...filter })
+          } = await queryLock({ ...params, ...sort, ...filter })
           setState({ ...state, totalOld, totalNew, orderIds: longle.map(item => item.id) })
           return {
             data: longle,

+ 1 - 2
src/pages/Product/Road/Enterprise/index.jsx

@@ -133,11 +133,10 @@ const Enterprise = ({ compilationv2, shouldUpdate }) => {
         columns={columns}
         params={state.params}
         request={async (params, sort, filter) => {
-          const sortOrder = generateSortField(sort)
           const {
             code = -1,
             data: { list = [], total = 0 }
-          } = await queryRoadcompanyList({ ...params, ...sortOrder, ...filter })
+          } = await queryRoadcompanyList({ ...params, ...sort, ...filter })
           return {
             data: list,
             success: code === consts.RET_CODE.SUCCESS,

+ 1 - 2
src/pages/Product/Road/Personal/index.jsx

@@ -206,11 +206,10 @@ const Personal = props => {
         columns={columns}
         params={state.params}
         request={async (params, sort, filter) => {
-          const sortOrder = generateSortField(sort)
           const {
             code = -1,
             data: { list = [], total = 0 }
-          } = await queryRoadpricingListV2({ ...params, ...sortOrder, ...filter })
+          } = await queryRoadpricingListV2({ ...params, ...sort, ...filter })
           return {
             data: list,
             success: code === consts.RET_CODE.SUCCESS,

+ 0 - 31
src/utils/utils.js

@@ -9,37 +9,6 @@ export const dayjsFormat = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
   return dayjs(date).format(format)
 }
 
-/** 处理表格排序字段 */
-export const generateSortField = sort => {
-  if (!sort) return {}
-  // 处理后的排序,格式{ field: 'xxxxx', order: 'desc/asc' }
-  const s = { field: null, order: null }
-  const keys = Object.keys(sort)
-  const orKey = keys[0]
-  if (orKey) {
-    s.field = orKey
-    s.order = sort[orKey].replace('end', '')
-    return s
-  }
-  return {}
-}
-
-/** 处理表格中的筛选(特殊情况) */
-export const generateFilterField = filter => {
-  if (!filter) return {}
-  const keys = Object.keys(filter)
-  const nFiter = { ...filter }
-  const district = keys.find(item => item.startsWith('district'))
-  if (district?.length) {
-    const [province = null, city = null, area = null] = filter[district] || []
-    nFiter.province = province
-    nFiter.city = city
-    nFiter.area = area
-    delete nFiter[district]
-  }
-  return nFiter
-}
-
 // 可控长度的随机数拼接时间戳成产唯一id
 export const createUid = () => URL.createObjectURL(new Blob()).substr(-36)
 // Number(Math.random().toString().substr(3, length) + Date.now()).toString(36)