оптимизацмя таблицы

This commit is contained in:
PotapovaA 2026-07-20 11:30:51 +03:00
parent dc621a1223
commit 096a8b817f

View File

@ -134,6 +134,11 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
return () => document.removeEventListener('mousedown', handleDocumentClick);
}, [selectedColumnId]);
const handleCellUpdateError = useCallback((rowId, columnId, error) => {
console.error(`Error updating cell ${rowId}_${columnId}:`, error);
toast.error('Ошибка обновления ячейки');
}, []);
const columns = useMemo(() => {
if (!columnsConfig || !columnsConfig.columns) return [];
try {
@ -143,128 +148,160 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
columnsConfig,
onCellUpdate: handleUpdateCell,
onCellNumberClick: handleClickRowCell,
onCellUpdateError: (rowId, columnId, error) => {
console.error(`Error updating cell ${rowId}_${columnId}:`, error);
toast.error('Ошибка обновления ячейки')
}
onCellUpdateError: handleCellUpdateError,
});
} catch (error) {
console.error('Error creating columns:', error);
return [];
}
}, [columnsConfig, handleUpdateCell, handleClickRowCell]);
}, [columnsConfig, handleUpdateCell, handleClickRowCell, handleCellUpdateError]);
const selectedColumnIdRef = useRef(selectedColumnId);
useEffect(() => {
selectedColumnIdRef.current = selectedColumnId;
}, [selectedColumnId]);
const tableMeta = useMemo(() => ({
updateCell: handleUpdateCell,
selectedColumnId,
}), [handleUpdateCell, selectedColumnId]);
getSelectedColumnId: () => selectedColumnIdRef.current,
}), [handleUpdateCell]);
// Конфигурация таблицы
const tableConfig = useMemo(
() => ({
...BASE_TABLE_CONFIG,
columns,
data: data,
enableRowVirtualization: true,
enableColumnVirtualization: true,
rowVirtualizerInstanceRef: rowVirtualizerRef,
rowVirtualizerOptions: {
overscan: 30,
scrollPaddingStart: 0,
scrollPaddingEnd: 0,
estimateSize: () => TABLE_ROW_HEIGHT,
measureElement: (el) => el?.offsetHeight || TABLE_ROW_HEIGHT,
},
onEditingCellChange: (cell) => {
if (cell) {
if (editingCell) return;
contextStartEditing?.(cell.row, cell.column);
const ROW_VIRTUALIZER_OPTIONS = {
overscan: 30,
scrollPaddingStart: 0,
scrollPaddingEnd: 0,
estimateSize: () => TABLE_ROW_HEIGHT,
measureElement: (el) => el?.offsetHeight || TABLE_ROW_HEIGHT,
};
const createTableConfig = ({
columns,
data,
columnSizing,
columnPinning,
columnVisibility,
globalFilter,
showColumnFilters,
rowSelection,
containerRef,
tableMeta,
setColumnSizing,
setColumnPinning,
editingCell,
contextStartEditing,
}) => ({
...BASE_TABLE_CONFIG,
columns,
data,
enableRowVirtualization: true,
enableColumnVirtualization: true,
rowVirtualizerInstanceRef: rowVirtualizerRef,
rowVirtualizerOptions: ROW_VIRTUALIZER_OPTIONS,
onEditingCellChange: (cell) => {
if (cell && !editingCell) {
contextStartEditing?.(cell.row, cell.column);
}
},
columnVirtualizerOptions: ({ table }) => ({
overscan: 10,
measureElement: (el) => {
if (!el) return 150;
const index = Number(el?.getAttribute?.('data-index'));
const isPinned = Boolean(el?.getAttribute?.('data-pinned'));
if (isPinned) {
const colId = table.getState().columnPinning.left[index];
const column = table.getColumn(colId);
return column?.getSize() ?? 150;
}
},
columnVirtualizerOptions: ({ table }) => ({
overscan: 10,
measureElement: (el) => {
if (!el) return 150;
const index = Number(el?.getAttribute?.('data-index'));
const isPinned = Boolean(el?.getAttribute?.('data-pinned'));
if (isPinned) {
const colId = table.getState().columnPinning.left[index];
const column = table.getColumn(colId);
return column?.getSize() ?? 150;
}
const allCols = [...table.getLeftVisibleLeafColumns(), ...table.getCenterVisibleLeafColumns()]
return allCols[index]?.getSize() ?? 150;
},
}),
enableRowSelection: true,
onRowSelectionChange: setRowSelection,
onColumnSizingChange: setColumnSizing,
onColumnPinningChange: setColumnPinning,
onGlobalFilterChange: handleGlobalFilterChange,
state: {
columnSizing,
columnPinning,
columnVisibility,
globalFilter,
showColumnFilters,
rowSelection,
editingCell,
},
initialState: {
expanded: true,
},
meta: tableMeta,
muiTableHeadCellProps: {
sx: { boxSizing: 'border-box' },
},
muiTableBodyCellProps: getTableBodyCellProps,
muiTableHeadProps: {
sx: {
display: 'table-header-group',
height: '1px',
minHeight: '1px',
maxHeight: '1px',
visibility: 'hidden',
'& svg': {
height: '1px',
minHeight: '1px',
maxHeight: '1px',
visibility: 'hidden',
}
},
},
muiTablePaperProps: getTablePaperStyles(),
muiTableContainerProps: {
ref: containerRef,
sx: {
position: 'relative',
contain: 'layout',
minHeight: '100%',
'& .MuiTable-root': { position: 'relative' },
},
},
muiTableHeadCellFilterTextFieldProps: {
placeholder: 'Поиск...',
size: 'small',
const allCols = [...table.getLeftVisibleLeafColumns(), ...table.getCenterVisibleLeafColumns()]
return allCols[index]?.getSize() ?? 150;
},
}),
[
columns,
data,
setColumnSizing,
setColumnPinning,
enableRowSelection: true,
onRowSelectionChange: setRowSelection,
onColumnSizingChange: setColumnSizing,
onColumnPinningChange: setColumnPinning,
onGlobalFilterChange: handleGlobalFilterChange,
state: {
columnSizing,
columnPinning,
columnVisibility,
globalFilter,
showColumnFilters,
containerRef,
tableMeta,
rowSelection,
editingCell
],
);
editingCell,
},
initialState: {
expanded: true,
},
meta: tableMeta,
muiTableHeadCellProps: {
sx: { boxSizing: 'border-box' },
},
muiTableBodyCellProps: getTableBodyCellProps,
muiTableHeadProps: {
sx: {
display: 'table-header-group',
height: '1px',
minHeight: '1px',
maxHeight: '1px',
visibility: 'hidden',
'& svg': {
height: '1px',
minHeight: '1px',
maxHeight: '1px',
visibility: 'hidden',
}
},
},
muiTablePaperProps: getTablePaperStyles(),
muiTableContainerProps: {
ref: containerRef,
sx: {
position: 'relative',
contain: 'layout',
minHeight: '100%',
'& .MuiTable-root': { position: 'relative' },
},
},
muiTableHeadCellFilterTextFieldProps: {
placeholder: 'Поиск...',
size: 'small',
},
});
// Конфигурация таблицы
const tableConfig = useMemo(() => createTableConfig({
columns,
data,
columnSizing,
columnPinning,
columnVisibility,
globalFilter,
showColumnFilters,
rowSelection,
containerRef,
tableMeta,
setColumnSizing,
setColumnPinning,
editingCell,
contextStartEditing,
}), [
columns,
data,
columnSizing,
columnPinning,
columnVisibility,
globalFilter,
showColumnFilters,
rowSelection,
containerRef,
tableMeta,
setColumnSizing,
setColumnPinning,
editingCell,
]);
const table = useMaterialReactTable(tableConfig);
@ -342,6 +379,17 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
setRowSelection({});
}, [rowSelection, table])
useEffect(() => {
return () => {
setData([]);
setRowSelection({});
setEditingCell(null);
if (rowVirtualizerRef.current) {
rowVirtualizerRef.current = null;
}
};
}, []);
return (
<>
<SettingsPanel