From 1360959e26859142cbf306d4a0f1706044bb08d1 Mon Sep 17 00:00:00 2001 From: "gorbenko.pavel" Date: Fri, 25 Sep 2026 15:58:04 +0500 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=80=D0=B0=D1=81=D1=85=D0=BE=D0=B6=D0=B4=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D1=87=D1=91=D1=82=D1=87=D0=B8=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B8=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=20=D0=B2=20?= =?UTF-8?q?=C2=AB=D0=92=D1=81=D0=B5=20=D0=B7=D0=B0=D1=8F=D0=B2=D0=BA=D0=B8?= =?UTF-8?q?=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getAllRequestsForType брал totalRows из сырого ответа Search (RowLimit/ StartRow), а строки — из hitsToEntries, который дедуплицирует хиты по (тип, Id): TrimDuplicates:false намеренно допускает, что индекс отдаст один и тот же элемент несколько раз. Счётчик над таблицей поэтому мог быть больше числа видимых строк. Теперь берём весь срез разом (fetchAllSearchRows), дедуп и оба числа считаются по одному и тому же набору. Co-Authored-By: Claude Sonnet 5 --- .../features/myRequests/myRequests.service.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/webparts/requestPortal/features/myRequests/myRequests.service.ts b/src/webparts/requestPortal/features/myRequests/myRequests.service.ts index e28178c..74ee956 100644 --- a/src/webparts/requestPortal/features/myRequests/myRequests.service.ts +++ b/src/webparts/requestPortal/features/myRequests/myRequests.service.ts @@ -1381,6 +1381,14 @@ export async function searchOwnRequests( // searchOwnRequests — без фильтра по автору, и только ОДИН тип (раздел уже // показывает конкретный выбранный тип, а не все связанные разом). Только // Search, без REST-подстраховки на свежесть — как и у searchOwnRequests. +// +// Весь найденный срез целиком (fetchAllSearchRows), а не постранично через +// Search RowLimit/StartRow: totalRows там был бы сырым счётчиком индекса ДО +// дедупа по (тип, Id) (см. hitsToEntries — TrimDuplicates:false намеренно, и +// индекс может вернуть один и тот же элемент несколькими хитами), и на +// странице оказывалось МЕНЬШЕ строк, чем показывал счётчик над таблицей. +// Тип здесь только один — набор в разумных пределах, дедуп и сортировка идут +// по всему сразу, страница нарезается уже в памяти. export async function getAllRequestsForType( context: WebPartContext, type: IRequestType, @@ -1393,23 +1401,15 @@ export async function getAllRequestsForType( if (text) clauses.push(text); const kql = clauses.join(' AND '); - const results = await traced('Search: все заявки типа', () => - sp.search({ - Querytext: kql, - RowLimit: PAGE_SIZE, - StartRow: (page - 1) * PAGE_SIZE, - SelectProperties: OWN_SELECT_PROPERTIES, - TrimDuplicates: false, - SortList: [{ Property: 'Created', Direction: 1 }], - }) + const hits = await traced('Search: все заявки типа', () => + fetchAllSearchRows(sp, kql, OWN_SELECT_PROPERTIES, 'Все заявки типа', [{ Property: 'Created', Direction: 1 }]) ); - const totalRows = results.TotalRows || 0; // kind: 'other' — заявка не обязательно текущего пользователя, открывается // только на просмотр (см. IMyRequest.kind, openRequest в RequestPortal.tsx). - const rows = hitsToEntries(results, [type]).map((e) => toMyRequestFromSearch(e, 'other')); + const rows = hitsToEntries({ PrimarySearchResults: hits }, [type]).map((e) => toMyRequestFromSearch(e, 'other')); - return { rows, totalRows }; + return { rows: rows.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE), totalRows: rows.length }; } // Свои заявки с конкретным статусом ЗАЯВКИ (не строки маршрута) — «Доработка»