From 5c9e62a1654cb74e04c734c49dc0914b891e4996 Mon Sep 17 00:00:00 2001 From: hh <2587203630@qq.com> Date: Wed, 8 Jul 2026 16:21:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A7=86=E9=A2=91=E9=A1=B9=E7=9B=AE-?= =?UTF-8?q?=E5=88=86=E9=95=9C=E8=84=9A=E6=9C=AC=E5=88=A0=E9=99=A4=E6=97=B6?= =?UTF-8?q?=E5=9B=9E=E6=98=BE=E4=B8=80=E4=B8=8B=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/frontend/src/routes/pipeline.tsx | 29 +++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/core/frontend/src/routes/pipeline.tsx b/core/frontend/src/routes/pipeline.tsx index 9d81612..b193f63 100644 --- a/core/frontend/src/routes/pipeline.tsx +++ b/core/frontend/src/routes/pipeline.tsx @@ -1283,19 +1283,22 @@ export function PipelinePage(props: { function persistPending(next: Set) { try { localStorage.setItem(`airshelf:pending-del:${project.id}`, JSON.stringify([...next])); } catch { /* localStorage 不可用就算了 */ } } - function dropPending(id: string) { + function stopDeleteRetry(id: string) { delRetryingRef.current.delete(id); + } + function dropPending(id: string) { + stopDeleteRetry(id); setPendingDeletes((prev) => { if (!prev.has(id)) return prev; const next = new Set(prev); next.delete(id); persistPending(next); return next; }); } async function runDeleteRetry(shotId: string, attempt: number) { try { await api.deleteScriptSegment(project.id, { segment_id: shotId }); - dropPending(shotId); + stopDeleteRetry(shotId); void onRefreshProject(); // 后端已删 → 拉回最新(re-sort 后的镜号) } catch (e) { const status = e instanceof ApiError ? e.status : 0; - if (status === 404) { dropPending(shotId); void onRefreshProject(); return; } // 本来就没了 = 删成 - if (status >= 400 && status < 500) { console.warn("删除被拒(非网络),停重试但按要求不回滚:", status, shotId); delRetryingRef.current.delete(shotId); return; } + if (status === 404) { stopDeleteRetry(shotId); void onRefreshProject(); return; } // 本来就没了 = 删成 + if (status >= 400 && status < 500) { console.warn("删除被拒(非网络),停重试但按要求不回滚:", status, shotId); stopDeleteRetry(shotId); return; } // 网络/5xx → 退避重试(最长 30s),扛到删成 const delay = Math.min(30000, 1000 * 2 ** Math.min(attempt, 5)); window.setTimeout(() => { void runDeleteRetry(shotId, attempt + 1); }, delay); @@ -1320,6 +1323,24 @@ export function PipelinePage(props: { ids.forEach((id) => ensureDeleteRetry(id)); // eslint-disable-next-line react-hooks/exhaustive-deps }, [project.id]); + useEffect(() => { + if (!currentScript || pendingDeletes.size === 0) return; + const liveIds = new Set((currentScript.segments ?? []).map((segment) => segment.id)); + setPendingDeletes((prev) => { + let changed = false; + const next = new Set(prev); + prev.forEach((id) => { + if (!liveIds.has(id)) { + stopDeleteRetry(id); + next.delete(id); + changed = true; + } + }); + if (changed) persistPending(next); + return changed ? next : prev; + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentScript, pendingDeletes]); useEffect(() => { if (!armedDelete) return; const timer = window.setTimeout(() => setArmedDelete(null), 3000);