- 一键策划后自动连续执行完整流程(策划→图片→视频),无需手动点继续
- 节点数量跟随 API 返回的分镜数动态生成,策划前只显示 1 个占位节点
- 分镜图片和视频可点击弹出全屏预览浮层
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The three-phase exit→enter→idle flow caused a visible "double refresh"
jitter. During the enter phase (220ms), the wrapper animated from
opacity:0 while cancelling child .page-motion with animation:none
!important. When phase switched to idle, the !important rule was
removed and child .page-motion re-triggered, creating a second
entrance animation — the jitter.
Fix: remove the enter phase entirely. After exit animation (180ms),
phase goes directly to idle. The child page's own .page-motion class
handles entrance naturally via React's fresh DOM mount. No wrapper
animation on enter, no double-animation conflict.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously all 4 image tools generated a single image and duplicated
it across 5 fixed card slots. Now:
- Set (套图) mode: uses cloneSetCounts (卖点图/白底图/场景图 quantity)
to determine how many images to generate. Each type gets its own
createImageTask call with a type-specific prompt, so images differ
by category (selling-point vs white-background vs lifestyle scene).
- Preview cards are dynamically built from cloneSetCounts, not from
the fixed 5-slot productSetPreviewCards template. A card labeled
"卖点图 1", "卖点图 2" etc for count > 1, or just "卖点图" for
count = 1.
- clonePreview: shows dynamic card grid for set mode, single result
for detail/model/hot modes.
- setPreview: shows original image as main card, then all generated
set cards in the grid.
- generateSetImages: new async function that loops over each count
type and generates images sequentially with distinct prompts.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The set/detail preview areas were using static placeholder images
instead of the API-generated results. Fix:
- Add productSetResultImages state for set tool results
- Add detailResultUrl state for detail tool results
- Create setPreviewCards (like clonePreviewCards) that overlays
generated URLs onto static card templates
- Replace setPreview JSX references from productSetPreviewCards
to setPreviewCards so generated URLs are displayed
- Replace detailPreview longPage image with detailResultUrl fallback
- Update handleSetGenerate setResultFn to save URLs via
setProductSetResultImages
- Update handleDetailGenerate setResultFn to save URL via
setDetailResultUrl
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
All four image tools (套图, 详情图, 模特图, 爆款图复刻) previously used
setTimeout + static sample images. Now they:
1. Upload product images to OSS via uploadAssetBinary
2. Build contextual prompts including platform/ratio/language/market + user text
3. Call aiGenerationClient.createImageTask with model=gpt-image-2
4. Poll task status via waitForTask (SSE + fallback polling)
5. Display the generated result URL in the preview grid
Key changes:
- Add ServerRequestError + waitForTask imports
- Add imageAbortRef for task cancellation
- Add uploadCloneImages() (generic version of uploadProductImages)
- Add buildEcommerceImagePrompt() with output-type-specific instructions
- Add generateEcommerceImage() orchestrating upload → prompt → API → result
- Replace all 5 mock handlers (handleGenerate, handleSetGenerate,
handleDetailGenerate, handleTryOnGenerate, handleGenerateModel) with
real async API calls
- Handle 402 (Payment Required) with user-friendly error message
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When the server returns 402 (balance insufficient), the rendering loop
continued submitting all remaining scenes, each failing with the same 402.
Now it immediately stops the loop, sets a clear "余额不足,请充值后再生成视频"
error message, and aborts further scene submissions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The renderScene function was passing local data URLs (data:image/png;base64,...)
as imageUrl and referenceUrls to createVideoTask, which the /api/ai/video endpoint
rejects with 400 Bad Request. The planning phase already uploads images to OSS
but the resulting URLs were not returned to the component.
- Add imageUrls field to EcommerceVideoPlanResult
- Return OSS imageUrls from runVideoPlan alongside existing plan data
- Use planResult.imageUrls[0] in handleRender instead of productImageDataUrls[0]
- Use planResult?.imageUrls[0] for sourceImage display fallback
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Logout and session expiry previously redirected to "workbench" which
requires authentication, causing 401 errors and a frozen page state.
Now correctly redirects to "login" page immediately.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
runVideoPlan was passing blob URLs as "dataUrl" to uploadAssetWithProgress,
which sent them to /api/oss/upload (base64 path). Blob URLs don't match
DATA_URL_PATTERN regex, causing corrupt 44-byte files on OSS.
Now uses uploadAssetBinary (FormData multipart) via /api/oss/upload-binary,
fetching blob → uploading binary directly, same as EcommercePage path.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add uploadAssetBinary method to aiGenerationClient (FormData + busboy)
- Replace base64 dataUrl upload in uploadProductImages with direct blob upload
via /oss/upload-binary multipart endpoint
- This eliminates the DATA_URL_PATTERN regex parsing bug that produced
44-byte corrupt files on OSS, causing DashScope "image format illegal" errors
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>