/** * 剪辑计划编辑器 API * 对接后端 /api/v1/templates 路由 */ import apiClient from "./client"; /* ──────────── 类型定义 ──────────── */ /** 模板模式(后端枚举值) */ export type TemplateMode = "pip" | "voice_over" | "one_take" | "voice_pip"; /** 模式显示名称映射 */ export const MODE_LABELS: Record = { pip: "画中画", voice_over: "人物口播", one_take: "一镜到底", voice_pip: "口播+混剪", }; /** 模式颜色映射 */ export const MODE_COLORS: Record = { pip: "blue", voice_over: "green", one_take: "orange", voice_pip: "purple", }; /** 标题配置 */ export interface TitleConfig { ai_auto_select: boolean; content: string; font_preset: string; font_color: string; font_size: number; position: string; } /** 字幕配置 */ export interface SubtitleConfig { enabled: boolean; position: string; font: string; color: string; size: number; animation: string; } /** BGM 配置 */ export interface BgmConfig { enabled: boolean; music_id: string; } /** 模板片段 */ export interface TemplateSegment { id?: string; segment_order: number; duration_min: number; duration_max: number; material_type: string | null; } /** 剪辑模板 */ export interface EditingTemplate { id: string; name: string; mode: TemplateMode; category: string; tags: string[]; title_config: TitleConfig; subtitle_config: SubtitleConfig; bgm_config: BgmConfig; estimated_duration: number; segments: TemplateSegment[]; is_active?: boolean; created_at: string; updated_at: string; } /** 模板分类 */ export interface TemplateCategory { id: string; name: string; created_at?: string; } /** 创建/更新模板请求体 */ export interface SaveTemplatePayload { name: string; mode: TemplateMode; category: string; tags: string[]; title_config: TitleConfig; subtitle_config: SubtitleConfig; bgm_config: BgmConfig; estimated_duration: number; segments: Omit[]; } /** 使用模板生成请求体 */ export interface GenerateFromTemplatePayload { voiceover_duration: number; } /** 验证/生成响应 */ export interface ValidateWarning { code: string; message: string; details?: Record; } /** 使用模板生成响应 */ export interface GenerateFromTemplateResponse { template: EditingTemplate; warnings: ValidateWarning[]; } /** 列表响应(带分页) */ export interface ListTemplatesResponse { items: EditingTemplate[]; total: number; } /** 分类列表响应 */ export interface ListCategoriesResponse { items: TemplateCategory[]; } // ============ API 函数 ============ /** 获取模板列表 */ export const getEditingTemplates = async (params?: { category?: string; tag?: string; skip?: number; limit?: number; }): Promise => { const response = await apiClient.get("/templates", { params: { skip: params?.skip ?? 0, limit: params?.limit ?? 50, }, }); let list = response.data.items; if (params?.category) list = list.filter((t) => t.category === params.category); if (params?.tag) list = list.filter((t) => t.tags.includes(params.tag!)); return list; }; /** 获取模板详情 */ export const getEditingTemplate = async ( id: string, ): Promise => { const response = await apiClient.get(`/templates/${id}`); return response.data; }; /** 创建模板 */ export const createEditingTemplate = async ( data: SaveTemplatePayload, ): Promise => { const response = await apiClient.post("/templates", data); return response.data; }; /** 更新模板 */ export const updateEditingTemplate = async ( id: string, data: SaveTemplatePayload, ): Promise => { const response = await apiClient.patch( `/templates/${id}`, data, ); return response.data; }; /** 删除模板 */ export const deleteEditingTemplate = async (id: string): Promise => { await apiClient.delete(`/templates/${id}`); }; /** 获取模板分类列表 */ export const getTemplateCategories = async (): Promise => { const response = await apiClient.get( "/templates/categories/list", ); return response.data.items; }; /** 使用模板生成视频(调用 validate 端点) */ export const generateFromTemplate = async ( templateId: string, data: GenerateFromTemplatePayload, ): Promise => { const response = await apiClient.post( `/templates/${templateId}/validate`, data, ); return response.data; };