fix(generate): 修复生成进度条卡56%不刷新 P1 #2071

Open
xiaoxia wants to merge 1 commits from fix/progress-stuck-at-56-20260927 into develop
Owner

问题(P1)

用户反馈前端渲染进度条卡在 56% 不动,但后端任务实际已经渲染完成(状态 = awaiting_cover),需手动刷新页面才能看到结果。

根因分析

  1. 状态映射缺失:旧代码只处理 completed/awaiting_cover/failed/cancelled/running 五种状态,后端新增/历史脏值(pending/queued/scheduled/processing/rendering/complete/done 等)会走到 fallback 分支,既不更新进度也不终止轮询,视觉停在上一次推送的 progress(约 56%)
  2. 网络错误终止轮询:连续 10 次错误后直接放弃轮询,浏览器 tab 切后台被节流或短暂网络抖动即永久停止
  3. 后台 tab 无恢复机制:setTimeout 在后台被严重节流,切回前台不会主动拉取最新状态,必须等下一个定时器
  4. 完成后需手动点「下一步」:用户停留在进度条页不知道已经生成好

注:本项目进度更新完全基于 HTTP 轮询(无 SSE/WebSocket),useGenerationPolling 是唯一来源。

修复

useGenerationPolling(主要修复点)

  • 新增 normalizeTaskStatus 归一化函数,兼容 pending/queued/scheduled/processing/rendering/complete/done/success/finished 等状态;pending 阶段显示 ≤5%,unknown 状态保持上次进度继续轮询,不阻断
  • 网络/5xx 错误改为指数退避无限重试(2s→15s),连续错误达到 5 次弹一次「网络不稳定…」提示避免 toast 风暴;只有 4xx(任务不存在/未授权)才终止
  • visibilitychange 监听:页面从后台切回立即触发一次 poll,秒级看到最新状态
  • unmount 时 useEffect cleanup 兜底清理所有定时器 + 控制器
  • 进度停滞探测:15s 内进度无变化且任务仍 running,缩短到 3s 主动再查,防止后端最后一次 progress 回调丢失
  • awaiting_cover 阶段 results 接口 write-after-read 抖动:空结果补 1.5s 后再查一次
  • 终态分支强制 onProgress(100) 再调 onComplete,避免 UI 停在 95%

GeneratePage(体验补全)

  • 新增 effect:生成完成后延迟 800ms 自动跳转到 Step5(封面选择页)
    • 单视频:finalVideo 或 currentTaskId 存在即可
    • 批量:所有 task 结束(completed/awaiting_cover/failed)且至少一个成功
    • 失败/手动重试/仍在生成中不跳转

验证

  • tsc --noEmit ✅
  • eslint ✅ 无错误/警告(含 react-hooks 规则)
  • prettier --write ✅
  • vite build ✅ 6.33s 构建通过

影响范围

仅修改 useGenerationPolling.ts(轮询鲁棒性增强)与 GeneratePage.tsx(自动跳转),不改后端 API 契约、不改 UI 样式。

未改动

  • 后端进度上报逻辑(worker 里已有合理分段:started 5% / TTS 10-25% / 字幕 30% / 片段 35-55% / 拼接 60-80% / 编码 80-95% / 完成 95-100%)
  • AI 数字人(ai-avatar)的进度轮询走独立组件,本次未动(如需同样修复可另行处理,本 PR 聚焦用户报障的智能剪辑 Step4 进度条)
