perf(table): фиксированная высота строк вместо measureElement (лист, свод 1, свод 2)
Высота строки и ячейки задана явно в rem, виртуализатор не читает offsetHeight. Мёртвая muiTableRowProps удалена. Overscan строк свода 2: 8 -> 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
bdb00afc5a
commit
12a315b04a
@ -16,7 +16,8 @@ import { CreateProgramModal } from './Modals/CreateProgramProjectModal';
|
|||||||
import { SelectExpenseItemModal } from './Modals/SelectExpenseItemModal';
|
import { SelectExpenseItemModal } from './Modals/SelectExpenseItemModal';
|
||||||
import { SelectVspModal } from './Modals/SelectVspModal';
|
import { SelectVspModal } from './Modals/SelectVspModal';
|
||||||
import { additionExpenseRowTable, additionVspRowTable } from './constants/addingRowConfig';
|
import { additionExpenseRowTable, additionVspRowTable } from './constants/addingRowConfig';
|
||||||
import { BASE_TABLE_CONFIG, TABLE_ROW_HEIGHT, getTableBodyCellProps, getTablePaperStyles } from './constants/tableConfig';
|
import { BASE_TABLE_CONFIG, TABLE_ROW_HEIGHT, getTableBodyCellProps, getTablePaperStyles, getTableRowHeightPx } from './constants/tableConfig';
|
||||||
|
import { createFixedRowVirtualizerOptions } from './utils/virtualizerOptions';
|
||||||
import { useRealtimeActions, useVspOptions } from './contexts/RealtimeContext';
|
import { useRealtimeActions, useVspOptions } from './contexts/RealtimeContext';
|
||||||
import { useColumnSettings } from './hooks/useColumnSettings';
|
import { useColumnSettings } from './hooks/useColumnSettings';
|
||||||
import { useHeaderPortal } from './hooks/useHeaderPortal';
|
import { useHeaderPortal } from './hooks/useHeaderPortal';
|
||||||
@ -34,13 +35,11 @@ import useDenomination from '../common/useDenomination';
|
|||||||
|
|
||||||
const CONFIG_CACHE = new Map();
|
const CONFIG_CACHE = new Map();
|
||||||
|
|
||||||
const ROW_VIRTUALIZER_OPTIONS = {
|
const ROW_VIRTUALIZER_OPTIONS = createFixedRowVirtualizerOptions({
|
||||||
|
rowHeight: getTableRowHeightPx,
|
||||||
overscan: 5,
|
overscan: 5,
|
||||||
scrollPaddingStart: 0,
|
extra: { scrollPaddingStart: 0, scrollPaddingEnd: 0 },
|
||||||
scrollPaddingEnd: 0,
|
});
|
||||||
estimateSize: () => TABLE_ROW_HEIGHT,
|
|
||||||
measureElement: (element) => element?.offsetHeight || TABLE_ROW_HEIGHT,
|
|
||||||
};
|
|
||||||
|
|
||||||
const hasVspDropdown = (columns) =>
|
const hasVspDropdown = (columns) =>
|
||||||
columns.some((column) => column.editType === 'vsp_dropdown' || (column.columns?.length && hasVspDropdown(column.columns)));
|
columns.some((column) => column.editType === 'vsp_dropdown' || (column.columns?.length && hasVspDropdown(column.columns)));
|
||||||
@ -362,6 +361,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
|
|||||||
muiTableBodyRowProps: ({ row }) => ({
|
muiTableBodyRowProps: ({ row }) => ({
|
||||||
onClick: () => handleClickRowCell(row.id),
|
onClick: () => handleClickRowCell(row.id),
|
||||||
hover: false,
|
hover: false,
|
||||||
|
style: { height: TABLE_ROW_HEIGHT },
|
||||||
sx: {
|
sx: {
|
||||||
'& > td::after': {
|
'& > td::after': {
|
||||||
content: row.getIsSelected() ? '""' : 'none',
|
content: row.getIsSelected() ? '""' : 'none',
|
||||||
|
|||||||
@ -1,9 +1,14 @@
|
|||||||
export const TABLE_ROW_HEIGHT = 80;
|
import { getRootFontSizePx } from '../utils/virtualizerOptions';
|
||||||
|
|
||||||
|
// Высота строки листа = 3rem (так было фактически: minHeight/maxHeight ячейки).
|
||||||
|
// rem зависит от ширины окна (App.css: .83vw при ширине <= 1920px), поэтому в px высота
|
||||||
|
// вычисляется в момент вызова. Виртуализатор строк не читает layout (measureElement = константа),
|
||||||
|
// значит стили строки/ячейки и эта высота обязаны совпадать.
|
||||||
|
export const TABLE_ROW_HEIGHT_REM = 3;
|
||||||
|
export const TABLE_ROW_HEIGHT = `${TABLE_ROW_HEIGHT_REM}rem`;
|
||||||
|
export const getTableRowHeightPx = () => TABLE_ROW_HEIGHT_REM * getRootFontSizePx();
|
||||||
|
|
||||||
export const BASE_TABLE_CONFIG = {
|
export const BASE_TABLE_CONFIG = {
|
||||||
muiTableRowProps: {
|
|
||||||
sx: { height: '5rem' },
|
|
||||||
},
|
|
||||||
enableExpanding: true,
|
enableExpanding: true,
|
||||||
enableStickyHeader: true,
|
enableStickyHeader: true,
|
||||||
enableColumnPinning: true,
|
enableColumnPinning: true,
|
||||||
@ -40,8 +45,8 @@ export const getTableHeadCellStyles = () => ({
|
|||||||
whiteSpace: 'auto',
|
whiteSpace: 'auto',
|
||||||
wordBreak: 'normal',
|
wordBreak: 'normal',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
minHeight: '3rem',
|
minHeight: TABLE_ROW_HEIGHT,
|
||||||
maxHeight: '3rem',
|
maxHeight: TABLE_ROW_HEIGHT,
|
||||||
border: '1px solid #E6E6E6',
|
border: '1px solid #E6E6E6',
|
||||||
fontSize: '11px',
|
fontSize: '11px',
|
||||||
fontFamily: 'Calibri, Arial, sans-serif',
|
fontFamily: 'Calibri, Arial, sans-serif',
|
||||||
@ -56,6 +61,8 @@ export const getTableBodyCellProps = ({ column, table }) => {
|
|||||||
sx: {
|
sx: {
|
||||||
...getTableHeadCellStyles().sx,
|
...getTableHeadCellStyles().sx,
|
||||||
fontSize: '1rem',
|
fontSize: '1rem',
|
||||||
|
height: TABLE_ROW_HEIGHT,
|
||||||
|
overflow: 'hidden',
|
||||||
...(isPinned && { zIndex: 5 }),
|
...(isPinned && { zIndex: 5 }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { HeaderSwitch } from '../../components/HeaderMenu/HeaderSwitch';
|
|||||||
import { PrimaryButton } from '../../components/common/Buttons/Buttons';
|
import { PrimaryButton } from '../../components/common/Buttons/Buttons';
|
||||||
import DenominationSelect from '../../components/common/DenominationSelect';
|
import DenominationSelect from '../../components/common/DenominationSelect';
|
||||||
import useDenomination from '../../components/common/useDenomination';
|
import useDenomination from '../../components/common/useDenomination';
|
||||||
|
import { createFixedRowVirtualizerOptions, getRootFontSizePx } from '../../components/RealtimeTable/utils/virtualizerOptions';
|
||||||
import { useSvod } from '../SvodPage/SvodContext';
|
import { useSvod } from '../SvodPage/SvodContext';
|
||||||
import { SvodFilters } from '../SvodPage/SvodFilters';
|
import { SvodFilters } from '../SvodPage/SvodFilters';
|
||||||
|
|
||||||
@ -21,12 +22,13 @@ const createInitialTableState = () =>
|
|||||||
const QUARTERS = [1, 2, 3, 4];
|
const QUARTERS = [1, 2, 3, 4];
|
||||||
const tableSize = (rem) => rem * 16;
|
const tableSize = (rem) => rem * 16;
|
||||||
const numberFormatter = new Intl.NumberFormat('ru-RU', { maximumFractionDigits: 2 });
|
const numberFormatter = new Intl.NumberFormat('ru-RU', { maximumFractionDigits: 2 });
|
||||||
const ROW_HEIGHT = 37;
|
// Высота строки задана в rem явно (строка и ячейка), виртуализатор layout не читает.
|
||||||
const ROW_VIRTUALIZER_OPTIONS = {
|
const ROW_HEIGHT_REM = 2.75;
|
||||||
overscan: 8,
|
const ROW_HEIGHT = `${ROW_HEIGHT_REM}rem`;
|
||||||
estimateSize: () => ROW_HEIGHT,
|
const ROW_VIRTUALIZER_OPTIONS = createFixedRowVirtualizerOptions({
|
||||||
measureElement: (element) => element?.offsetHeight || ROW_HEIGHT,
|
rowHeight: () => ROW_HEIGHT_REM * getRootFontSizePx(),
|
||||||
};
|
overscan: 3,
|
||||||
|
});
|
||||||
const COLUMN_BAND_COLORS = {
|
const COLUMN_BAND_COLORS = {
|
||||||
head: ['#f8f9fa', '#f1f7f3'],
|
head: ['#f8f9fa', '#f1f7f3'],
|
||||||
body: ['#ffffff', '#f8fbf9'],
|
body: ['#ffffff', '#f8fbf9'],
|
||||||
@ -532,8 +534,12 @@ export default function Svod2Page() {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
muiTableHeadRowProps: { sx: { boxShadow: 'none' } },
|
muiTableHeadRowProps: { sx: { boxShadow: 'none' } },
|
||||||
|
muiTableBodyRowProps: { style: { height: ROW_HEIGHT } },
|
||||||
muiTableBodyCellProps: ({ column }) => ({
|
muiTableBodyCellProps: ({ column }) => ({
|
||||||
sx: {
|
sx: {
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
height: ROW_HEIGHT,
|
||||||
|
overflow: 'hidden',
|
||||||
backgroundColor: COLUMN_BAND_COLORS.body[columnBands.get(column.id) ?? 0],
|
backgroundColor: COLUMN_BAND_COLORS.body[columnBands.get(column.id) ?? 0],
|
||||||
borderRight: columnGroupEnds.has(column.id) ? '0.1875rem solid #9eafa3' : '0.0625rem solid #edf0f2',
|
borderRight: columnGroupEnds.has(column.id) ? '0.1875rem solid #9eafa3' : '0.0625rem solid #edf0f2',
|
||||||
fontSize: '0.8125rem',
|
fontSize: '0.8125rem',
|
||||||
|
|||||||
@ -5,13 +5,16 @@ import useDenomination from '../../components/common/useDenomination';
|
|||||||
import { blueColumn, greenColumn, orangeColumn } from '../../components/RealtimeTable/constants/columnColors';
|
import { blueColumn, greenColumn, orangeColumn } from '../../components/RealtimeTable/constants/columnColors';
|
||||||
import { sectionCodeColor } from '../../components/RealtimeTable/constants/columnConfig';
|
import { sectionCodeColor } from '../../components/RealtimeTable/constants/columnConfig';
|
||||||
import { buildRowHierarchy } from '../../components/RealtimeTable/utils/rowUtils';
|
import { buildRowHierarchy } from '../../components/RealtimeTable/utils/rowUtils';
|
||||||
|
import { createFixedRowVirtualizerOptions, getRootFontSizePx } from '../../components/RealtimeTable/utils/virtualizerOptions';
|
||||||
|
|
||||||
const tableSize = (rem) => rem * 16;
|
const tableSize = (rem) => rem * 16;
|
||||||
const ROW_VIRTUALIZER_OPTIONS = {
|
// Высота строки задана в rem явно (строка и ячейка), виртуализатор layout не читает.
|
||||||
|
const ROW_HEIGHT_REM = 2.25;
|
||||||
|
const ROW_HEIGHT = `${ROW_HEIGHT_REM}rem`;
|
||||||
|
const ROW_VIRTUALIZER_OPTIONS = createFixedRowVirtualizerOptions({
|
||||||
|
rowHeight: () => ROW_HEIGHT_REM * getRootFontSizePx(),
|
||||||
overscan: 8,
|
overscan: 8,
|
||||||
estimateSize: () => 37,
|
});
|
||||||
measureElement: (element) => element?.offsetHeight || 37,
|
|
||||||
};
|
|
||||||
|
|
||||||
const SOURCE_COLORS = { ahr: greenColumn, oper: blueColumn, cap: orangeColumn };
|
const SOURCE_COLORS = { ahr: greenColumn, oper: blueColumn, cap: orangeColumn };
|
||||||
|
|
||||||
@ -157,6 +160,7 @@ export const SummaryTable = memo(function SummaryTable({ columns, data, loading,
|
|||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
muiTableBodyRowProps: { style: { height: ROW_HEIGHT } },
|
||||||
muiTableBodyCellProps: ({ row, column }) => {
|
muiTableBodyCellProps: ({ row, column }) => {
|
||||||
const backgroundColor = getSummaryRowColor(row, colorBySource);
|
const backgroundColor = getSummaryRowColor(row, colorBySource);
|
||||||
return {
|
return {
|
||||||
@ -167,6 +171,9 @@ export const SummaryTable = memo(function SummaryTable({ columns, data, loading,
|
|||||||
fontSize: '0.8125rem',
|
fontSize: '0.8125rem',
|
||||||
px: column.id === 'mrt-row-expand' ? '0.25rem' : '0.75rem',
|
px: column.id === 'mrt-row-expand' ? '0.25rem' : '0.75rem',
|
||||||
py: column.id === 'mrt-row-expand' ? 0 : '0.5rem',
|
py: column.id === 'mrt-row-expand' ? 0 : '0.5rem',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
height: ROW_HEIGHT,
|
||||||
|
overflow: 'hidden',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
textAlign: ['section_code', 'name'].includes(column.id) ? 'left' : 'right',
|
textAlign: ['section_code', 'name'].includes(column.id) ? 'left' : 'right',
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user