import React, { useState, useRef, useEffect, useContext } from 'react'; import { Table, ConfigProvider } from 'antd'; import { TableProps } from 'antd/es/table'; // @ts-ignore import { useHeight } from '@ra-lib/hooks'; import ComponentContext from '../component-context'; export interface RATableProps extends TableProps { // 是否适应高度 fitHeight?: boolean, // 是否显示序号 serialNumber?: boolean, // 序号列是否固定 serialNumberFixed?: boolean, // 序号列头名称 serialText?: string, // 序号列宽 serialNumberWidth?: number, // 如果显示序号,需要传递pageSize pageSize?: number, // 如果显示序号,需要传递pageNum pageNum?: number, // 计算高度使用的额外高度 otherHeight?: number, // 计算之后,再做偏移的高度 offsetHeight?: number, borderBottom?: boolean, } export default function RATable = any>(props: RATableProps) { let { fitHeight = false, scroll = {}, otherHeight, offsetHeight = 0, columns, serialNumber = false, serialText = '序号', serialNumberFixed = false, serialNumberWidth = 60, pageSize, pageNum, dataSource, pagination = false, borderBottom = true, rowKey = 'id', ...others } = props; const context = useContext(ComponentContext); if (context.isMobile) { fitHeight = false; if (!scroll.x && columns.length > 3) scroll.x = columns.length * 180; } const antdContext = useContext(ConfigProvider.ConfigContext); const antdPrefixCls = antdContext.getPrefixCls(); const rootRef = useRef(null); const [ _otherHeight, setOtherHeight ] = useState(otherHeight); const [ hasPagination, setHasPagination ] = useState(false); const pageContentPadding = 8; const pageContentMargin = 8; const { isMobile, mobileColumnDefaultWidth } = context; let [ height ] = useHeight(rootRef); height = height - (_otherHeight || 0) - (offsetHeight || 0); if (scroll.y) fitHeight = false; const _scroll = { ...scroll }; if (fitHeight) _scroll.y = height; useEffect(() => { if (!fitHeight) return; const oldOverflowY = window.document.body.style.overflowY || 'auto'; window.document.body.style.overflowY = 'hidden'; return () => { window.document.body.style.overflowY = oldOverflowY; }; }, [ fitHeight ]); useEffect(() => { function _setOtherHeight() { if (otherHeight !== undefined) return; if (!rootRef.current) return; let headHeight = 0; let paginationHeight = 0; const tableHead = rootRef.current.querySelector(`.${antdPrefixCls}-table-thead`); if (tableHead) headHeight = tableHead.getBoundingClientRect().height; const paginationDom = rootRef.current.nextElementSibling; if (paginationDom) { setHasPagination(true); paginationHeight = paginationDom.getBoundingClientRect().height; } setOtherHeight(headHeight + paginationHeight + pageContentPadding + pageContentMargin + 1); } // 预设值,防止body出现滚动条 _setOtherHeight(); // 等待table-thead 渲染完成 再设置,调整表格高度 setTimeout(() => { _setOtherHeight(); }); // 等待表格数据渲染完成,从新调整一次高度 setTimeout(() => { _setOtherHeight(); }, 100); // 窗口改变也设置高度 window.addEventListener('resize', _setOtherHeight); return () => window.removeEventListener('resize', _setOtherHeight); }, [ otherHeight, dataSource, antdPrefixCls ]); useEffect(() => { if (!fitHeight) return; const tableBody = rootRef.current.querySelector(`.${antdPrefixCls}-table-body`); const tablePlaceholder = rootRef.current.querySelector(`.${antdPrefixCls}-table-placeholder .${antdPrefixCls}-table-cell`); if (!tableBody) return; tableBody.style.height = `${height}px`; if (tablePlaceholder) { tablePlaceholder.style.height = `${height - 40}px`; tablePlaceholder.style.border = 'none'; } }, [ fitHeight, height, dataSource, antdPrefixCls ]); if (serialNumber) { if (hasPagination) { if (!('pageNum' in props)) throw Error('分页表格如果显示序号,需要传递pageNum属性'); if (!('pageSize' in props)) throw Error('分页表格如果显示序号,需要传递pageSize属性'); } columns = [ { title: serialText, width: serialNumberWidth, dataIndex: '__num', key: '__num', fixed: serialNumberFixed ? 'left' : false, render: (value, record, index) => index + 1 + (hasPagination ? pageSize * (pageNum - 1) : 0), }, ...columns, ]; } if (isMobile) { columns.forEach(item => { if (!('width' in item)) { // eslint-disable-next-line no-param-reassign item.width = mobileColumnDefaultWidth; } }); } return (
); }