fix(extract): 实体提取改异步(worker+轮询),根治 502 + 刷新丢 loading + 重复扣费
问题:进资产页点"提取人物/场景"——同步死等豆包思考模型(数十秒)→ 撞网关超时 502;"提取中"loading 是纯前端内存态,刷新即丢;且无幂等,刷新后重点会重复扣费。 改动(对齐全站异步三件套:出图/三视图/故事板同款): - 后端 submit_extract_entities:Web 只建 RESERVED 任务 + 预留额度秒回(不再 502); 已有在途提取则复用,绝不二次预扣(防刷新后重点 / 并发重复扣费)。 - 后端 run_extract_entities_task(Celery worker):流式调豆包 + 解析 + 落库 + 扣费; 失败退费并把可读错误记进 task.error_message。 - 新增 AITask.Type.entity_extraction(迁移 0011)+ extract-status 端点(轮询进度/成败)。 - 前端 runExtract 改提交+轮询;进资产页自动认领在途提取,刷新后 loading 自己回来。 验收:完整 Django 套件 149/149 全绿(含新增 4 测:异步落库+计费一次 / content空 回退 reasoning / 在途防重复扣费 / 状态端点成败透出);tsc + vite build 全绿; makemigrations --check 无遗漏。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
71af0ae166
commit
c8cb6d3d51
@@ -327,16 +327,19 @@ export const api = {
|
||||
body: JSON.stringify({ script_version_id })
|
||||
});
|
||||
},
|
||||
// 独立实体提取:读已定稿脚本 → AI 识别角色/场景 + 每镜 refs,落库覆盖 metadata。商品不提(参考图层用真实主图)。
|
||||
// 独立实体提取(**异步**):只提交任务、秒回 task_id(慢活在 worker 跑,不再 502);已有在途则复用(防重复扣费)。
|
||||
// 进度/结果用 extractStatus 轮询。商品不提(参考图层用真实主图)。
|
||||
extractEntities(projectId: string) {
|
||||
return request<{ task_id: string; status: string }>(`/api/projects/${projectId}/extract-entities/`, { method: "POST" });
|
||||
},
|
||||
// 实体提取进度:running=有在途任务(刷新后据此重建 loading);否则读最近一次成败,成功回带 entities 供「提取+生成」继续出图。
|
||||
extractStatus(projectId: string) {
|
||||
return request<{
|
||||
running: boolean;
|
||||
status: string;
|
||||
error: string;
|
||||
entities: Array<{ id: string; type: "character" | "scene"; name: string; visual_prompt: string; ref_index: number }>;
|
||||
segments: Array<{ index: number; entity_refs: string[] }>;
|
||||
cast: string[];
|
||||
cast_prompts: Record<string, string>;
|
||||
scenes: string[];
|
||||
scene_prompts: Record<string, string>;
|
||||
}>(`/api/projects/${projectId}/extract-entities/`, { method: "POST" });
|
||||
}>(`/api/projects/${projectId}/extract-status/`);
|
||||
},
|
||||
updateScriptSegment(projectId: string, payload: { segment_id: string; narration?: string; visual_prompt?: string; duration_seconds?: number }) {
|
||||
return request<ScriptVersion>(`/api/projects/${projectId}/update-script-segment/`, { method: "POST", body: JSON.stringify(payload) });
|
||||
|
||||
Reference in New Issue
Block a user