diff --git a/web/src/pages/Svod2Page/Svod2Page.jsx b/web/src/pages/Svod2Page/Svod2Page.jsx
index 149cceb..b2144d2 100644
--- a/web/src/pages/Svod2Page/Svod2Page.jsx
+++ b/web/src/pages/Svod2Page/Svod2Page.jsx
@@ -2,7 +2,7 @@ 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_Localization_RU } from 'material-react-table/locales/ru';
-import { useCallback, useMemo, useRef, useState } from 'react';
+import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { HeaderSwitch } from '../../components/HeaderMenu/HeaderSwitch';
@@ -317,6 +317,7 @@ export default function Svod2Page() {
const tableRef = useRef(null);
const getScrollTop = useCallback(() => tableRef.current?.refs.tableContainerRef.current?.scrollTop ?? 0, []);
+ const [rowHeight, setRowHeight] = useState(ROW_HEIGHT);
const { state, windowRows, padding, facetsMap, load, onScroll } = useSvod2Pages({
sheet,
year,
@@ -324,7 +325,7 @@ export default function Svod2Page() {
queryKey: currentQueryKey,
search,
columnFilters,
- rowHeight: ROW_HEIGHT,
+ rowHeight,
getScrollTop,
});
const { loading, error } = state;
@@ -360,7 +361,7 @@ export default function Svod2Page() {
enableBottomToolbar: false,
enableSorting: false,
getFacetedUniqueValues: (_table, columnId) => () => facetsMapRef.current.get(columnId) ?? EMPTY_FACET_MAP,
- rowVirtualizerOptions: { ...ROW_VIRTUALIZER_OPTIONS, measureElement: () => ROW_HEIGHT, ...padding },
+ rowVirtualizerOptions: { ...ROW_VIRTUALIZER_OPTIONS, estimateSize: () => rowHeight, measureElement: () => rowHeight, ...padding },
state: { isLoading: loading, columnFilters },
initialState: {
columnPinning: { left: ['smeta_type', 'smeta_direction', 'org_name', 'name'] },
@@ -398,6 +399,12 @@ export default function Svod2Page() {
},
});
tableRef.current = table;
+ // Единая высота строки для окна страниц: реальная высота первой строки с данными (по умолчанию ROW_HEIGHT).
+ useLayoutEffect(() => {
+ const element = tableRef.current?.refs.tableContainerRef.current?.querySelector('tbody tr:not([data-svod2-placeholder])');
+ const measured = element ? Math.round(element.offsetHeight) : 0;
+ if (measured > 0 && measured !== rowHeight) setRowHeight(measured);
+ });
let content = ;
if (!hasCurrentData && !loading && !error) {
content = (
@@ -453,7 +460,7 @@ export default function Svod2Page() {
emptyOrganizationsPlaceholder='Выберите ССП/РФ'
allowSelectAll
additionalFilters={}>
- {shouldShowFound({ hasCurrentData, loading, facets: state.facets }) && (
+ {shouldShowFound({ hasCurrentData, loading, facets: state.facets, error }) && (
{`Найдено ${state.facets.search_total.toLocaleString('ru-RU')} из ${state.facets.total.toLocaleString('ru-RU')} строк`}
diff --git a/web/src/pages/Svod2Page/svod2Paging.js b/web/src/pages/Svod2Page/svod2Paging.js
index 0ca4367..93c49f9 100644
--- a/web/src/pages/Svod2Page/svod2Paging.js
+++ b/web/src/pages/Svod2Page/svod2Paging.js
@@ -98,8 +98,16 @@ export function facetsToMaps(result) {
return maps;
}
-export function shouldShowFound({ hasCurrentData, loading, facets }) {
- return Boolean(hasCurrentData) && !loading && !!facets && facets.search_total !== facets.total;
+export function shouldShowFound({ hasCurrentData, loading, facets, error = '' }) {
+ return Boolean(hasCurrentData) && !loading && !error && !!facets && facets.search_total !== facets.total;
+}
+
+// Нужно ли уточнение (refine) при смене поиска/колоночных фильтров: на загруженных данных
+// либо пока для текущего queryKey ещё летит первая загрузка (иначе ответы станут «текущими» по старым условиям).
+export function shouldRefine({ hasCurrentData, loading, pendingQueryKey, queryKey, prevRefineKey, refineKey }) {
+ if (prevRefineKey === refineKey) return false;
+ if (hasCurrentData) return true;
+ return Boolean(loading) && pendingQueryKey === queryKey;
}
export function isPlaceholderRow(row) {
diff --git a/web/src/pages/Svod2Page/svod2Paging.test.js b/web/src/pages/Svod2Page/svod2Paging.test.js
index 07e9c16..ee19dc5 100644
--- a/web/src/pages/Svod2Page/svod2Paging.test.js
+++ b/web/src/pages/Svod2Page/svod2Paging.test.js
@@ -16,6 +16,7 @@ import {
getWindowPages,
getWindowRange,
isPlaceholderRow,
+ shouldRefine,
shouldShowFound,
svod2PagingReducer,
touchPage,
@@ -279,3 +280,18 @@ test('refine поверх load: loading снимает settled нового по
s = svod2PagingReducer(s, { type: 'settled', generation: 2 });
assert.equal(s.loading, false);
});
+
+test('«Найдено» не показывается рядом с ошибкой', () => {
+ assert.equal(shouldShowFound({ hasCurrentData: true, loading: false, error: 'x', facets: { total: 5, search_total: 1 } }), false);
+});
+test('shouldRefine: на загруженных данных при смене условий', () => {
+ const base = { hasCurrentData: true, loading: false, pendingQueryKey: 'q', queryKey: 'q', prevRefineKey: 'a', refineKey: 'b' };
+ assert.equal(shouldRefine(base), true);
+ assert.equal(shouldRefine({ ...base, refineKey: 'a' }), false);
+});
+test('shouldRefine: поиск изменён во время первой загрузки (T12.7)', () => {
+ const base = { hasCurrentData: false, loading: true, pendingQueryKey: 'q', queryKey: 'q', prevRefineKey: 'a', refineKey: 'b' };
+ assert.equal(shouldRefine(base), true);
+ assert.equal(shouldRefine({ ...base, pendingQueryKey: 'old' }), false);
+ assert.equal(shouldRefine({ ...base, loading: false }), false);
+});
diff --git a/web/src/pages/Svod2Page/useSvod2Pages.js b/web/src/pages/Svod2Page/useSvod2Pages.js
index 4f915a8..adbef98 100644
--- a/web/src/pages/Svod2Page/useSvod2Pages.js
+++ b/web/src/pages/Svod2Page/useSvod2Pages.js
@@ -17,6 +17,7 @@ import {
getVisiblePage,
getWindowPages,
getWindowRange,
+ shouldRefine,
svod2PagingReducer,
} from './svod2Paging';
@@ -235,7 +236,17 @@ export function useSvod2Pages({ sheet, year, orgIds, queryKey, search, columnFil
syncWindow();
return;
}
- if (previous.refineKey !== refineKey && hasCurrentData) start('refine');
+ if (
+ shouldRefine({
+ hasCurrentData,
+ loading: sheetState.loading,
+ pendingQueryKey: sheetState.pendingQueryKey,
+ queryKey,
+ prevRefineKey: previous.refineKey,
+ refineKey,
+ })
+ )
+ start('refine');
}, [sheet, refineKey]);
useEffect(() => {