feat: 生成前同步片段到后端clips表
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 31s
CI/CD Pipeline / Frontend Lint (push) Failing after 30s
CI/CD Pipeline / Unit Tests (push) Successful in 1m47s
CI/CD Pipeline / Integration Tests (push) Successful in 1m24s
CI Build & Deploy Pipeline / Production Browser E2E (push) Failing after 1492h26m21s
CI Build & Deploy Pipeline / Deploy Production (push) Failing after 1492h26m23s
CI Build & Deploy Pipeline / Build Production Web Image (push) Failing after 1492h26m27s
CI Build & Deploy Pipeline / Build Production API Image (push) Failing after 1492h26m29s
CI Build & Deploy Pipeline / Build Staging Worker Image (push) Failing after 1492h26m37s
CI Build & Deploy Pipeline / Staging API Integration Tests (push) Failing after 1492h26m33s
CI Build & Deploy Pipeline / Build Staging Web Image (push) Failing after 1492h26m39s
CI Build & Deploy Pipeline / Staging E2E Tests (push) Failing after 1492h26m33s
CI Build & Deploy Pipeline / Build Staging API Image (push) Failing after 1492h26m39s
CI Build & Deploy Pipeline / Build Production Worker Image (push) Failing after 1492h58m12s
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Failing after 1492h58m22s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 31s
CI/CD Pipeline / Frontend Lint (push) Failing after 30s
CI/CD Pipeline / Unit Tests (push) Successful in 1m47s
CI/CD Pipeline / Integration Tests (push) Successful in 1m24s
CI Build & Deploy Pipeline / Production Browser E2E (push) Failing after 1492h26m21s
CI Build & Deploy Pipeline / Deploy Production (push) Failing after 1492h26m23s
CI Build & Deploy Pipeline / Build Production Web Image (push) Failing after 1492h26m27s
CI Build & Deploy Pipeline / Build Production API Image (push) Failing after 1492h26m29s
CI Build & Deploy Pipeline / Build Staging Worker Image (push) Failing after 1492h26m37s
CI Build & Deploy Pipeline / Staging API Integration Tests (push) Failing after 1492h26m33s
CI Build & Deploy Pipeline / Build Staging Web Image (push) Failing after 1492h26m39s
CI Build & Deploy Pipeline / Staging E2E Tests (push) Failing after 1492h26m33s
CI Build & Deploy Pipeline / Build Staging API Image (push) Failing after 1492h26m39s
CI Build & Deploy Pipeline / Build Production Worker Image (push) Failing after 1492h58m12s
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Failing after 1492h58m22s
- 编辑器新增 syncClipsToBackend 函数 - 生成前自动将本地片段同步到后端 clips 表 - 并发控制 3 个请求,删除旧片段后批量重建 - 同步失败不阻塞生成(后端有模板兜底) - 对接后端 PR#389 clips API
This commit is contained in:
@@ -38,6 +38,11 @@ import {
|
||||
getGenerationStatus,
|
||||
getGenerationTaskResults,
|
||||
cancelGenerationTask,
|
||||
getEditPlanClips,
|
||||
createEditPlanClip,
|
||||
batchDeleteEditPlanClips,
|
||||
type EditPlanClip,
|
||||
type CreateEditPlanClipRequest,
|
||||
} from "@/api/editPlans";
|
||||
import { useUndoRedo } from "./hooks/useUndoRedo";
|
||||
import type {
|
||||
@@ -931,10 +936,62 @@ const EditingPlanner: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 将本地编辑的片段同步到后端 clips 表
|
||||
* 策略:先删除后端所有片段,再批量创建(简单可靠,生成前使用)
|
||||
*/
|
||||
const syncClipsToBackend = async (planId: string): Promise<void> => {
|
||||
if (clips.length === 0) return;
|
||||
|
||||
// 1. 获取后端现有片段 ID
|
||||
try {
|
||||
const existing = await getEditPlanClips(planId, { limit: 500 });
|
||||
if (existing.items.length > 0) {
|
||||
await batchDeleteEditPlanClips(
|
||||
planId,
|
||||
existing.items.map((c) => c.id),
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("[获取后端片段失败,跳过删除]", err);
|
||||
}
|
||||
|
||||
// 2. 批量创建新片段(并发 3 个)
|
||||
const clipDataList: CreateEditPlanClipRequest[] = clips.map((c, i) => ({
|
||||
clip_type: c.type === "voice" ? "voiceover" : "main",
|
||||
order: i,
|
||||
asset_id: c.media_asset_id || "",
|
||||
text_content: c.script_text || "",
|
||||
start_time: 0,
|
||||
duration: c.duration,
|
||||
transition_effect: c.transition?.type || "cut",
|
||||
transition_duration: c.transition?.duration || 0,
|
||||
playback_speed: c.speed?.rate || 1.0,
|
||||
config: {
|
||||
tts_config: c.tts_config || null,
|
||||
trim_config: c.trim_config || null,
|
||||
template_segment_id: c.template_segment_id || null,
|
||||
},
|
||||
}));
|
||||
|
||||
// 并发控制:最多同时 3 个请求
|
||||
const results: EditPlanClip[] = [];
|
||||
const concurrency = 3;
|
||||
for (let i = 0; i < clipDataList.length; i += concurrency) {
|
||||
const batch = clipDataList.slice(i, i + concurrency);
|
||||
const batchResults = await Promise.all(
|
||||
batch.map((data) => createEditPlanClip(planId, data)),
|
||||
);
|
||||
results.push(...batchResults);
|
||||
}
|
||||
|
||||
console.log(`[片段同步] 创建了 ${results.length} 个片段`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 剪辑计划生成
|
||||
* 1. 有 planId → 更新计划配置 + 触发生成
|
||||
* 2. 无 planId(从模板库直接进入)→ 先创建计划 + 触发生成
|
||||
* 1. 有 planId → 更新计划配置 + 同步片段 + 触发生成
|
||||
* 2. 无 planId(从模板库直接进入)→ 先创建计划 + 同步片段 + 触发生成
|
||||
* 3. 触发生成后轮询状态,完成后获取视频结果
|
||||
*/
|
||||
const handleGoToGenerate = async () => {
|
||||
@@ -991,6 +1048,14 @@ const EditingPlanner: React.FC = () => {
|
||||
window.history.replaceState(null, "", `?${params.toString()}`);
|
||||
}
|
||||
|
||||
// 同步片段到后端 clips 表(生成前必须同步,后端生成从 clips 表读)
|
||||
try {
|
||||
await syncClipsToBackend(planId);
|
||||
} catch (syncErr) {
|
||||
console.warn("[片段同步失败]", syncErr);
|
||||
// 同步失败不阻塞生成,后端有模板兜底
|
||||
}
|
||||
|
||||
// 触发生成
|
||||
const genRes = await generateEditPlan(planId);
|
||||
setGenTotalClips(genRes.clip_count);
|
||||
|
||||
Reference in New Issue
Block a user