zy-react-library/src/components/Table/index.js

187 lines
5.4 KiB
JavaScript
Raw Normal View History

2025-12-27 09:53:06 +08:00
import { ProTable } from "@ant-design/pro-components";
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";
2025-10-29 09:38:36 +08:00
import "./index.less";
2025-10-22 14:43:42 +08:00
2025-12-27 09:53:06 +08:00
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.sessionStorage.getItem(getPersistenceKey(index).size);
2025-12-27 09:53:06 +08:00
}
function setTableSize(value, index) {
return window.sessionStorage.setItem(getPersistenceKey(index).size, value);
2025-12-27 09:53:06 +08:00
}
2025-11-12 15:46:41 +08:00
function Table(props) {
2025-10-22 14:43:42 +08:00
const {
columns = [],
2025-11-05 09:17:28 +08:00
showIndexColumn = true,
2025-12-24 15:45:07 +08:00
ellipsis = true,
align = "center",
2025-11-05 09:17:28 +08:00
indexColumnFixed = "left",
2025-10-29 09:38:36 +08:00
rowKey = "id",
2025-12-27 09:53:06 +08:00
storeIndex,
disabledResizer = false,
height,
2025-10-22 14:43:42 +08:00
...restProps
} = props;
2025-11-13 17:45:55 +08:00
2025-12-27 09:53:06 +08:00
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,
});
}
2025-12-24 15:45:07 +08:00
2025-12-27 09:53:06 +08:00
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 });
2025-12-24 15:45:07 +08:00
const setAlign = column => ({
align,
ellipsis,
2025-11-13 17:47:12 +08:00
...column,
2025-12-24 15:45:07 +08:00
...(column.children ? { children: column.children.map(setAlign) } : {}),
2025-11-13 17:45:55 +08:00
});
2025-12-27 09:53:06 +08:00
return columnsCopy.map(setAlign);
};
const processedColumns = useMemo(() => settingColumns(), [resizableColumns, showIndexColumn, align, ellipsis, indexColumnFixed, props.pagination]);
2025-12-24 15:45:07 +08:00
return (
<div className="table-layout card-layout">
2025-12-27 09:53:06 +08:00
<ProTable
ghost={true}
search={false}
scroll={{
x: tableWidth,
y: height || (enabledResizer ? tableHeight : undefined),
2025-12-27 09:53:06 +08:00
}}
options={{
reload: false,
fullScreen: true,
setting: {
checkedReset: true,
extra: (
<a
className={`${antPrefix}-pro-table-column-setting-action-rest-button`}
onClick={resetColumns}
>
重置列宽
</a>
),
},
}}
components={components}
columnsState={{
persistenceKey: persistenceKey.columnState,
persistenceType: "localStorage",
}}
onSizeChange={setSize}
columns={processedColumns}
bordered
size="small"
rowKey={rowKey}
{...restProps}
/>
2025-12-24 15:45:07 +08:00
</div>
);
2025-10-22 14:43:42 +08:00
}
2025-12-24 15:45:07 +08:00
Table.displayName = "Table";
2025-11-12 15:46:41 +08:00
export default Table;