## 问题(P1) 用户反馈前端渲染进度条卡在 56% 不动,但后端任务实际已经渲染完成(状态 = `awaiting_cover`),需手动刷新页面才能看到结果。 ## 根因分析 1. **状态映射缺失**:旧代码只处理 `completed/awaiting_cover/failed/cancelled/running` 五种状态,后端新增/历史脏值(`pending/queued/scheduled/processing/rendering/complete/done` 等)会走到 fallback 分支,既不更新进度也不终止轮询,视觉停在上一次推送的 progress(约 56%) 2. **网络错误终止轮询**:连续 10 次错误后直接放弃轮询,浏览器 tab 切后台被节流或短暂网络抖动即永久停止 3. **后台 tab 无恢复机制**:`setTimeout` 在后台被严重节流,切回前台不会主动拉取最新状态,必须等下一个定时器 4. **完成后需手动点「下一步」**:用户停留在进度条页不知道已经生成好 注:本项目进度更新**完全基于 HTTP 轮询**(无 SSE/WebSocket),`useGenerationPolling` 是唯一来源。 ## 修复 ### useGenerationPolling(主要修复点) - 新增 `normalizeTaskStatus` 归一化函数,兼容 `pending/queued/scheduled/processing/rendering/complete/done/success/finished` 等状态;pending 阶段显示 ≤5%,unknown 状态保持上次进度继续轮询,不阻断 - 网络/5xx 错误改为**指数退避无限重试**(2s→15s),连续错误达到 5 次弹一次「网络不稳定…」提示避免 toast 风暴;只有 4xx(任务不存在/未授权)才终止 - `visibilitychange` 监听:页面从后台切回**立即**触发一次 poll,秒级看到最新状态 - unmount 时 `useEffect cleanup` 兜底清理所有定时器 + 控制器 - **进度停滞探测**:15s 内进度无变化且任务仍 running,缩短到 3s 主动再查,防止后端最后一次 progress 回调丢失 - `awaiting_cover` 阶段 results 接口 write-after-read 抖动:空结果补 1.5s 后再查一次 - 终态分支强制 `onProgress(100)` 再调 `onComplete`,避免 UI 停在 95% ### GeneratePage(体验补全) - 新增 effect:生成完成后延迟 800ms 自动跳转到 Step5(封面选择页) - 单视频:`finalVideo` 或 `currentTaskId` 存在即可 - 批量:所有 task 结束(completed/awaiting_cover/failed)且至少一个成功 - 失败/手动重试/仍在生成中不跳转 ## 验证 - `tsc --noEmit` ✅ - `eslint` ✅ 无错误/警告(含 react-hooks 规则) - `prettier --write` ✅ - `vite build` ✅ 6.33s 构建通过 ## 影响范围 仅修改 `useGenerationPolling.ts`(轮询鲁棒性增强)与 `GeneratePage.tsx`(自动跳转),不改后端 API 契约、不改 UI 样式。 ## 未改动 - 后端进度上报逻辑(worker 里已有合理分段:started 5% / TTS 10-25% / 字幕 30% / 片段 35-55% / 拼接 60-80% / 编码 80-95% / 完成 95-100%) - AI 数字人(ai-avatar)的进度轮询走独立组件,本次未动(如需同样修复可另行处理,本 PR 聚焦用户报障的智能剪辑 Step4 进度条)
xiaoxia added 1 commit 2026-09-27 23:12:59 +08:00
fix(generate): 修复进度条卡56%不刷新P1 bug
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m15s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m27s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m32s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m57s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m22s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m11s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m40s
AI Code Review / AI Code Review (pull_request) Successful in 6m42s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m44s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 14m36s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
7a06ad52de
根因分析:
1. 后端任务状态新增/历史脏值(pending/queued/unknown等)未在前端
   normalizeTaskStatus映射中,fallback分支既不更新progress也不终止
   轮询,导致视觉停在上一次progress(约56%)
2. 旧版轮询网络/5xx错误连续10次即终止,浏览器tab切后台被节流或
   短暂网络抖动后永久停止轮询,用户看到的是停滞的旧progress
3. 浏览器后台tab的setTimeout被节流,切回前台时不会主动拉取最新状态,
   必须等下一个定时器才能看到结果
4. 生成完成后需手动点击「下一步」,用户误以为仍在渲染

修复:
- 新增normalizeTaskStatus兼容pending/queued/scheduled/processing/
  rendering/unknown/complete/done等状态,pending阶段显示≤5%进度,
  unknown状态保持上次进度继续轮询
- 网络/5xx错误改为指数退避无限重试(最大15s间隔),连续5次错误弹
  一次提示;4xx才终止(任务不存在/未授权)
- visibilitychange监听:页面从后台切回立即触发一次poll,秒级看到最新状态
- unmount时useEffect cleanup兜底清理所有定时器和控制器
- 进度停滞探测(15s无变化自动缩短到3s再查),防后端最后progress回调丢失
- awaiting_cover阶段results接口write-after-read抖动:空结果补1.5s后再查
- 终态前强制onProgress(100),避免UI停在95%
- 生成完成(单视频finalVideo就绪/批量全部完成且至少一个成功)后延迟800ms
  自动跳转到Step5封面选择页,无需手动点下一步

验证:tsc/eslint/prettier/vite build全通过
auto-approve-bot approved these changes 2026-09-27 23:14:26 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-09-27 23:14:26 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。

🚀 预览环境已部署

项目 详情
PR号 #2071
预览链接 https://pr-2071.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #2071 | | 预览链接 | [https://pr-2071.preview.xiaoxiajianji.com](https://pr-2071.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
Some checks are pending
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m15s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m27s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m32s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m57s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m22s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m11s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m40s
AI Code Review / AI Code Review (pull_request) Successful in 6m42s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m44s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 14m36s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
This pull request has changes conflicting with the target branch.
  • apps/web/src/pages/generate/hooks/generate-video/useGenerationPolling.ts
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/progress-stuck-at-56-20260927:fix/progress-stuck-at-56-20260927
git checkout fix/progress-stuck-at-56-20260927
Sign in to join this conversation.