Преглед изворни кода

feat: 增加表格自定义筛选菜单

lanjianrong пре 5 година
родитељ
комит
b376abf4a1

+ 54 - 0
src/components/Table/src/components/FilterCascader.tsx

@@ -0,0 +1,54 @@
+import { Button, Tooltip } from 'antd'
+import type { FilterDropdownProps } from 'antd/lib/table/interface'
+import LazyCascader from '@/components/LazyCascader'
+
+const FilterCascader: React.FC<FilterDropdownProps> = ({
+  clearFilters,
+  setSelectedKeys,
+  confirm,
+  selectedKeys,
+  visible
+}) => {
+  const handleOnChange = v => {
+    setSelectedKeys(v)
+  }
+
+  const handleClearFilters = () => {
+    clearFilters()
+  }
+
+  return (
+    <div className="p-2">
+      {visible ? (
+        <>
+          <Tooltip title="双击省/市筛选">
+            <LazyCascader
+              value={selectedKeys}
+              onChange={handleOnChange}
+              allowClear={false}
+              changeOnSelect={true}
+              style={{ width: '220px' }}
+              showFooter={true}
+            />
+            <div className="flex justify-end items-center mt-2">
+              {/* <InfoCircleOutlined /> */}
+              <Button
+                type="link"
+                size="small"
+                onClick={() => handleClearFilters()}
+                disabled={!selectedKeys?.length}
+              >
+                重置
+              </Button>
+              <Button type="primary" size="small" onClick={() => confirm()}>
+                确定
+              </Button>
+            </div>
+          </Tooltip>
+        </>
+      ) : null}
+    </div>
+  )
+}
+
+export default FilterCascader

+ 43 - 0
src/components/Table/src/components/FilterDatePicker.tsx

@@ -0,0 +1,43 @@
+import { Button, DatePicker } from 'antd'
+import { useState } from 'react'
+import type { FilterDropdownProps } from 'antd/lib/table/interface'
+import dayjs from 'dayjs'
+
+const FilterDatePicker: React.FC<FilterDropdownProps> = ({
+  clearFilters,
+  setSelectedKeys,
+  confirm,
+  selectedKeys
+}) => {
+  const [date, setDate] = useState(selectedKeys.map(item => dayjs(item)))
+  const handleOnChange = (dates, dateStrings) => {
+    setDate(dates)
+    setSelectedKeys(dateStrings)
+  }
+
+  const handleClearFilters = () => {
+    setDate([])
+    clearFilters()
+  }
+
+  return (
+    <div className="p-2">
+      <DatePicker.RangePicker value={date} onChange={handleOnChange} allowClear={false} />
+      <div className="flex justify-end mt-2">
+        <Button
+          type="link"
+          size="small"
+          onClick={() => handleClearFilters()}
+          disabled={!selectedKeys?.length}
+        >
+          重置
+        </Button>
+        <Button type="primary" size="small" onClick={() => confirm()}>
+          确定
+        </Button>
+      </div>
+    </div>
+  )
+}
+
+export default FilterDatePicker

+ 20 - 18
src/pages/Customer/Client/index.jsx

@@ -5,7 +5,6 @@ import { Input, Button, message, Tooltip } from 'antd'
 import { connect, useModel } from 'umi'
 import React, { useEffect, useState, useRef, useMemo } from 'react'
 import consts from '@/consts'
-import LazyCascader from '@/components/LazyCascader'
 import { useModal } from '@/components/Modal'
 import { formatValues } from '@/components/LazyCascader'
 import PersonLabel from '../Company/components/PersonLabel'
@@ -18,10 +17,11 @@ 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 { refactorSortField } from '@/utils/utils'
+import { refactorFilterField, refactorSortField } from '@/utils/utils'
 import { PermDataTypeEunm } from '../Company/components/PermSelect'
 import BasicTable from '@/components/Table'
 import { getPermAuthCache } from '@/utils/auth'
