diff --git a/apps/ai-game-creator-shell/src/components/game-distribution/useGameDistributionPublishForm.ts b/apps/ai-game-creator-shell/src/components/game-distribution/useGameDistributionPublishForm.ts index 2723cfc0c..2347ff221 100644 --- a/apps/ai-game-creator-shell/src/components/game-distribution/useGameDistributionPublishForm.ts +++ b/apps/ai-game-creator-shell/src/components/game-distribution/useGameDistributionPublishForm.ts @@ -86,6 +86,18 @@ const COVER_GENERATION_MODEL = IMAGE_MODEL_GPT_IMAGE_2; const COVER_GENERATION_ASPECT_RATIO = '16:9'; const COVER_GENERATION_IMAGE_SIZE = '2K'; +/** 释放一组已登记的预览 blob 地址;重置与卸载共用,避免两处各写一遍。 */ +function revokeTrackedObjectUrls(objectUrls: Set) { + objectUrls.forEach((url) => { + try { + URL.revokeObjectURL(url); + } catch { + // 预览地址释放失败不影响重置 / 卸载。 + } + }); + objectUrls.clear(); +} + function buildPublishProjectContext(manifest: GameCreationAppManifest) { const taskSummary = (manifest.tasks ?? []) .slice(0, 16) @@ -224,7 +236,13 @@ export function useGameDistributionPublishForm({ setGeneratingCover(false); setCoverGenerationPrice(null); setCoverGenerationDetail(''); + // 表单在换项目时重来,封面与截图也必须跟着清:素材是「项目 A 的公开展示物料」, + // 留着会被当成项目 B 的封面 / 截图提交。缓存与预览地址一并回收。 + setCover(null); + setScreenshots([]); setPreviewScreenshot(null); + uploadedAssetCacheRef.current.clear(); + revokeTrackedObjectUrls(objectUrlsRef.current); summaryTouchedRef.current = false; categoryTouchedRef.current = false; @@ -282,14 +300,7 @@ export function useGameDistributionPublishForm({ useEffect(() => { const objectUrls = objectUrlsRef.current; return () => { - objectUrls.forEach((url) => { - try { - URL.revokeObjectURL(url); - } catch { - // 预览地址释放失败不影响关闭面板。 - } - }); - objectUrls.clear(); + revokeTrackedObjectUrls(objectUrls); }; }, []);