fix: avoid batch upload storage crash
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-05-09 17:15:24 +08:00
parent f99ca7e49d
commit 3a4aece308

View File

@ -54,6 +54,7 @@ const BATCH_REQUEST_STAGGER_MS = 700;
const BATCH_PARALLEL_WORKER_COUNT = 4;
const MULTI_PRODUCT_FAILOVER_MAX_ROUNDS = 5;
const MULTI_PRODUCT_FAILOVER_RETRY_DELAY_MS = 1500;
const PERSISTED_IMAGE_MAX_LENGTH = 200_000;
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
@ -104,6 +105,72 @@ type SceneFusionPersistedState = {
selectedResultIds: string[];
};
function isPersistableImageValue(value: unknown): value is string {
if (typeof value !== "string") return false;
const normalized = value.trim();
if (!normalized) return false;
if (normalized.startsWith("blob:")) return false;
if (normalized.startsWith("data:")) return false;
return normalized.length <= PERSISTED_IMAGE_MAX_LENGTH;
}
function toPersistableImageValue(value: unknown) {
return isPersistableImageValue(value) ? value.trim() : "";
}
function toPersistableItems(items: ProcessItem[]) {
const persistableItems: ProcessItem[] = [];
for (const item of items) {
const image = toPersistableImageValue(item.image);
const result = toPersistableImageValue(item.result);
const originalUrl = toPersistableImageValue(item.originalUrl);
if (!image && !result && !originalUrl) continue;
const persistableItem: ProcessItem = {
...item,
image: image || result || originalUrl,
};
if (result) {
persistableItem.result = result;
} else {
delete persistableItem.result;
}
if (originalUrl) {
persistableItem.originalUrl = originalUrl;
} else {
delete persistableItem.originalUrl;
}
persistableItems.push(persistableItem);
}
return persistableItems;
}
function createPersistableSnapshot(snapshot: SceneFusionPersistedState): SceneFusionPersistedState {
const sceneItems = toPersistableItems(snapshot.sceneItems);
const multiProductItems = toPersistableItems(snapshot.multiProductItems);
const randomItems = toPersistableItems(snapshot.randomItems);
const batchItems = toPersistableItems(snapshot.batchItems);
const persistedIds = new Set(
[...sceneItems, ...multiProductItems, ...randomItems, ...batchItems].map(
(item) => item.id
)
);
return {
...snapshot,
productImage: toPersistableImageValue(snapshot.productImage) || null,
sceneItems,
multiProductItems,
referenceSceneImage:
toPersistableImageValue(snapshot.referenceSceneImage) || null,
randomItems,
batchItems,
selectedResultIds: snapshot.selectedResultIds.filter((id) =>
persistedIds.has(id)
),
};
}
const randomBackgroundStyles = [
"现代简约客厅",
"北欧卧室",
@ -539,7 +606,19 @@ export function SceneFusionView({
selectedResultIds,
};
window.sessionStorage.setItem(persistenceKey, JSON.stringify(snapshot));
try {
window.sessionStorage.setItem(
persistenceKey,
JSON.stringify(createPersistableSnapshot(snapshot))
);
} catch (error) {
console.warn("[SceneFusionView] Failed to persist state:", error);
try {
window.sessionStorage.removeItem(persistenceKey);
} catch {
// Ignore storage cleanup failures.
}
}
}, [
aspectRatio,
batchItems,