useAutoTable.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { useState, useEffect, useMemo, useLayoutEffect, useRef } from 'react'
  2. import { useDebounceFn, useMount, useUpdateLayoutEffect } from 'ahooks'
  3. import { useStore } from 'dva'
  4. import { getViewportOffset } from '@/utils/domUtils'
  5. import { useWindowSizeFn } from './event/useWindomSizeFn'
  6. /**
  7. * @param {number} needSubtractHeight 被裁去的高度
  8. * @param {number} needSubtractWidth 被裁去的宽度
  9. */
  10. const useAutoTable = (needSubtractHeight, needSubtractWidth) => {
  11. const { collapsed = true } = useStore().getState().global
  12. const [scroll, setScroll] = useState({
  13. x: document.body.clientWidth - ((collapsed ? 208 : 48) + needSubtractWidth),
  14. y: document.body.clientHeight - needSubtractHeight
  15. })
  16. // const { run, cancel } = useDebounceFn(handleScroll, { wait: 5000})
  17. const { run, cancel } = useDebounceFn(() =>
  18. setScroll({
  19. ...scroll,
  20. x: document.body.clientWidth - ((collapsed ? 208 : 48) + needSubtractWidth),
  21. y: document.body.clientHeight - needSubtractHeight
  22. })
  23. )
  24. useEffect(() => {
  25. run()
  26. return () => cancel()
  27. }, [collapsed])
  28. useEffect(() => {
  29. window.addEventListener('resize', run)
  30. return () => {
  31. window.removeEventListener('resize', cancel)
  32. }
  33. }, [])
  34. // 实际返回的宽度要大一点让table出现滚动条,反正折叠菜单栏卡顿
  35. return [scroll.x + 50, scroll.y]
  36. }
  37. export default useAutoTable
  38. export function useTableScroll(columnsRef, selectKeysRef) {
  39. let paginationEl = null
  40. let footerEl = null
  41. let bodyEl = null
  42. const [tableHeight, setTableHeight] = useState(null)
  43. async function calcTableHeight() {
  44. const tableEl = document.getElementsByClassName('ant-table-wrapper')[0]
  45. if (!tableEl) return
  46. if (!bodyEl) {
  47. bodyEl = tableEl.querySelector('.ant-table-body')
  48. bodyEl && (bodyEl.style.height = 'unset')
  49. }
  50. // Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
  51. const headEl = tableEl.querySelector('.ant-table-thead ')
  52. if (!headEl) return
  53. // Table height from bottom
  54. const { bottomIncludeBody } = getViewportOffset(headEl)
  55. const paddingHeight = 64
  56. let paginationHeight = 2
  57. if (!paginationEl) {
  58. paginationEl = tableEl.querySelector('.ant-pagination')
  59. if (paginationEl) {
  60. const { offsetHeight } = paginationEl
  61. paginationHeight += offsetHeight || 0
  62. } else {
  63. // TODO First fix 24
  64. paginationHeight += 24
  65. }
  66. } else {
  67. paginationHeight = -8
  68. }
  69. let footerHeight = 0
  70. if (!paginationEl) {
  71. if (!footerEl) {
  72. footerEl = tableEl.querySelector('.ant-table-footer')
  73. } else {
  74. const { offsetHeight } = footerEl
  75. footerHeight += offsetHeight || 0
  76. }
  77. }
  78. let headerHeight = 0
  79. if (headEl) {
  80. headerHeight = headEl.offsetHeight
  81. }
  82. const height =
  83. bottomIncludeBody - paddingHeight - paginationHeight - footerHeight - headerHeight
  84. setTableHeight(height)
  85. bodyEl && (bodyEl.style.height = `${height}px`)
  86. }
  87. function redoHeight() {
  88. calcTableHeight()
  89. }
  90. const { run: debounceRedoHeight } = useDebounceFn(redoHeight, { wait: 280 })
  91. // Greater than animation time 280
  92. useWindowSizeFn(calcTableHeight, 280)
  93. useMount(() => {
  94. debounceRedoHeight()
  95. })
  96. useUpdateLayoutEffect(() => {
  97. debounceRedoHeight()
  98. }, [selectKeysRef.length])
  99. const getSrollX = useMemo(() => {
  100. let width = 0
  101. if (selectKeysRef.length) {
  102. width += 60
  103. }
  104. // TODO props ?? 0;
  105. const NORMAL_WIDTH = 150
  106. const columns = columnsRef.filter(item => !item.defaultHidden)
  107. columns.forEach(item => {
  108. width += Number.parseInt(item.width) || 0
  109. })
  110. const unsetWidthColumns = columns.filter(item => !Reflect.has(item, 'width'))
  111. const len = unsetWidthColumns.length
  112. if (len !== 0) {
  113. width += len * NORMAL_WIDTH
  114. }
  115. const tableEl = document.getElementsByClassName('ant-pro-table')[0]
  116. const tableWidth = tableEl && tableEl.offsetWidth ? tableEl.offsetWidth : 0
  117. return tableWidth > width ? '100%' : width
  118. }, [selectKeysRef])
  119. const getScrollRef = useMemo(() => {
  120. return { x: getSrollX, y: tableHeight || null }
  121. }, [getSrollX, tableHeight])
  122. return { getScrollRef, redoHeight }
  123. }