From afc91799ddfa0c9c6934b42295fadb6829765512 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期三, 04 二月 2026 14:18:59 +0800
Subject: [PATCH] #优化StickyDataTable
---
rsf-admin/src/page/components/StickyDataTable.jsx | 157 +++++++++++++++++++++++++++++----------------------
1 files changed, 89 insertions(+), 68 deletions(-)
diff --git a/rsf-admin/src/page/components/StickyDataTable.jsx b/rsf-admin/src/page/components/StickyDataTable.jsx
index f2cbada..4fbae7a 100644
--- a/rsf-admin/src/page/components/StickyDataTable.jsx
+++ b/rsf-admin/src/page/components/StickyDataTable.jsx
@@ -1,5 +1,5 @@
-import React from 'react';
+import React, { useMemo } from 'react';
import { DataTable, useDataTableDataContext, useTranslate } from 'react-admin';
import { TableFooter, TableRow, TableCell } from '@mui/material';
@@ -37,6 +37,50 @@
};
/**
+ * 鍥哄畾鍒楁牱寮忓父閲�
+ */
+const stickyLeftStyle = {
+ position: 'sticky',
+ left: 0,
+ zIndex: 2,
+ backgroundColor: '#FFFFFF',
+ '.MuiTableRow-root:not(.MuiTableRow-head):hover &': {
+ backgroundColor: '#f5f5f5'
+ }
+};
+
+const stickyRightStyle = {
+ position: 'sticky',
+ right: 0,
+ zIndex: 2,
+ backgroundColor: '#FFFFFF',
+ '.MuiTableRow-root:not(.MuiTableRow-head):hover &': {
+ backgroundColor: '#f5f5f5'
+ }
+};
+
+/**
+ * DataTable 鏍峰紡甯搁噺
+ */
+const tableStyles = {
+ '& .MuiTableCell-head': {
+ zIndex: 4,
+ borderBottom: 'none'
+ },
+ '& .MuiTableFooter-root': {
+ position: 'sticky',
+ bottom: 0,
+ zIndex: 3,
+ backgroundColor: '#FFFFFF',
+ },
+ '& .MuiTableFooter-root .MuiTableCell-root': {
+ backgroundColor: '#f5f5f5',
+ fontWeight: 'bold',
+ borderTop: '2px solid #e0e0e0',
+ },
+};
+
+/**
* 鍐呴儴 Footer 缁勪欢
* @param {Object} props
* @param {Array} props.footerConfig - footer 閰嶇疆鏁扮粍
@@ -46,7 +90,8 @@
const data = useDataTableDataContext();
const translate = useTranslate();
- const results = footerConfig.map(config => {
+ // 缂撳瓨璁$畻缁撴灉锛岄伩鍏嶄笉蹇呰鐨勯噸澶嶈绠�
+ const results = useMemo(() => footerConfig.map(config => {
const { field, type = 'sum', label, render } = config;
const calculator = calculators[type];
const value = calculator ? calculator(data, field) : 0;
@@ -60,7 +105,7 @@
// 鑾峰彇缈昏瘧鍚庣殑鏍囩
const displayLabel = label ? (label.startsWith('table.') || label.startsWith('common.') ? translate(label) : label) : field;
return { label: displayLabel, value, typePrefix };
- });
+ }), [footerConfig, data, translate]);
return (
<TableFooter>
@@ -100,80 +145,56 @@
...props
}) => {
- // 閫掑綊澶勭悊 Children锛岀‘淇濆嵆渚挎槸 Fragment 鍖呰9鐨勫垪涔熻兘琚鐞�
- const processChildren = (children) => {
- return React.Children.map(children, (child) => {
- if (!React.isValidElement(child)) return child;
+ // 浣跨敤 Set 浼樺寲鏌ユ壘鎬ц兘 O(n) -> O(1)
+ const stickyLeftSet = useMemo(() => new Set(stickyLeft), [stickyLeft]);
+ const stickyRightSet = useMemo(() => new Set(stickyRight), [stickyRight]);
- // 濡傛灉鏄� Fragment锛岄�掑綊澶勭悊鍏� children
- if (child.type === React.Fragment) {
- return <React.Fragment>{processChildren(child.props.children)}</React.Fragment>;
- }
+ // 缂撳瓨澶勭悊鍚庣殑 children锛岄伩鍏嶄笉蹇呰鐨勯噸鏂拌绠�
+ const processedChildren = useMemo(() => {
+ const processChildren = (children) => {
+ return React.Children.map(children, (child) => {
+ if (!React.isValidElement(child)) return child;
- const source = child.props.source;
- let stickyStyle = {};
+ // 濡傛灉鏄� Fragment锛岄�掑綊澶勭悊鍏� children
+ if (child.type === React.Fragment) {
+ return <React.Fragment>{processChildren(child.props.children)}</React.Fragment>;
+ }
- // 宸︿晶鍥哄畾
- if (stickyLeft.includes(source)) {
- stickyStyle = {
- position: 'sticky',
- left: 0,
- zIndex: 2, // 姣旀櫘閫氬唴瀹归珮
- backgroundColor: '#FFFFFF',
- '.MuiTableRow-root:not(.MuiTableRow-head):hover &': {
- backgroundColor: '#f5f5f5'
- }
- };
- }
+ const source = child.props.source;
+ let stickyStyle = null;
- // 鍙充晶鍥哄畾
- if (stickyRight.includes(source)) {
- stickyStyle = {
- position: 'sticky',
- right: 0,
- zIndex: 2,
- backgroundColor: '#FFFFFF',
- '.MuiTableRow-root:not(.MuiTableRow-head):hover &': {
- backgroundColor: '#f5f5f5'
- }
- };
- }
+ // 宸︿晶鍥哄畾
+ if (stickyLeftSet.has(source)) {
+ stickyStyle = stickyLeftStyle;
+ }
- if (Object.keys(stickyStyle).length > 0) {
- // 鍚堝苟 sx
- return React.cloneElement(child, {
- sx: { ...child.props.sx, ...stickyStyle }
- });
- }
+ // 鍙充晶鍥哄畾
+ if (stickyRightSet.has(source)) {
+ stickyStyle = stickyRightStyle;
+ }
- return child;
- });
- };
+ if (stickyStyle) {
+ // 鍚堝苟 sx
+ return React.cloneElement(child, {
+ sx: { ...child.props.sx, ...stickyStyle }
+ });
+ }
- // 鏋勫缓 foot 灞炴��
- const footerComponent = footerConfig && footerConfig.length > 0
- ? () => <StickyTableFooter footerConfig={footerConfig} footerLabel={footerLabel} />
- : undefined;
+ return child;
+ });
+ };
+ return processChildren(children);
+ }, [children, stickyLeftSet, stickyRightSet]);
+
+ // 缂撳瓨 footerComponent锛岄伩鍏嶆瘡娆℃覆鏌撳垱寤烘柊鍑芥暟
+ const footerComponent = useMemo(() => {
+ if (!footerConfig?.length) return undefined;
+ return () => <StickyTableFooter footerConfig={footerConfig} footerLabel={footerLabel} />;
+ }, [footerConfig, footerLabel]);
return (
- <DataTable {...props} foot={footerComponent} sx={{
- '& .MuiTableCell-head': {
- zIndex: 4,
- borderBottom: 'none' // 閬靛惊涔嬪墠鐨勪紭鍖栵紝鍘婚櫎琛ㄥご涓嬭竟妗�
- },
- '& .MuiTableFooter-root': {
- position: 'sticky',
- bottom: 0,
- zIndex: 3,
- backgroundColor: '#FFFFFF',
- },
- '& .MuiTableFooter-root .MuiTableCell-root': {
- backgroundColor: '#f5f5f5',
- fontWeight: 'bold',
- borderTop: '2px solid #e0e0e0',
- },
- }}>
- {processChildren(children)}
+ <DataTable {...props} foot={footerComponent} sx={tableStyles}>
+ {processedChildren}
</DataTable>
);
};
--
Gitblit v1.9.1