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

feat: 引入react-windown优化单位详情列表

lanjianrong пре 4 година
родитељ
комит
70f42077b0

+ 2 - 0
package.json

@@ -54,6 +54,7 @@
     "@ant-design/pro-layout": "6.19.3",
     "@ant-design/pro-table": "2.43.4",
     "@icon-park/react": "^1.3.3",
+    "@types/react-window": "^1.8.5",
     "@umijs/route-utils": "^1.0.33",
     "ahooks": "^2.10.0",
     "antd": "4.16.12",
@@ -70,6 +71,7 @@
     "react-helmet-async": "^1.0.4",
     "react-infinite-scroll-component": "^6.1.0",
     "react-markdown": "^7.1.0",
+    "react-window": "^1.8.6",
     "umi": "3.5.4",
     "vditor": "^3.8.7"
   },

+ 105 - 0
src/components/Table/src/VirtualTable.tsx

@@ -0,0 +1,105 @@
+import React, { useState, useEffect, useRef } from 'react'
+import { VariableSizeGrid as Grid } from 'react-window'
+import ResizeObserver from 'rc-resize-observer'
+import classNames from 'classnames'
+import { Table } from 'antd'
+import type { TableProps } from 'antd'
+
+function VirtualTable<RecordType extends Record<string, unknown>>(props: TableProps<RecordType>) {
+  const { columns, scroll } = props
+  const [state, setState] = useState({
+    tableWidth: 0,
+    current: 1
+  })
+  const widthColumnCount = columns.filter(({ width }) => !width).length
+  const mergedColumns = columns.map(column => {
+    if (column.width) {
+      return column
+    }
+
+    return { ...column, width: Math.floor(state.tableWidth / widthColumnCount) }
+  })
+  const gridRef = useRef()
+  const [connectObject] = useState(() => {
+    const obj = {}
+    Object.defineProperty(obj, 'scrollLeft', {
+      get: () => null,
+      set: scrollLeft => {
+        if (gridRef.current) {
+          gridRef.current.scrollTo({
+            scrollLeft
+          })
+        }
+      }
+    })
+    return obj
+  })
+
+  const resetVirtualGrid = () => {
+    gridRef.current?.resetAfterIndices({
+      columnIndex: 0,
+      shouldForceUpdate: true
+    })
+  }
+
+  useEffect(() => resetVirtualGrid, [state.tableWidth])
+
+  const renderVirtualList = (rawData, { scrollbarSize, ref, onScroll }) => {
+    // eslint-disable-next-line no-param-reassign
+    ref.current = connectObject
+    const totalHeight = rawData.length * 54
+    return (
+      <Grid
+        ref={gridRef}
+        className="virtual-grid"
+        columnCount={mergedColumns.length}
+        columnWidth={index => {
+          const { width } = mergedColumns[index]
+          return totalHeight > scroll.y && index === mergedColumns.length - 1
+            ? width - scrollbarSize - 1
+            : width
+        }}
+        height={scroll.y}
+        rowCount={rawData.length}
+        rowHeight={() => 54}
+        width={state.tableWidth}
+        onScroll={({ scrollLeft }) => {
+          onScroll({
+            scrollLeft
+          })
+        }}
+      >
+        {({ columnIndex, rowIndex, style }) => (
+          <div
+            className={classNames('virtual-table-cell', {
+              'virtual-table-cell-last': columnIndex === mergedColumns.length - 1
+            })}
+            style={style}
+          >
+            {rawData[rowIndex][mergedColumns[columnIndex].dataIndex]}
+          </div>
+        )}
+      </Grid>
+    )
+  }
+
+  return (
+    <ResizeObserver
+      onResize={({ width }) => {
+        setState({ ...state, tableWidth: width })
+      }}
+    >
+      <Table
+        {...props}
+        className="virtual-table"
+        columns={mergedColumns}
+        pagination={false}
+        components={{
+          body: renderVirtualList
+        }}
+      />
+    </ResizeObserver>
+  )
+} // Usage
+
+export default VirtualTable

+ 2 - 5
src/pages/Customer/Company/components/CompanyDetail/SyncClient.jsx

@@ -1,8 +1,7 @@
 import consts from '@/consts'
 import { syncToClient } from '@/services/customer'
-import ProTable from '@ant-design/pro-table'
 import { Copy } from '@icon-park/react'
-import { Button, Checkbox, message, Modal } from 'antd'
+import { Button, Checkbox, message, Modal, Table } from 'antd'
 import { useState } from 'react'
 import { useDispatch } from 'umi'
 
