/** * 片段 CRUD + 批量操作 API */ import apiClient from "../client" import type { EditPlanClip, EditPlanClipListParams, EditPlanClipListResponse, CreateEditPlanClipRequest, UpdateEditPlanClipRequest, ClipReorderItem, ClipReorderResponse, ClipBatchDeleteResponse, ClipsFromAssetsResponse, } from "./types" /** 获取片段列表 */ export async function getEditPlanClips( templateId: string, params?: EditPlanClipListParams, ): Promise { const response = await apiClient.get( `/templates/${templateId}/editor/clips`, { params }, ) return response.data } /** 获取单个片段详情 */ export async function getEditPlanClip(templateId: string, clipId: string): Promise { const response = await apiClient.get( `/templates/${templateId}/editor/clips/${clipId}`, ) return response.data } /** 创建片段 */ export async function createEditPlanClip( templateId: string, data: CreateEditPlanClipRequest, ): Promise { const response = await apiClient.post(`/templates/${templateId}/editor/clips`, data) return response.data } /** 更新片段 */ export async function updateEditPlanClip( templateId: string, clipId: string, data: UpdateEditPlanClipRequest, ): Promise { const response = await apiClient.put( `/templates/${templateId}/editor/clips/${clipId}`, data, ) return response.data } /** 删除片段 */ export async function deleteEditPlanClip(templateId: string, clipId: string): Promise { await apiClient.delete(`/templates/${templateId}/editor/clips/${clipId}`) } /** 片段重排序(拖拽排序后一次性提交) */ export async function reorderEditPlanClips( templateId: string, items: ClipReorderItem[], ): Promise { const response = await apiClient.post( `/templates/${templateId}/editor/clips/reorder`, { items }, ) return response.data } /** 批量删除片段 */ export async function batchDeleteEditPlanClips( templateId: string, clipIds: string[], ): Promise { const response = await apiClient.post( `/templates/${templateId}/editor/clips/batch-delete`, { clip_ids: clipIds }, ) return response.data } /** * 从素材批量创建片段(追加到时间线末尾)。 * #1921 修复:templateId 为空时调用新端点 POST /clips/from-assets,避免拼出双斜杠 * `/templates//editor/clips/from-assets` 导致 404;有 templateId 时保持原路径向后兼容。 */ export async function createClipsFromAssets( templateId: string | undefined | null, assetIds: string[], clipType = "main", requiredClipsCount?: number, opts?: { signal?: AbortSignal; silentErrorToast?: boolean }, ): Promise { const body: Record = { asset_ids: assetIds, clip_type: clipType, } if (requiredClipsCount !== undefined) { body.required_clips_count = requiredClipsCount } // 新端点(#1921):templateId 为空时,body 不传 template_id,由后端兜底创建默认模板 const hasTid = !!templateId const url = hasTid ? `/templates/${templateId}/editor/clips/from-assets` : "/clips/from-assets" // from-assets 后端会调用 MediaKit 智能选片(最长 60s),单独延长超时 const response = await apiClient.post(url, body, { timeout: 60000, signal: opts?.signal, // _silentErrorToast 由 api/client.ts 响应拦截器读取(抑制全局错误 toast,#1777) ...(opts?.silentErrorToast ? ({ _silentErrorToast: true } as Record) : {}), }) return response.data }