fix(svod2): заголовок без виртуализации колонок, группы над своими колонками
MRT при виртуализации колонок рисует каждую строку заголовка по индексам листовых колонок, из-за чего двухуровневые группы разъезжались. Штатный thead отключён (enableTableHead: false), тот же MRT_TableHead без columnVirtualizer вставляется порталом в <table>: все заголовки сразу, стили и встроенные фильтры MRT сохраняются. Тело по-прежнему виртуализировано по строкам и колонкам. Стили: order -1 для портального thead, flexShrink 0 у td/th (распорки виртуализации сжимались и сдвигали тело на 2-8 px), скрыта подложка ::before закреплённых ячеек (перекрывала чередование фона). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b834f1008d
commit
4cb0862ca5
@ -1,8 +1,9 @@
|
||||
import RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';
|
||||
import { Alert, Box, Button, Paper, Tab, Tabs, Typography } from '@mui/material';
|
||||
import { MaterialReactTable, useMaterialReactTable } from 'material-react-table';
|
||||
import { MRT_TableHead, MaterialReactTable, useMaterialReactTable } from 'material-react-table';
|
||||
import { MRT_Localization_RU } from 'material-react-table/locales/ru';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { HeaderSwitch } from '../../components/HeaderMenu/HeaderSwitch';
|
||||
@ -298,6 +299,8 @@ export default function Svod2Page() {
|
||||
const navigate = useNavigate();
|
||||
const { getSheetFilters, updateSheetFilters, getSummary, invalidateSummary } = useSvod();
|
||||
const [sheet, setSheet] = useState('GO');
|
||||
// <table> MRT: заголовок рисуем сами через портал (см. комментарий у enableTableHead).
|
||||
const [tableElement, setTableElement] = useState(null);
|
||||
const denominationStorageKey = `svod2_${sheet}_denomination`;
|
||||
const { denomination, setDenomination: handleDenominationChange, divisor } = useDenomination(denominationStorageKey);
|
||||
const [tableStateBySheet, setTableStateBySheet] = useState(createInitialTableState);
|
||||
@ -406,6 +409,11 @@ export default function Svod2Page() {
|
||||
enablePagination: false,
|
||||
enableRowVirtualization: true,
|
||||
enableColumnVirtualization: true,
|
||||
// Заголовок MRT при виртуализации колонок рисует строки по индексам листовых колонок,
|
||||
// и группы (colSpan) разъезжаются. Поэтому штатный thead отключён, а тот же MRT_TableHead
|
||||
// без columnVirtualizer (все заголовки сразу) вставляется в <table> порталом.
|
||||
enableTableHead: false,
|
||||
muiTableProps: { ref: setTableElement },
|
||||
...SVOD2_LAYOUT_OPTIONS,
|
||||
columnVirtualizerOptions: getSvod2ColumnVirtualizerOptions,
|
||||
enableTopToolbar: false,
|
||||
@ -446,7 +454,12 @@ export default function Svod2Page() {
|
||||
noRecordsToDisplay: 'Нет данных для выбранных параметров',
|
||||
},
|
||||
});
|
||||
let content = <MaterialReactTable table={table} />;
|
||||
let content = (
|
||||
<>
|
||||
<MaterialReactTable table={table} />
|
||||
{tableElement && createPortal(<MRT_TableHead table={table} />, tableElement)}
|
||||
</>
|
||||
);
|
||||
if (!hasCurrentData && !loading && !error) {
|
||||
content = (
|
||||
<Alert severity='info'>
|
||||
|
||||
@ -57,8 +57,11 @@ export const SVOD2_TABLE_CONTAINER_SX = {
|
||||
overflow: 'auto',
|
||||
minHeight: 0,
|
||||
height: '100%',
|
||||
'& thead': { position: 'sticky', top: 0, zIndex: 10 },
|
||||
// order: -1 — thead вставлен порталом в конец <table> (grid), а должен идти до tbody.
|
||||
'& thead': { position: 'sticky', top: 0, zIndex: 10, order: -1 },
|
||||
'& td': {
|
||||
// Распорки виртуализации колонок (td с inline width) не должны сжиматься во flex-строке.
|
||||
flexShrink: 0,
|
||||
backgroundColor: '#ffffff',
|
||||
borderRight: '0.0625rem solid #edf0f2',
|
||||
fontSize: '0.8125rem',
|
||||
@ -70,6 +73,7 @@ export const SVOD2_TABLE_CONTAINER_SX = {
|
||||
'& td.svod2-group-end': { borderRight: GROUP_END_BORDER },
|
||||
'& td[data-pinned="true"]': { zIndex: 2 },
|
||||
'& th': {
|
||||
flexShrink: 0,
|
||||
position: 'sticky',
|
||||
top: 0,
|
||||
boxShadow: 'none',
|
||||
@ -86,6 +90,8 @@ export const SVOD2_TABLE_CONTAINER_SX = {
|
||||
'& th.svod2-band-1': { backgroundColor: '#f1f7f3' },
|
||||
'& th.svod2-group-end': { borderRight: GROUP_END_BORDER },
|
||||
'& th[data-pinned="true"]': { zIndex: 5 },
|
||||
// enableColumnPinning добавляет закреплённым ячейкам подложку ::before (z-index -1), она перекрывает чередование фона.
|
||||
'& td[data-pinned="true"]::before, & th[data-pinned="true"]::before': { display: 'none' },
|
||||
'& .svod2-badge': {
|
||||
display: 'inline-block',
|
||||
padding: '0.25rem 0.625rem',
|
||||
|
||||
@ -71,3 +71,10 @@ test('column virtualization layout uses grid-no-grow and column pinning', () =>
|
||||
assert.equal(SVOD2_LAYOUT_OPTIONS.layoutMode, 'grid-no-grow');
|
||||
assert.equal(SVOD2_LAYOUT_OPTIONS.enableColumnPinning, true);
|
||||
});
|
||||
|
||||
test('container styles keep spacers unshrunk, hide pinned overlay and order portal thead first', () => {
|
||||
assert.equal(SVOD2_TABLE_CONTAINER_SX['& td'].flexShrink, 0);
|
||||
assert.equal(SVOD2_TABLE_CONTAINER_SX['& th'].flexShrink, 0);
|
||||
assert.equal(SVOD2_TABLE_CONTAINER_SX['& thead'].order, -1);
|
||||
assert.equal(SVOD2_TABLE_CONTAINER_SX['& td[data-pinned="true"]::before, & th[data-pinned="true"]::before'].display, 'none');
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user