fix(web): сводка, догруженная при уходе с ОСВ, не кешируется (M-9)

Сводка живёт только в состоянии ожидающего перехода; при summary=null запрашивается заново.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-27 22:24:39 +04:00
parent 2bb5683cde
commit 7c523b93d1

View File

@ -70,7 +70,8 @@ export function OsvTabs({ summary, versionId, status }: Props) {
const navigate = useNavigate();
const location = useLocation();
const { tab } = useParams<{ tab?: string }>();
const [pending, setPending] = useState<string | null>(null);
// переход, ожидающий решения в модалке; сводка — та, по которой модалка показана (только на время модалки)
const [pending, setPending] = useState<{ key: string; summary: OsvSummaryOut | null } | null>(null);
const activeKey = tab || 'osv';
@ -79,12 +80,7 @@ export function OsvTabs({ summary, versionId, status }: Props) {
navigate(to, options);
};
// сводка, догруженная при уходе, пока страница её не передала (или запрос страницы упал); привязана к версии
const [fetched, setFetched] = useState<{ versionId: string; summary: OsvSummaryOut } | null>(null);
const [checking, setChecking] = useState(false);
const fetchedSummary = fetched?.versionId === versionId ? fetched.summary : null;
const known = summary ?? fetchedSummary;
const shownPairs = known?.counter_pairs ?? [];
// актуальные версия и признак «компонент жив» — ответ запроса, пришедший после смены версии/размонтирования, игнорируется
const liveRef = useRef({ versionId, mounted: true });
@ -104,7 +100,7 @@ export function OsvTabs({ summary, versionId, status }: Props) {
return;
}
const storage = safeSessionStorage();
let found: OsvSummaryOut | null = known;
let found: OsvSummaryOut | null = summary;
let decision: 'warn' | 'go' | 'perform' = decideOsvLeave({ summary: found, versionId, status, storage });
if (decision === 'perform') {
setChecking(true);
@ -118,13 +114,12 @@ export function OsvTabs({ summary, versionId, status }: Props) {
if (!liveRef.current.mounted) return;
setChecking(false);
if (liveRef.current.versionId !== requestedFor) return;
if (result) setFetched({ versionId: requestedFor, summary: result });
found = result;
decision = resolveLeaveAfterFetch({ summary: result, versionId, status, storage });
}
if (decision === 'warn' && found) {
rememberCounterPairsShown(versionId, found.counter_pairs, storage);
setPending(newKey);
setPending({ key: newKey, summary: found });
} else {
go(newKey);
}
@ -162,8 +157,8 @@ export function OsvTabs({ summary, versionId, status }: Props) {
/>
<CounterPairsModal
open={pending !== null}
pairs={shownPairs}
unmappedTotal={known?.unmapped_total ?? 0}
pairs={pending?.summary?.counter_pairs ?? []}
unmappedTotal={pending?.summary?.unmapped_total ?? 0}
onShow={() => {
setPending(null);
navigate(
@ -173,7 +168,7 @@ export function OsvTabs({ summary, versionId, status }: Props) {
}}
onStay={() => setPending(null)}
onGo={() => {
const next = pending;
const next = pending?.key;
setPending(null);
if (next) go(next);
}}