style: prettier 格式化 useStep4Preview + useStep6Cover
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m35s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m46s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 1m13s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m44s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m49s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m24s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m13s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m31s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m0s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 19s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 6m11s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 7m28s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 10m13s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 9m48s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m49s
CI/CD Pipeline / CI Gate (pull_request) Failing after 6s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 832h49m50s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 832h49m51s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 832h49m51s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 832h49m52s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 833h0m25s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 833h0m28s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 833h0m29s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 833h0m29s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 833h0m26s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 833h23m20s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 833h23m21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 833h33m57s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 833h33m59s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m35s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m46s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 1m13s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m44s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m49s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m24s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m13s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m31s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m0s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 19s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 6m11s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 7m28s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 10m13s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 9m48s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m49s
CI/CD Pipeline / CI Gate (pull_request) Failing after 6s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 832h49m50s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 832h49m51s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 832h49m51s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 832h49m52s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 833h0m25s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 833h0m28s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 833h0m29s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 833h0m29s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 833h0m26s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 833h23m20s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 833h23m21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 833h33m57s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 833h33m59s
This commit is contained in:
@@ -212,99 +212,102 @@ export function useStep4Preview({
|
||||
}, [clearPollTimer])
|
||||
|
||||
/** 轮询单个预览任务状态 */
|
||||
const pollPreviewStatus = useCallback((index: number, taskId: string) => {
|
||||
const poll = async () => {
|
||||
// 竞态检查
|
||||
if (taskIdsRef.current.get(index) !== taskId) return
|
||||
|
||||
// 超时检查
|
||||
if (Date.now() - startTimeRef.current > POLL_TIMEOUT_MS) {
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index ? { ...it, status: "error", error: "预览生成超时,请重试" } : it,
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const data: PreviewTaskResponse = await getPreviewStatus(taskId)
|
||||
|
||||
const pollPreviewStatus = useCallback(
|
||||
(index: number, taskId: string) => {
|
||||
const poll = async () => {
|
||||
// 竞态检查
|
||||
if (taskIdsRef.current.get(index) !== taskId) return
|
||||
|
||||
const status = data.status as ApiPreviewStatus
|
||||
// 超时检查
|
||||
if (Date.now() - startTimeRef.current > POLL_TIMEOUT_MS) {
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index ? { ...it, status: "error", error: "预览生成超时,请重试" } : it,
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (status === "completed") {
|
||||
const result: PreviewResult = {
|
||||
taskId: safeString(data.task_id, ""),
|
||||
videoUrl: safeString(data.video_url, ""),
|
||||
clipCount: safeNumber(data.clip_count),
|
||||
transitionCount: safeNumber(data.transition_count),
|
||||
materialUsage: safeNumber(data.material_usage),
|
||||
duration: safeNumber(data.duration),
|
||||
fileSize: safeNumber(data.file_size),
|
||||
generateDuration: safeNumber(data.generate_duration),
|
||||
progress: 100,
|
||||
try {
|
||||
const data: PreviewTaskResponse = await getPreviewStatus(taskId)
|
||||
|
||||
if (taskIdsRef.current.get(index) !== taskId) return
|
||||
|
||||
const status = data.status as ApiPreviewStatus
|
||||
|
||||
if (status === "completed") {
|
||||
const result: PreviewResult = {
|
||||
taskId: safeString(data.task_id, ""),
|
||||
videoUrl: safeString(data.video_url, ""),
|
||||
clipCount: safeNumber(data.clip_count),
|
||||
transitionCount: safeNumber(data.transition_count),
|
||||
materialUsage: safeNumber(data.material_usage),
|
||||
duration: safeNumber(data.duration),
|
||||
fileSize: safeNumber(data.file_size),
|
||||
generateDuration: safeNumber(data.generate_duration),
|
||||
progress: 100,
|
||||
}
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index ? { ...it, status: "ready", result, progress: 100 } : it,
|
||||
),
|
||||
)
|
||||
|
||||
// 保存预览视频 URL 到 plan config,供封面生成使用
|
||||
if (result.videoUrl && selectedTemplate) {
|
||||
updateEditPlan(selectedTemplate, {
|
||||
config: { rendered_storage_key: result.videoUrl },
|
||||
}).catch((err) => {
|
||||
console.warn("[Step4] 保存预览视频URL到plan config失败:", err)
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index ? { ...it, status: "ready", result, progress: 100 } : it,
|
||||
),
|
||||
)
|
||||
|
||||
// 保存预览视频 URL 到 plan config,供封面生成使用
|
||||
if (result.videoUrl && selectedTemplate) {
|
||||
updateEditPlan(selectedTemplate, {
|
||||
config: { rendered_storage_key: result.videoUrl },
|
||||
}).catch((err) => {
|
||||
console.warn("[Step4] 保存预览视频URL到plan config失败:", err)
|
||||
})
|
||||
if (status === "failed") {
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index
|
||||
? {
|
||||
...it,
|
||||
status: "error",
|
||||
error: safeString(data.error_message, "预览生成失败,请重试"),
|
||||
}
|
||||
: it,
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (status === "failed") {
|
||||
if (status === "cancelled") {
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index ? { ...it, status: "error", error: "预览任务已取消" } : it,
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// pending / generating 状态继续轮询
|
||||
const prog = safeNumber(data.progress)
|
||||
const nextStatus: PreviewStatus = status === "pending" ? "pending" : "generating"
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index
|
||||
? {
|
||||
...it,
|
||||
status: "error",
|
||||
error: safeString(data.error_message, "预览生成失败,请重试"),
|
||||
}
|
||||
: it,
|
||||
it.index === index ? { ...it, status: nextStatus, progress: prog } : it,
|
||||
),
|
||||
)
|
||||
return
|
||||
const delay = status === "pending" ? 5000 : 2000
|
||||
pollTimersRef.current.set(index, setTimeout(poll, delay))
|
||||
} catch {
|
||||
if (taskIdsRef.current.get(index) !== taskId) return
|
||||
pollTimersRef.current.set(index, setTimeout(poll, 3000))
|
||||
}
|
||||
|
||||
if (status === "cancelled") {
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index ? { ...it, status: "error", error: "预览任务已取消" } : it,
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// pending / generating 状态继续轮询
|
||||
const prog = safeNumber(data.progress)
|
||||
const nextStatus: PreviewStatus = status === "pending" ? "pending" : "generating"
|
||||
setItems((prev) =>
|
||||
prev.map((it) =>
|
||||
it.index === index ? { ...it, status: nextStatus, progress: prog } : it,
|
||||
),
|
||||
)
|
||||
const delay = status === "pending" ? 5000 : 2000
|
||||
pollTimersRef.current.set(index, setTimeout(poll, delay))
|
||||
} catch {
|
||||
if (taskIdsRef.current.get(index) !== taskId) return
|
||||
pollTimersRef.current.set(index, setTimeout(poll, 3000))
|
||||
}
|
||||
}
|
||||
|
||||
pollTimersRef.current.set(index, setTimeout(poll, 1000))
|
||||
}, [selectedTemplate])
|
||||
pollTimersRef.current.set(index, setTimeout(poll, 1000))
|
||||
},
|
||||
[selectedTemplate],
|
||||
)
|
||||
|
||||
/** 生成所有预览 */
|
||||
const generatePreview = useCallback(async () => {
|
||||
|
||||
@@ -110,7 +110,11 @@ export function useStep6Cover({
|
||||
|
||||
// 提取详细错误信息
|
||||
let errorMsg = "封面生成失败"
|
||||
const e = err as { response?: { data?: { detail?: string; message?: string }; status?: number }; request?: unknown; message?: string }
|
||||
const e = err as {
|
||||
response?: { data?: { detail?: string; message?: string }; status?: number }
|
||||
request?: unknown
|
||||
message?: string
|
||||
}
|
||||
if (e.response) {
|
||||
// 后端返回错误
|
||||
const detail = e.response.data?.detail || e.response.data?.message || ""
|
||||
|
||||
Reference in New Issue
Block a user