diff --git a/web/src/components/RealtimeTable/RealtimeTable.jsx b/web/src/components/RealtimeTable/RealtimeTable.jsx index 539e4b3..7aded64 100644 --- a/web/src/components/RealtimeTable/RealtimeTable.jsx +++ b/web/src/components/RealtimeTable/RealtimeTable.jsx @@ -16,7 +16,8 @@ import { CreateProgramModal } from './Modals/CreateProgramProjectModal'; import { SelectExpenseItemModal } from './Modals/SelectExpenseItemModal'; import { SelectVspModal } from './Modals/SelectVspModal'; 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 { useColumnSettings } from './hooks/useColumnSettings'; import { useHeaderPortal } from './hooks/useHeaderPortal'; @@ -34,13 +35,11 @@ import useDenomination from '../common/useDenomination'; const CONFIG_CACHE = new Map(); -const ROW_VIRTUALIZER_OPTIONS = { +const ROW_VIRTUALIZER_OPTIONS = createFixedRowVirtualizerOptions({ + rowHeight: getTableRowHeightPx, overscan: 5, - scrollPaddingStart: 0, - scrollPaddingEnd: 0, - estimateSize: () => TABLE_ROW_HEIGHT, - measureElement: (element) => element?.offsetHeight || TABLE_ROW_HEIGHT, -}; + extra: { scrollPaddingStart: 0, scrollPaddingEnd: 0 }, +}); const hasVspDropdown = (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 }) => ({ onClick: () => handleClickRowCell(row.id), hover: false, + style: { height: TABLE_ROW_HEIGHT }, sx: { '& > td::after': { content: row.getIsSelected() ? '""' : 'none', diff --git a/web/src/components/RealtimeTable/constants/tableConfig.js b/web/src/components/RealtimeTable/constants/tableConfig.js index 0df3d06..0c0aa17 100644 --- a/web/src/components/RealtimeTable/constants/tableConfig.js +++ b/web/src/components/RealtimeTable/constants/tableConfig.js @@ -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 = { - muiTableRowProps: { - sx: { height: '5rem' }, - }, enableExpanding: true, enableStickyHeader: true, enableColumnPinning: true, @@ -40,8 +45,8 @@ export const getTableHeadCellStyles = () => ({ whiteSpace: 'auto', wordBreak: 'normal', boxSizing: 'border-box', - minHeight: '3rem', - maxHeight: '3rem', + minHeight: TABLE_ROW_HEIGHT, + maxHeight: TABLE_ROW_HEIGHT, border: '1px solid #E6E6E6', fontSize: '11px', fontFamily: 'Calibri, Arial, sans-serif', @@ -56,6 +61,8 @@ export const getTableBodyCellProps = ({ column, table }) => { sx: { ...getTableHeadCellStyles().sx, fontSize: '1rem', + height: TABLE_ROW_HEIGHT, + overflow: 'hidden', ...(isPinned && { zIndex: 5 }), }, }; diff --git a/web/src/pages/Svod2Page/Svod2Page.jsx b/web/src/pages/Svod2Page/Svod2Page.jsx index 76bd120..eb76b8d 100644 --- a/web/src/pages/Svod2Page/Svod2Page.jsx +++ b/web/src/pages/Svod2Page/Svod2Page.jsx @@ -9,6 +9,7 @@ import { HeaderSwitch } from '../../components/HeaderMenu/HeaderSwitch'; import { PrimaryButton } from '../../components/common/Buttons/Buttons'; import DenominationSelect from '../../components/common/DenominationSelect'; import useDenomination from '../../components/common/useDenomination'; +import { createFixedRowVirtualizerOptions, getRootFontSizePx } from '../../components/RealtimeTable/utils/virtualizerOptions'; import { useSvod } from '../SvodPage/SvodContext'; import { SvodFilters } from '../SvodPage/SvodFilters'; @@ -21,12 +22,13 @@ const createInitialTableState = () => const QUARTERS = [1, 2, 3, 4]; const tableSize = (rem) => rem * 16; const numberFormatter = new Intl.NumberFormat('ru-RU', { maximumFractionDigits: 2 }); -const ROW_HEIGHT = 37; -const ROW_VIRTUALIZER_OPTIONS = { - overscan: 8, - estimateSize: () => ROW_HEIGHT, - measureElement: (element) => element?.offsetHeight || ROW_HEIGHT, -}; +// Высота строки задана в rem явно (строка и ячейка), виртуализатор layout не читает. +const ROW_HEIGHT_REM = 2.75; +const ROW_HEIGHT = `${ROW_HEIGHT_REM}rem`; +const ROW_VIRTUALIZER_OPTIONS = createFixedRowVirtualizerOptions({ + rowHeight: () => ROW_HEIGHT_REM * getRootFontSizePx(), + overscan: 3, +}); const COLUMN_BAND_COLORS = { head: ['#f8f9fa', '#f1f7f3'], body: ['#ffffff', '#f8fbf9'], @@ -532,8 +534,12 @@ export default function Svod2Page() { }, }), muiTableHeadRowProps: { sx: { boxShadow: 'none' } }, + muiTableBodyRowProps: { style: { height: ROW_HEIGHT } }, muiTableBodyCellProps: ({ column }) => ({ sx: { + boxSizing: 'border-box', + height: ROW_HEIGHT, + overflow: 'hidden', backgroundColor: COLUMN_BAND_COLORS.body[columnBands.get(column.id) ?? 0], borderRight: columnGroupEnds.has(column.id) ? '0.1875rem solid #9eafa3' : '0.0625rem solid #edf0f2', fontSize: '0.8125rem', diff --git a/web/src/pages/SvodPage/SummaryTable.jsx b/web/src/pages/SvodPage/SummaryTable.jsx index eb41a65..fc2b68e 100644 --- a/web/src/pages/SvodPage/SummaryTable.jsx +++ b/web/src/pages/SvodPage/SummaryTable.jsx @@ -5,13 +5,16 @@ import useDenomination from '../../components/common/useDenomination'; import { blueColumn, greenColumn, orangeColumn } from '../../components/RealtimeTable/constants/columnColors'; import { sectionCodeColor } from '../../components/RealtimeTable/constants/columnConfig'; import { buildRowHierarchy } from '../../components/RealtimeTable/utils/rowUtils'; +import { createFixedRowVirtualizerOptions, getRootFontSizePx } from '../../components/RealtimeTable/utils/virtualizerOptions'; 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, - estimateSize: () => 37, - measureElement: (element) => element?.offsetHeight || 37, -}; +}); const SOURCE_COLORS = { ahr: greenColumn, oper: blueColumn, cap: orangeColumn }; @@ -157,6 +160,7 @@ export const SummaryTable = memo(function SummaryTable({ columns, data, loading, boxShadow: 'none', }, }, + muiTableBodyRowProps: { style: { height: ROW_HEIGHT } }, muiTableBodyCellProps: ({ row, column }) => { const backgroundColor = getSummaryRowColor(row, colorBySource); return { @@ -167,6 +171,9 @@ export const SummaryTable = memo(function SummaryTable({ columns, data, loading, fontSize: '0.8125rem', px: column.id === 'mrt-row-expand' ? '0.25rem' : '0.75rem', py: column.id === 'mrt-row-expand' ? 0 : '0.5rem', + boxSizing: 'border-box', + height: ROW_HEIGHT, + overflow: 'hidden', whiteSpace: 'nowrap', textAlign: ['section_code', 'name'].includes(column.id) ? 'left' : 'right', },