fix(web): перечитывание файлов гасит индикатор догрузки, OpenSpec files-pagination (AURORA-1816)

Ревью PR #242: перечитывание (опрос, удаление, загрузка, подтверждение)
во время догрузки отбрасывало её ответ, а loadingMore оставался true —
спиннер под списком и в переключателе документа не гас. Теперь
перечитывание сразу сбрасывает флаг догрузки.

useScrollSentinel: biome-ignore для trigger с причиной (переподписка
после новой порции файлов).

OpenSpec files-pagination: «Догрузка списка файлов» (primary-files-ui),
опрос перечитывает все показанные страницы, переключатель документа
догружает список при прокрутке (document-review-ui).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-11-11 13:02:47 +04:00
parent ca19d654da
commit 3cc7b82969
6 changed files with 100 additions and 0 deletions

View File

@ -0,0 +1,36 @@
# Proposal
## Why
AURORA-1816 (PR arm-core #242). Панель «Первичные документы» запрашивала файлы ЮЛ с `limit=100` и не догружала
остальные: в режиме «Все документы организации» у ЮЛ с сотней файлов и больше лишние не видны ни в панели, ни в
переключателе документа на экране проверки, и пользователь не знает, что список неполный. Сервер пагинацию уже
поддерживает (`total`, `offset`, `limit` до 200).
## What Changes
- Панель «Первичные документы»: над списком «Всего N файлов» (`total` ответа); файлы страницами по 200, следующая —
при прокрутке до конца списка.
- Опрос раз в 5 секунд и перечитывание после удаления, загрузки и подтверждения перечитывают все показанные страницы,
список не сворачивается к первой.
- Переключатель «Документ» на экране проверки берёт тот же список: догрузка при прокрутке выпадающего списка, открытый
документ есть в списке, даже если он дальше загруженных страниц.
## Capabilities
### Modified Capabilities
- `primary-files-ui` — новое требование «Догрузка списка файлов»; «Опрос до окончания распознавания» перечитывает все
показанные страницы.
- `document-review-ui` — «Переключатель документа»: догрузка и открытый документ в списке.
## Impact
Только фронт arm-core: `web/src/hooks/useLegalEntityFiles.ts` (перенесён из `widgets/FilesDrawer/`),
`web/src/hooks/useScrollSentinel.ts`, `web/src/services/api/files.ts`, `web/src/widgets/FilesDrawer/*`,
`web/src/layouts/DocumentPage.tsx`. API, DBML, правила `05-domain-rules.md` не меняются.
## Non-goals
- Кнопка «Показать ещё» — выбрана подгрузка при прокрутке (задача допускала оба варианта).
- Серверный поиск и фильтры по файлам.

View File

@ -0,0 +1,22 @@
## MODIFIED Requirements
### Requirement: Переключатель документа
В шапке экрана документа SHALL быть выпадающий список «Документ» с документами файлов того же ЮЛ в той же консолидации,
что и файл открытого документа (файл вне консолидации — все файлы ЮЛ): у пункта имя файла, вторая строка (тип · формат ·
дата) и статус; пункты, которые нельзя открыть, неактивны. Список читается теми же страницами, что панель «Первичные документы»
(требование «Догрузка списка файлов» `primary-files-ui`): следующая — при прокрутке выпадающего списка до конца;
открытый документ SHALL быть в списке и показываться по имени, даже если его файл дальше загруженных страниц. Выбор пункта SHALL открывать `/documents/:document_id`
выбранного документа заменой текущей записи истории браузера, без новой записи: кнопка «Назад» экрана и браузера
возвращает на экран, с которого открыт первый документ, а не к предыдущему выбранному. Если первый документ открыт из
панели «Первичные документы» консолидации, «Назад» SHALL открывать экран консолидации с этой панелью той же организации.
#### Scenario: Назад после перебора документов
- **WHEN** аналитик открыл документ из панели «Первичные документы» организации в карточке консолидации, выбрал в списке
«Документ» подряд ещё два документа и нажал «Назад»
- **THEN** открыт экран консолидации с той же выбранной версией и открытой панелью «Первичные документы» той же
организации
#### Scenario: Документ открыт прямой ссылкой
- **WHEN** документ открыт прямой ссылкой в новой вкладке, аналитик выбрал в списке «Документ» другой документ и нажал
«Назад» экрана
- **THEN** открыт список групп компаний `/groups`

View File

@ -0,0 +1,29 @@
## ADDED Requirements
### Requirement: Догрузка списка файлов
Панель SHALL читать список файлов активного режима (стол или все документы) страницами по 200 (`limit=200&offset=…`,
`MAX_PAGE_LIMIT` бэка): первую — при открытии, следующую — когда аналитик прокрутил список до конца, пока показано
меньше `total`. Над списком SHALL стоять «Всего N файлов» с `total` ответа. Опрос, удаление, загрузка и подтверждение
документа SHALL перечитывать все показанные файлы (столько страниц, сколько было показано), а не только первую.
Перечитывание отменяет идущую догрузку: её ответ не применяется, индикатор догрузки гаснет.
#### Scenario: 450 файлов в режиме «все»
- **WHEN** у ЮЛ 450 файлов, панель открыта в режиме «Все документы организации»
- **THEN** над списком «Всего 450 файлов», показаны первые 200; прокрутка до конца догружает 201–400, ещё одна —
401–450, дальше запросов нет
#### Scenario: Опрос не сворачивает список
- **WHEN** показаны 400 файлов и среди них есть файл в `PROCESSING`
- **THEN** раз в 5 секунд перечитываются обе показанные страницы, после ответа в списке по-прежнему 400 файлов
## MODIFIED Requirements
### Requirement: Опрос до окончания распознавания
Пока панель открыта и среди файлов активного списка (стол или все документы) есть `UPLOADED` или `PROCESSING`, панель
SHALL перечитывать этот список раз в 5 секунд — все показанные страницы, не сворачивая список к первой (требование «Догрузка списка файлов»), и SHALL прекратить опрос, когда таких файлов нет или панель закрыта.
Переключение режима или смена ЮЛ SHALL сбрасывать список и перечитывать его. При закрытии панели карточка версии SHALL
перечитываться (обновить ячейки чек-листа).
#### Scenario: Опрос останавливается
- **WHEN** все файлы активного списка перешли в `PROCESSED` или `ERROR`
- **THEN** запросы списка файлов прекращаются

View File

@ -0,0 +1,10 @@
# Tasks
- [x] 1.1 arm-core `web/src/services/api/files.test.ts` — несколько страниц: перечитывание показанного, догрузка с
позиции, конец по `total`, пустая страница раньше `total`
- [x] 1.2 arm-core `web/src/services/api/files.ts` — `listLegalEntityFiles(offset, limit)`, `listLegalEntityFilesFrom`,
`FILES_PAGE_LIMIT = 200`
- [x] 1.3 arm-core `web/` — хук `useLegalEntityFiles` со страницами, `useScrollSentinel`, «Всего N файлов» в панели,
переключатель документа на экране проверки (PR #242, автор)
- [x] 1.4 Ревью: перечитывание во время догрузки сбрасывает `loadingMore` (иначе спиннер под списком не гаснет);
`biome-ignore` для `trigger` в `useScrollSentinel` с причиной

View File

@ -30,6 +30,8 @@ export function useLegalEntityFiles(legalEntityId: string | null, consolidationI
const setBusy = append ? setLoadingMore : setLoading;
const requestId = ++requestRef.current;
inFlightRef.current = true;
// перечитывание отменяет идущую догрузку: её ответ отбросится, а finally не сбросит флаг чужого запроса
if (!append) setLoadingMore(false);
setBusy(true);
try {
const { items, total } = await listLegalEntityFilesFrom(legalEntityId, consolidationId, from, count);

View File

@ -8,6 +8,7 @@ export function useScrollSentinel(enabled: boolean, trigger: unknown, onReach: (
const ref = useRef<HTMLDivElement | null>(null);
const onReachRef = useRef(onReach);
onReachRef.current = onReach;
// biome-ignore lint/correctness/useExhaustiveDependencies: trigger — переподписка после новой порции: если метка всё ещё на экране, наблюдатель сразу вызовет onReach
useEffect(() => {
const node = ref.current;
if (!enabled || !node) return;