import { ProTable } from "@ant-design/pro-components"; import dayjs from "dayjs"; import { useEffect, useMemo, useState } from "react"; import { throttle } from "throttle-debounce"; import { useAntdResizableHeader } from "use-antd-resizable-header"; import { getDataType, getIndexColumn } from "../../utils"; import "use-antd-resizable-header/dist/style.css"; import "./index.less"; const CLEANUP_INTERVAL_DAYS = 10; // 清理间隔天数 const LAST_CLEANUP_KEY = "tableLocalStorageLastCleanup"; // 最后清理时间存储key // 清理本地存储中特定后缀的key function cleanupTableLocalStorage() { const now = dayjs(); const lastCleanupStr = localStorage.getItem(LAST_CLEANUP_KEY); const lastCleanup = lastCleanupStr ? dayjs(lastCleanupStr) : null; // 如果没有上次清理时间或距离上次清理已超过10天 if (!lastCleanup || now.diff(lastCleanup, "day") >= CLEANUP_INTERVAL_DAYS) { // 查找并清理符合条件的key const keysToRemove = []; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && (key.endsWith("#columnState") || key.endsWith("#size") || key.endsWith("#resizable"))) { keysToRemove.push(key); } } // 删除匹配的key keysToRemove.forEach((key) => { localStorage.removeItem(key); }); // 更新最后清理时间 localStorage.setItem(LAST_CLEANUP_KEY, now.toISOString()); } } function getPersistenceKey(index) { const basename = process.env?.app?.basename; const pathname = decodeURIComponent(window.location.pathname); const insertIndex = getDataType(index) === "Undefined" ? "" : `#{${index}}`; return { size: `${basename}#${pathname}${insertIndex}#size`, resizable: `${basename}#${pathname}${insertIndex}#resizable`, columnState: `${basename}#${pathname}${insertIndex}#columnState`, }; } function getTableSize(index) { return window.localStorage.getItem(getPersistenceKey(index).size); } function setTableSize(value, index) { return window.localStorage.setItem(getPersistenceKey(index).size, value); } function Table(props) { const { columns = [], showIndexColumn = true, ellipsis = true, align = "center", indexColumnFixed = "left", rowKey = "id", storeIndex, disabledResizer = false, height, ...restProps } = props; const antPrefix = process.env.app.antd["ant-prefix"]; const prefix = antPrefix || "ant"; const baseCls = `.${prefix}-table`; const tableCls = `${baseCls}-wrapper`; const tableBodyCls = `${baseCls}-body`; const [size, setSize] = useState(getTableSize(storeIndex) || "default"); const [tableHeight, setTableHeight] = useState(0); const persistenceKey = getPersistenceKey(storeIndex); const enabledResizer = !disabledResizer; const { components, resizableColumns, tableWidth, resetColumns, } = useAntdResizableHeader({ columns, columnsState: { persistenceKey: persistenceKey.resizable, persistenceType: "localStorage", }, }); // 计算高度 const calcTableHeight = throttle(50, () => { try { // table元素 const tableEl = document.querySelector(tableCls); // table-body元素 const tableBodyEl = document.querySelector(tableBodyCls); // 获取页脚元素高度 const footerEl = document.querySelector(".page-layout-footer"); const footerHeight = footerEl ? footerEl.offsetHeight : 0; if (tableBodyEl && tableEl) { // 获取table元素的矩形数据 const tableRect = tableEl.getBoundingClientRect(); // 获取table-body元素的矩形数据 const tableBodyRect = tableBodyEl.getBoundingClientRect(); // 获取底部的高度差 const bottomHeight = tableRect.bottom - tableBodyRect.bottom; // 计算最终值,减去页脚高度 setTableHeight(innerHeight - tableBodyRect.top - bottomHeight - (window.__IN_BASE__ ? 38 : 22) - footerHeight); } } catch (e) { window.console.error(e); } }); useEffect(() => { let mutationObserver, resizeObserver; if (enabledResizer) { // 监听-DOM树 mutationObserver = new MutationObserver(mutations => mutations.forEach(() => calcTableHeight())); // 监听-缩放 resizeObserver = new ResizeObserver(entries => entries.forEach(() => calcTableHeight())); // 初始化首次计算 setTimeout(() => calcTableHeight(), 500); // 执行-监听-缩放 resizeObserver.observe(document.body); // 执行-监听-DOM树是否发生变化 mutationObserver.observe(document.body, { subtree: true, childList: true, }); } cleanupTableLocalStorage(); return () => { if (mutationObserver && resizeObserver && enabledResizer) { resizeObserver.unobserve(document.body); mutationObserver.disconnect(document.body); } }; }, []); useEffect(() => { setTableSize(size, storeIndex); }, [size]); const settingColumns = () => { const columnsCopy = [...resizableColumns]; showIndexColumn && columnsCopy.unshift({ ...getIndexColumn(props.pagination), fixed: indexColumnFixed }); const setAlign = column => ({ align, ellipsis, ...column, ...(column.children ? { children: column.children.map(setAlign) } : {}), }); return columnsCopy.map(setAlign); }; const processedColumns = useMemo(() => settingColumns(), [resizableColumns, showIndexColumn, align, ellipsis, indexColumnFixed, props.pagination]); return (