Files
xiaoxia-saas/apps/web/src/api/template-editor/clips.ts
T
xiaoxia a25aa7baed
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (push) Successful in 16s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 27s
CI/CD Pipeline / Build Staging API Image (push) Successful in 28s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 30s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m1s
CI/CD Pipeline / Frontend Unit Tests (push) Failing after 2m49s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m56s
CI/CD Pipeline / Integration Tests (push) Successful in 4m0s
CI/CD Pipeline / Validate - Style (push) Successful in 4m23s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m7s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m9s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m48s
CI/CD Pipeline / Validate - Security (push) Successful in 9m39s
CI/CD Pipeline / Unit Tests (push) Successful in 9m40s
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Failing after 27h59m57s
CI/CD Pipeline / Build Production Web Image (push) Failing after 28h0m1s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Failing after 28h8m54s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 28h9m45s
CI/CD Pipeline / PR Build Web Image (push) Failing after 28h9m7s
CI/CD Pipeline / PR Build API Image (push) Failing after 28h9m7s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 27h59m23s
CI/CD Pipeline / Build Production API Image (push) Failing after 27h59m24s
CI/CD Pipeline / CI Gate (push) Failing after 27h59m23s
CI/CD Pipeline / Canary Release to Production (push) Failing after 27h59m19s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Failing after 28h8m16s
CI/CD Pipeline / Retag skipped Staging API Image (push) Failing after 28h8m17s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 28h9m8s
CI/CD Pipeline / Frontend Lint (push) Failing after 28h9m4s
fix(generate): #1921 from-assets空templateId双斜杠404修复(P0前端) (#1925)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-09-15 11:13:58 +08:00

119 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 片段 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<EditPlanClipListResponse> {
const response = await apiClient.get<EditPlanClipListResponse>(
`/templates/${templateId}/editor/clips`,
{ params },
)
return response.data
}
/** 获取单个片段详情 */
export async function getEditPlanClip(templateId: string, clipId: string): Promise<EditPlanClip> {
const response = await apiClient.get<EditPlanClip>(
`/templates/${templateId}/editor/clips/${clipId}`,
)
return response.data
}
/** 创建片段 */
export async function createEditPlanClip(
templateId: string,
data: CreateEditPlanClipRequest,
): Promise<EditPlanClip> {
const response = await apiClient.post<EditPlanClip>(`/templates/${templateId}/editor/clips`, data)
return response.data
}
/** 更新片段 */
export async function updateEditPlanClip(
templateId: string,
clipId: string,
data: UpdateEditPlanClipRequest,
): Promise<EditPlanClip> {
const response = await apiClient.put<EditPlanClip>(
`/templates/${templateId}/editor/clips/${clipId}`,
data,
)
return response.data
}
/** 删除片段 */
export async function deleteEditPlanClip(templateId: string, clipId: string): Promise<void> {
await apiClient.delete(`/templates/${templateId}/editor/clips/${clipId}`)
}
/** 片段重排序(拖拽排序后一次性提交) */
export async function reorderEditPlanClips(
templateId: string,
items: ClipReorderItem[],
): Promise<ClipReorderResponse> {
const response = await apiClient.post<ClipReorderResponse>(
`/templates/${templateId}/editor/clips/reorder`,
{ items },
)
return response.data
}
/** 批量删除片段 */
export async function batchDeleteEditPlanClips(
templateId: string,
clipIds: string[],
): Promise<ClipBatchDeleteResponse> {
const response = await apiClient.post<ClipBatchDeleteResponse>(
`/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<ClipsFromAssetsResponse> {
const body: Record<string, unknown> = {
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<ClipsFromAssetsResponse>(url, body, {
timeout: 60000,
signal: opts?.signal,
// _silentErrorToast 由 api/client.ts 响应拦截器读取(抑制全局错误 toast,#1777)
...(opts?.silentErrorToast ? ({ _silentErrorToast: true } as Record<string, unknown>) : {}),
})
return response.data
}