@@ -142,10 +141,8 @@ const SyncClient = ({ customer, client }) => {
             </div>
           </Checkbox.Group>
         </div>
-        <ProTable
-          search={false}
+        <Table
           rowKey="id"
-          toolBarRender={false}
           size="small"
           columns={columns}
           dataSource={client}

+ 19 - 6
src/pages/Customer/Company/components/CompanyDetail/TabList.jsx

@@ -16,6 +16,7 @@ import { longleSellStatusNum, longlePreserveStatusNum } from '@/pages/Product/Lo
 import { renderBadge } from '@/pages/Workbench/Dashboard/components/RatioPanels'
 import { DownOutlined } from '@ant-design/icons'
 import { ProductLabel } from '@/pages/Product/Lock/LockStore/index'
+import VirtualTable from '@/components/Table/src/VirtualTable'
 
 const CompanyTabList = ({
   initData,
@@ -101,7 +102,8 @@ const CompanyTabList = ({
         if (key !== defaultSelectedKey) {
           changePriority(key, id)
         }
-      }}>
+      }}
+    >
       <Menu.Item key="1">1</Menu.Item>
       <Menu.Item key="2">2</Menu.Item>
       <Menu.Item key="3">3</Menu.Item>
@@ -120,7 +122,8 @@ const CompanyTabList = ({
         <Dropdown
           overlay={priorityMenu(text, record.id)}
           trigger="click"
-          className="hover:cursor-pointer">
+          className="hover:cursor-pointer"
+        >
           <span>
             {text} <DownOutlined />
           </span>
@@ -187,14 +190,16 @@ const CompanyTabList = ({
             <Text delete type="secondary">
               <span
                 onClick={() => showLongleDrawer(record.id)}
-                className="cursor-pointer hover:text-hex-967bbd">
+                className="cursor-pointer hover:text-hex-967bbd"
+              >
                 {clientName}
               </span>
             </Text>
           ) : (
             <span
               onClick={() => showLongleDrawer(record.id)}
-              className="text-primary cursor-pointer hover:text-hex-967bbd">
+              className="text-primary cursor-pointer hover:text-hex-967bbd"
+            >
               {clientName}
             </span>
           )}
@@ -279,7 +284,8 @@ const CompanyTabList = ({
       render: (text, record) => (
         <span
           onClick={() => showDrawerBusiness(record.id)}
-          className="text-primary cursor-pointer hover:text-[#967bbd]">
+          className="text-primary cursor-pointer hover:text-[#967bbd]"
+        >
           {text}
         </span>
       )
@@ -346,7 +352,7 @@ const CompanyTabList = ({
         <Tabs>
           <TabPane tab={<span>客户{renderBadge(client.total, true)}</span>} key="1">
             <div className="sheet-right-panel" ref={tRef}>
-              <ProTable
+              {/* <ProTable
                 size="small"
                 columns={columns}
                 search={false}
@@ -354,6 +360,13 @@ const CompanyTabList = ({
                 toolBarRender={false}
                 rowKey={record => record.id}
                 pagination={false}
+              /> */}
+              <VirtualTable
+                size="small"
+                columns={columns}
+                search={false}
+                dataSource={client.client}
+                rowKey={record => record.id}
               />
             </div>
           </TabPane>

+ 0 - 54
src/pages/Customer/Test/index.jsx

@@ -1,54 +0,0 @@
-// import * as echarts from 'echarts/core'
-// import { useEffect } from 'react'
-// // 引入柱状图图表,图表后缀都为 Chart
-// import { BarChart } from 'echarts/charts'
-// // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
-// import {
-//   TitleComponent,
-//   TooltipComponent,
-//   GridComponent,
-//   DatasetComponent,
-//   DatasetComponentOption,
-//   TransformComponent
-// } from 'echarts/components'
-// // 标签自动布局,全局过渡动画等特性
-// import { LabelLayout, UniversalTransition } from 'echarts/features'
-// // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
-// import { CanvasRenderer } from 'echarts/renderers'
-
-// // 注册必须的组件
-// echarts.use([
-//   TitleComponent,
-//   TooltipComponent,
-//   GridComponent,
-//   DatasetComponent,
-//   TransformComponent,
-//   BarChart,
-//   LabelLayout,
-//   UniversalTransition,
-//   CanvasRenderer
-// ])
-
-// export default function Index() {
-//   useEffect(() => {
-//     const myChart = echarts.init(document.getElementById('mian11'))
-//     myChart.setOption({
-//       title: {
-//         text: 'ECharts 入门示例'
-//       },
-//       tooltip: {},
-//       xAxis: {
-//         data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
-//       },
-//       yAxis: {},
-//       series: [
-//         {
-//           name: '销量',
-//           type: 'bar',
-//           data: [5, 20, 36, 10, 10, 20]
-//         }
-//       ]
-//     })
-//   }, [])
-//   return <div id="mian11" style={{ width: '300px', height: '500px' }} />
-// }