chen.lin
1 天以前 209878277a178ab91d48b523265e5ffb1b8cf7e6
rsf-admin/src/page/components/StickyDataTable.jsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
import React, { useMemo, useRef, useEffect } from 'react';
import { DataTable, useDataTableDataContext, useTranslate } from 'react-admin';
import { TableFooter, TableRow, TableCell } from '@mui/material';
@@ -63,6 +63,10 @@
 * DataTable 样式常量
 */
const tableStyles = {
    '& .RaBulkActionsToolbar-toolbar': {
        top: 0,
        zIndex: 6,
    },
    '& .MuiTableCell-head': {
        zIndex: 4,
        borderBottom: 'none'
@@ -140,12 +144,14 @@
 *   - label: 显示的标签,支持翻译 key 或直接显示的文本
 *   - render: 可选,自定义渲染函数 (value, data) => ReactNode
 * @param {string} props.footerLabel - footer 第一列标签,默认'合计'
 * @param {number} props.bulkActionsOffsetY - 批量操作栏展开时向下偏移(px)
 */
export const StickyDataTable = ({
    stickyLeft = [],
    stickyRight = [],
    footerConfig,
    footerLabel = '合计',
    bulkActionsOffsetY = 0,
    children,
    ...props
}) => {
@@ -197,8 +203,37 @@
        return () => <StickyTableFooter footerConfig={footerConfig} footerLabel={footerLabel} />;
    }, [footerConfig, footerLabel]);
    const dataTableStyles = useMemo(() => {
        return {
            ...tableStyles,
            '& .RaBulkActionsToolbar-toolbar:not(.RaBulkActionsToolbar-collapsed)': {
                transform: `translateY(${bulkActionsOffsetY}px)`,
                zIndex: 10,
                opacity: 1,
            },
            '& .RaBulkActionsToolbar-toolbar.RaBulkActionsToolbar-collapsed': {
                zIndex: 10,
                opacity: 1,
            },
        };
    }, [bulkActionsOffsetY]);
    const containerRef = useRef(null);
    useEffect(() => {
        const el = containerRef.current;
        if (!el) return;
        const clearExpandIconAriaHidden = () => {
            el.querySelectorAll('.RaDataTable-expandIcon').forEach((btn) => btn.removeAttribute('aria-hidden'));
        };
        clearExpandIconAriaHidden();
        const mo = new MutationObserver(clearExpandIconAriaHidden);
        mo.observe(el, { attributes: true, attributeFilter: ['aria-hidden'], subtree: true });
        return () => mo.disconnect();
    }, []);
    return (
        <DataTable {...props} foot={footerComponent} sx={tableStyles}>
        <span ref={containerRef} style={{ display: 'contents' }}>
        <DataTable {...props} foot={footerComponent} sx={dataTableStyles}>
            {/* {processedChildren} */}
            {processedChildren
                .map((column) => (
@@ -213,6 +248,7 @@
                ))
            }
        </DataTable>
        </span>
    );
};