优化Table
parent
ab99f43ea1
commit
001e82c7cf
|
|
@ -1,10 +1,14 @@
|
||||||
import TablePro from "@cqsjjb/jjb-react-admin-component/Table";
|
import { ProTable } from "@ant-design/pro-components";
|
||||||
import { getIndexColumn } from "../../utils/index";
|
import dayjs from "dayjs";
|
||||||
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";
|
import "./index.less";
|
||||||
|
|
||||||
const CLEANUP_INTERVAL_DAYS = 10; // 清理间隔天数
|
const CLEANUP_INTERVAL_DAYS = 10; // 清理间隔天数
|
||||||
const LAST_CLEANUP_KEY = 'tableLocalStorageLastCleanup'; // 最后清理时间存储key
|
const LAST_CLEANUP_KEY = "tableLocalStorageLastCleanup"; // 最后清理时间存储key
|
||||||
|
|
||||||
// 清理本地存储中特定后缀的key
|
// 清理本地存储中特定后缀的key
|
||||||
function cleanupTableLocalStorage() {
|
function cleanupTableLocalStorage() {
|
||||||
|
|
@ -13,20 +17,20 @@ function cleanupTableLocalStorage() {
|
||||||
const lastCleanup = lastCleanupStr ? dayjs(lastCleanupStr) : null;
|
const lastCleanup = lastCleanupStr ? dayjs(lastCleanupStr) : null;
|
||||||
|
|
||||||
// 如果没有上次清理时间或距离上次清理已超过10天
|
// 如果没有上次清理时间或距离上次清理已超过10天
|
||||||
if (!lastCleanup || now.diff(lastCleanup, 'day') >= CLEANUP_INTERVAL_DAYS) {
|
if (!lastCleanup || now.diff(lastCleanup, "day") >= CLEANUP_INTERVAL_DAYS) {
|
||||||
// 查找并清理符合条件的key
|
// 查找并清理符合条件的key
|
||||||
const keysToRemove = [];
|
const keysToRemove = [];
|
||||||
for (let i = 0; i < localStorage.length; i++) {
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
const key = localStorage.key(i);
|
const key = localStorage.key(i);
|
||||||
if (key && (key.endsWith('#columnState') ||
|
if (key && (key.endsWith("#columnState")
|
||||||
key.endsWith('#size') ||
|
|| key.endsWith("#size")
|
||||||
key.endsWith('#resizable'))) {
|
|| key.endsWith("#resizable"))) {
|
||||||
keysToRemove.push(key);
|
keysToRemove.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除匹配的key
|
// 删除匹配的key
|
||||||
keysToRemove.forEach(key => {
|
keysToRemove.forEach((key) => {
|
||||||
localStorage.removeItem(key);
|
localStorage.removeItem(key);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -35,6 +39,26 @@ function cleanupTableLocalStorage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
function Table(props) {
|
||||||
const {
|
const {
|
||||||
columns = [],
|
columns = [],
|
||||||
|
|
@ -43,14 +67,101 @@ function Table(props) {
|
||||||
align = "center",
|
align = "center",
|
||||||
indexColumnFixed = "left",
|
indexColumnFixed = "left",
|
||||||
rowKey = "id",
|
rowKey = "id",
|
||||||
|
storeIndex,
|
||||||
|
disabledResizer = false,
|
||||||
...restProps
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
// 组件初始化时执行清理
|
const antPrefix = process.env.app.antd["ant-prefix"];
|
||||||
cleanupTableLocalStorage();
|
const prefix = antPrefix || "ant";
|
||||||
|
const baseCls = `.${prefix}-table`;
|
||||||
|
const tableCls = `${baseCls}-wrapper`;
|
||||||
|
const tableBodyCls = `${baseCls}-body`;
|
||||||
|
|
||||||
function settingColumns() {
|
const [size, setSize] = useState(getTableSize(storeIndex) || "default");
|
||||||
showIndexColumn && columns.unshift({ ...getIndexColumn(props.pagination), fixed: indexColumnFixed });
|
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 => ({
|
const setAlign = column => ({
|
||||||
align,
|
align,
|
||||||
|
|
@ -59,11 +170,47 @@ function Table(props) {
|
||||||
...(column.children ? { children: column.children.map(setAlign) } : {}),
|
...(column.children ? { children: column.children.map(setAlign) } : {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
return columns.map(setAlign);
|
return columnsCopy.map(setAlign);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const processedColumns = useMemo(() => settingColumns(), [resizableColumns, showIndexColumn, align, ellipsis, indexColumnFixed, props.pagination]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="table-layout card-layout">
|
<div className="table-layout card-layout">
|
||||||
<TablePro rowKey={rowKey} columns={settingColumns()} bordered size="small" {...restProps} />
|
<ProTable
|
||||||
|
ghost={true}
|
||||||
|
search={false}
|
||||||
|
scroll={{
|
||||||
|
x: tableWidth,
|
||||||
|
y: enabledResizer ? tableHeight : undefined,
|
||||||
|
}}
|
||||||
|
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}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,3 @@
|
||||||
padding-top: 0 !important;
|
padding-top: 0 !important;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-layout {
|
|
||||||
+ .table-layout .@{ant-prefix}-pro-table-list-toolbar-container {
|
|
||||||
padding-top: 26px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue