index.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { useSize } from "ahooks";
  2. import React, { useRef, useState, useEffect } from "react"
  3. import Table, { BaseTableProps, ColumnShape, SortOrder } from 'react-base-table'
  4. import 'react-base-table/styles.css'
  5. import './index.less'
  6. import { Empty, Pagination, Skeleton, Spin } from "antd";
  7. import { PaginationProps } from "antd/es/pagination";
  8. interface Props extends Omit<BaseTableProps, 'width'> {
  9. isPagination?: boolean,
  10. pagination?: PaginationProps
  11. width?: number
  12. loading?: boolean
  13. onChange?: (data: {
  14. pagination?: { current?: number, pageSize?: number, gzh?: string },
  15. sortData?: { column: ColumnShape<unknown>, field: React.Key, order: "ascend" | "descend" }
  16. }) => void
  17. }
  18. const BaseTable: React.FC<Props> = ({ isPagination = true, pagination, width, height, estimatedRowHeight, rowHeight, fixed, columns, loading, onChange, ...props }) => {
  19. /***************************************/
  20. const ref = useRef(null);
  21. const tableRef = useRef(null);
  22. const size = useSize(ref);
  23. const [operate, setOperate] = useState<{
  24. pagination?: { current?: number, pageSize?: number },
  25. sortData?: { column: ColumnShape<unknown>, key: React.Key, order: SortOrder }
  26. }>({})
  27. /***************************************/
  28. useEffect(() => {
  29. setOperate({ ...operate, pagination: { current: pagination?.current || 1, pageSize: pagination?.pageSize || pagination?.defaultPageSize || 20 } })
  30. }, [pagination?.current, pagination?.pageSize, pagination?.defaultPageSize])
  31. let tableProps: BaseTableProps = {
  32. fixed: fixed || true, // 是否开启 列的宽度是固定的还是灵活的
  33. width: width || size.width || 900, // 表固定宽度
  34. height: height || 700, // 表固定高度
  35. }
  36. if (estimatedRowHeight) {
  37. tableProps.estimatedRowHeight = estimatedRowHeight // 灵活高度
  38. tableProps.rowHeight = estimatedRowHeight() || rowHeight || 26
  39. if (props?.data?.length < 10) {
  40. tableProps.maxHeight = 700
  41. }
  42. } else {
  43. tableProps.rowHeight = rowHeight || 26 // 固定高度
  44. if (props?.data?.length < 20) {
  45. tableProps.maxHeight = 700
  46. }
  47. }
  48. if (props.frozenData?.length > 0 && tableProps.rowHeight && tableProps.height) {
  49. tableProps.height = tableProps.height + tableProps.rowHeight
  50. }
  51. if (tableProps.rowHeight && tableProps.rowHeight < 26) {
  52. tableProps.rowHeight = 26
  53. }
  54. if (columns) {
  55. let totalWidth = columns.reduce((pre: number, cur: { width: number; }) => {
  56. pre += cur.width
  57. return pre
  58. }, 0)
  59. if (totalWidth < tableProps.width) {
  60. let length = columns?.length || 1
  61. let diffW = (tableProps.width - totalWidth - 6) / length
  62. tableProps.fixed = false
  63. columns = columns.map((item: any) => {
  64. return { ...item, width: item.width + diffW }
  65. })
  66. }
  67. }
  68. if (!props?.data || props?.data?.length === 0) {
  69. delete tableProps.maxHeight
  70. tableProps.height = 200
  71. }
  72. tableProps.columns = columns
  73. tableProps = { ...tableProps, ...props }
  74. // 排序操作
  75. const onColumnSort = (sortBy: { column: ColumnShape<unknown>, key: React.Key, order: SortOrder }) => {
  76. const { key, order } = sortBy;
  77. let newOperate = JSON.parse(JSON.stringify(operate))
  78. const sortData = newOperate?.sortData
  79. if (sortData && sortData.key === key) {
  80. if (order === 'asc') {
  81. newOperate = { ...newOperate, sortData: undefined } // 取消排序
  82. } else {
  83. newOperate = { ...newOperate, sortData: sortBy }
  84. }
  85. } else {
  86. newOperate = { ...newOperate, sortData: sortBy }
  87. }
  88. setOperate(newOperate)
  89. onChange?.({ ...newOperate, sortData: newOperate?.sortData ? { ...newOperate.sortData, field: newOperate.sortData.key, order: newOperate.sortData.order === 'asc' ? 'ascend' : 'descend' } : undefined })
  90. }
  91. // const rowRenderer = ({ isScrolling, cells }: any) => {
  92. // if (isScrolling) return <Skeleton.Button active size="small" block />
  93. // return cells
  94. // }
  95. return <Spin spinning={loading}>
  96. <div ref={ref}>
  97. <Table
  98. ref={tableRef}
  99. overscanRowCount={3}
  100. emptyRenderer={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
  101. sortBy={operate?.sortData}
  102. onColumnSort={onColumnSort}
  103. // useIsScrolling
  104. // rowRenderer={rowRenderer}
  105. {...tableProps}
  106. />
  107. {isPagination && <div className="pagination">
  108. <Pagination
  109. onChange={(page: number, pageSize: number) => {
  110. setOperate({ ...operate, pagination: { current: page, pageSize } });
  111. onChange?.({ ...operate, pagination: { current: page, pageSize }, sortData: operate?.sortData ? { ...operate.sortData, field: operate.sortData.key, order: operate.sortData.order === 'asc' ? 'ascend' : 'descend' } : undefined });
  112. (tableRef.current as any)?.scrollToTop(0)
  113. }}
  114. {...pagination}
  115. />
  116. </div>}
  117. </div>
  118. </Spin>
  119. }
  120. export default React.memo(BaseTable)