+import FilterCascader from '@/components/Table/src/components/FilterCascader'
 
 const Client = props => {
   const { toggleDrawer, setDrawerProps } = useModal()
@@ -184,7 +184,7 @@ const Client = props => {
       title: '单位名称',
       dataIndex: 'companyName',
       key: 'companyName',
-      width: 150,
+      width: 100,
       ellipsis: true,
       render: (companyName, record) => (
         <span onClick={() => showDrawerComapny(record.companyId)} className={styles.textPurple}>
@@ -257,6 +257,7 @@ const Client = props => {
       width: 75,
       search: false,
       ellipsis: true,
+      filterDropdown: filterDropdownProps => <FilterCascader {...filterDropdownProps} />,
       renderText: text => text?.replaceAll(' / ', ' , ')
     },
     {
@@ -437,12 +438,12 @@ const Client = props => {
     setState({ ...state, params: { ...state.params, search: value } })
   }
 
-  const onDistrictChange = value => {
-    if (!value) return
-    tRef.current.reset()
-    const [province = '', city = '', area = ''] = value || []
-    setState({ ...state, params: { ...state.params, province, city, area } })
-  }
+  // const onDistrictChange = value => {
+  //   if (!value) return
+  //   tRef.current.reset()
+  //   const [province = '', city = '', area = ''] = value || []
+  //   setState({ ...state, params: { ...state.params, province, city, area } })
+  // }
 
   // 批量设置-确认触发
   const tagsSettingConfirm = async clientIds => {
@@ -545,10 +546,11 @@ const Client = props => {
         columns={columns}
         request={async (params, sort, filter) => {
           const srotOrder = refactorSortField(sort)
+          const nFilter = refactorFilterField(filter)
           const {
             code = -1,
             data: { client = [], total = 0 }
-          } = await queryClient({ ...params, ...srotOrder, ...filter })
+          } = await queryClient({ ...params, ...srotOrder, ...nFilter })
           setState({ ...state, orderIds: client.map(item => item.id) })
           return {
             data: client,
@@ -579,14 +581,14 @@ const Client = props => {
           ),
 
           actions: [
-            <LazyCascader
-              key="lazyCascader"
-              onChange={onDistrictChange}
-              changeOnSelect={true}
-              bordered={false}
-              showFooter={true}
-              className="hover:bg-[rgba(0,0,0,0.1)]"
-            />,
+            // <LazyCascader
+            //   key="lazyCascader"
+            //   onChange={onDistrictChange}
+            //   changeOnSelect={true}
+            //   bordered={false}
+            //   showFooter={true}
+            //   className="hover:bg-[rgba(0,0,0,0.1)]"
+            // />,
             <AddClient
               modalProps={{ zIndex: 1050 }}
               onConfirm={handleAddClient}

+ 19 - 17
src/pages/Customer/Company/index.jsx

@@ -3,7 +3,6 @@ import { Input, Button, message, Tooltip } from 'antd'
 import { connect, useModel } from 'umi'
 import consts from '@/consts'
 import { queryCompany, apiAddCompany } from '@/services/customer'
-import LazyCascader from '@/components/LazyCascader'
 import CompanyDetail from '@/pages/Customer/Company/components/CompanyDetail'
 import AddCompany from '@/pages/Customer/Company/components/AddCompany'
 import { useModal } from '@/components/Modal'
@@ -13,10 +12,11 @@ import { TagTypeEnum, TagDataTypeEnum, LabelModeType } from './components/Person
 import { Add, Down, Check } from '@icon-park/react'
 import { apiBatchLink } from '@/services/customer'
 import styles from './index.less'
-import { refactorSortField } from '@/utils/utils'
+import { refactorFilterField, refactorSortField } from '@/utils/utils'
 import { PermDataTypeEunm } from './components/PermSelect'
 import BasicTable from '@/components/Table'
 import { getPermAuthCache } from '@/utils/auth'
+import FilterCascader from '@/components/Table/src/components/FilterCascader'
 
 const Company = props => {
   const {
@@ -134,12 +134,12 @@ const Company = props => {
     tRef.current.reset()
     setState({ ...state, params: { ...state.params, search: value } })
   }
-  const onDistrictChange = value => {
-    if (!value) return
-    tRef.current.reset()
-    const [province = '', city = '', area = ''] = value
-    setState({ ...state, params: { ...state.params, province, city, area } })
-  }
+  // const onDistrictChange = value => {
+  //   if (!value) return
+  //   tRef.current.reset()
+  //   const [province = '', city = '', area = ''] = value
+  //   setState({ ...state, params: { ...state.params, province, city, area } })
+  // }
 
   // 展示drawer
   const showDrawer = id => {
@@ -180,6 +180,7 @@ const Company = props => {
       search: false,
       width: 100,
       ellipsis: true,
+      filterDropdown: filterDropdownProps => <FilterCascader {...filterDropdownProps} />,
       renderText: text => text?.replaceAll(' / ', ' , ')
     },
     {
@@ -470,8 +471,9 @@ const Company = props => {
         params={state.params}
         request={async (params, sort, filter) => {
           const srotOrder = refactorSortField(sort)
+          const nFilter = refactorFilterField(filter)
           const { code = -1, data: { customer = [], total = 0 } = { customer: [], total: 0 } } =
-            await queryCompany({ ...params, ...srotOrder, ...filter })
+            await queryCompany({ ...params, ...srotOrder, ...nFilter })
           setState({ ...state, orderIds: customer.map(item => item.id) })
           return {
             data: customer,
@@ -496,14 +498,14 @@ const Company = props => {
             </Tooltip>
           ),
           actions: [
-            <LazyCascader
-              onChange={onDistrictChange}
-              changeOnSelect={true}
-              key="lazyCascader"
-              showFooter={true}
-              className="hover:bg-[rgba(0,0,0,0.1)]"
-              bordered={false}
-            />,
+            // <LazyCascader
+            //   onChange={onDistrictChange}
+            //   changeOnSelect={true}
+            //   key="lazyCascader"
+            //   showFooter={true}
+            //   className="hover:bg-[rgba(0,0,0,0.1)]"
+            //   bordered={false}
+            // />,
             <AddCompany
               onConfirm={handleAddCompany}
               key="addCompanyBtn"

+ 29 - 27
src/pages/Product/Lock/Lockstore/index.jsx

@@ -1,5 +1,5 @@
 import React, { useEffect, useState, useRef } from 'react'
-import { Tag, Tooltip, Input, DatePicker, Button } from 'antd'
+import { Tag, Tooltip, Input, Button } from 'antd'
 import consts from '@/consts'
 import { useModel, connect } from 'umi'
 import { queryLock } from '@/services/product'
@@ -14,6 +14,7 @@ import ReceiveLock from './components/ReceiveLock'
 import { PermDataTypeEunm } from '@/pages/Customer/Company/components/PermSelect'
 import BasicTable from '@/components/Table'
 import { getPermAuthCache } from '@/utils/auth'
+import FilterDatePicker from '@/components/Table/src/components/FilterDatePicker'
 // import { DownOutlined } from '@ant-design/icons'
 
 // 渲染产品标签
@@ -233,6 +234,7 @@ const LockStore = ({ prodList = [], dispatch, shouldUpdate }) => {
       key: 'stockTime',
       valueType: 'date',
       filters: true,
+      filterDropdown: filterDropdownProps => <FilterDatePicker {...filterDropdownProps} />,
       sorter: true,
       width: 90
     },
@@ -255,13 +257,13 @@ const LockStore = ({ prodList = [], dispatch, shouldUpdate }) => {
         return <>{longleStockStatusNum[stockStatus]?.text}</>
       }
     },
-    {
-      title: '出库时间',
-      dataIndex: 'stockTime',
-      valueType: 'date',
-      key: 'stockTime',
-      width: 90
-    },
+    // {
+    //   title: '出库时间',
+    //   dataIndex: 'stockTime',
+    //   valueType: 'date',
+    //   key: 'stockTime',
+    //   width: 90
+    // },
     {
       title: '销售状态',
       dataIndex: 'sellStatus',
@@ -440,25 +442,25 @@ const LockStore = ({ prodList = [], dispatch, shouldUpdate }) => {
               onSearch={handleSearch}
             />
           </Tooltip>
-        ),
-        actions: [
-          <Tooltip title="产品出库时间" key="date">
-            <DatePicker.RangePicker
-              bordered={false}
-              onChange={time => {
-                const [time1, time2] = time || [null, null]
-                setState({
-                  ...state,
-                  params: {
-                    ...state.params,
-                    beginTime: time1 ? time1.format('YYYY-MM-DD') : null,
-                    endTime: time2 ? time2.format('YYYY-MM-DD') : null
-                  }
-                })
-              }}
-            />
-          </Tooltip>
-        ]
+        )
+        // actions: [
+        //   <Tooltip title="产品出库时间" key="date">
+        //     <DatePicker.RangePicker
+        //       bordered={false}
+        //       onChange={time => {
+        //         const [time1, time2] = time || [null, null]
+        //         setState({
+        //           ...state,
+        //           params: {
+        //             ...state.params,
+        //             beginTime: time1 ? time1.format('YYYY-MM-DD') : null,
+        //             endTime: time2 ? time2.format('YYYY-MM-DD') : null
+        //           }
+        //         })
+        //       }}
+        //     />
+        //   </Tooltip>
+        // ]
       }}
     />
   )

+ 16 - 3
src/utils/utils.js

@@ -35,7 +35,7 @@ export const dayjsFormat = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
 
 /** 处理表格排序字段 */
 export const refactorSortField = sort => {
-  if (!sort) return
+  if (!sort) return {}
   // 处理后的排序,格式{ field: 'xxxxx', order: 'desc/asc' }
   const s = { field: null, order: null }
   const keys = Object.keys(sort)
@@ -43,13 +43,26 @@ export const refactorSortField = sort => {
   if (orKey) {
     s.field = orKey
     s.order = sort[orKey].replace('end', '')
-    // eslint-disable-next-line consistent-return
     return s
   }
-  // eslint-disable-next-line consistent-return
   return {}
 }
 
+/** 处理表格中的筛选(特殊情况) */
+export const refactorFilterField = 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 = length =>
   Number(Math.random().toString().substr(3, length) + Date.now()).toString(36)