feat: 剪辑规划器完整交互 — 7大配置面板 + 时间轴拖拽/缩放/播放头 + 预览播放器 (#284)
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Failing after 1533h11m48s
CI/CD Pipeline / Build Production Web Image (push) Failing after 1533h11m51s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 1533h11m51s
CI/CD Pipeline / Build Production API Image (push) Failing after 1533h11m51s
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been skipped
CI/CD Pipeline / Unit Tests (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Failing after 1533h43m28s

This commit was merged in pull request #284.
This commit is contained in:
2026-07-14 18:15:55 +08:00
parent c88be032c1
commit 78d1c88ca1
53 changed files with 13521 additions and 894 deletions
+133 -4
View File
@@ -1,26 +1,112 @@
/**
* 模板相关 API
* Phase 1 新增:全局模板库
* 对接后端模板管理接口:
* - GET /api/v1/templates — 模板列表(分页/筛选)
* - GET /api/v1/templates/{id} — 模板详情
* - POST /api/v1/templates/{id}/copy — 复制模板
* - POST /api/v1/templates/{id}/generate — 从模板生成剪辑计划
* - POST /api/v1/templates/{id}/toggle-favorite — 收藏/取消收藏
*/
import apiClient from "./client";
import type { TitleConfig, SubtitleConfig, BgmConfig } from "./editingPlanner";
import type { EditPlanConfig } from "./editPlans";
/** 模板条目 */
/* ──────────── 类型定义 ──────────── */
/** 模板条目(后端 TemplateResponse) */
export interface TemplateItem {
id: string;
name: string;
description: string;
category: string;
tags?: string[];
target_duration: number;
clip_count: number;
/** 使用次数 */
usage_count?: number;
thumbnail_url?: string;
preview_url?: string;
is_active: boolean;
is_favorite?: boolean;
/** 素材规则(片段配置) */
segments?: TemplateSegment[];
/** 字幕样式 */
subtitle_config?: SubtitleConfig;
/** BGM 配置 */
bgm_config?: BgmConfig;
/** 标题配置 */
title_config?: TitleConfig;
/** 视频比例 */
aspect_ratio?: string;
created_at?: string;
updated_at?: string;
}
/** 获取全局模板列表 */
export const getTemplates = async (): Promise<TemplateItem[]> => {
/** 模板片段(素材规则) */
export interface TemplateSegment {
id?: string;
segment_order: number;
duration_min: number;
duration_max: number;
material_type: string | null;
description?: string;
}
/** 模板列表查询参数 */
export interface TemplateListParams {
page?: number;
page_size?: number;
category?: string;
tags?: string;
keyword?: string;
/** 时长筛选(秒):short < 30, medium 30-120, long > 120 */
duration_range?: "short" | "medium" | "long";
}
/** 模板列表分页响应 */
export interface TemplateListResponse {
items: TemplateItem[];
total: number;
page: number;
page_size: number;
}
/** 从模板生成剪辑计划请求 */
export interface GenerateFromTemplateRequest {
asset_ids?: string[];
name?: string;
config?: EditPlanConfig;
}
/** 从模板生成剪辑计划响应 */
export interface GenerateFromTemplateResponse {
plan_id: string;
template_id: string;
status: string;
name: string;
}
/** 复制模板响应 */
export interface CopyTemplateResponse {
id: string;
name: string;
source_template_id: string;
}
/* ──────────── API 函数 ──────────── */
/** 获取模板列表(支持分页和筛选) */
export const getTemplates = async (
params?: TemplateListParams,
): Promise<TemplateListResponse> => {
const { data } = await apiClient.get<TemplateListResponse>("/templates", {
params,
});
return data;
};
/** 获取模板列表(兼容旧接口,返回数组) */
export const getTemplatesList = async (): Promise<TemplateItem[]> => {
const response = await apiClient.get("/templates");
return response.data.items || response.data || [];
};
@@ -42,3 +128,46 @@ export const toggleFavoriteTemplate = async (
);
return response.data;
};
/** 复制模板(创建副本到我的模板) */
export const copyTemplate = async (
templateId: string,
): Promise<CopyTemplateResponse> => {
const response = await apiClient.post<CopyTemplateResponse>(
`/templates/${templateId}/copy`,
);
return response.data;
};
/** 从模板生成剪辑计划 */
export const generateFromTemplate = async (
templateId: string,
data?: GenerateFromTemplateRequest,
): Promise<GenerateFromTemplateResponse> => {
const response = await apiClient.post<GenerateFromTemplateResponse>(
`/templates/${templateId}/generate`,
data,
);
return response.data;
};
/* ──────────── 常量 ──────────── */
/** 模板分类选项 */
export const TEMPLATE_CATEGORY_OPTIONS = [
{ value: "", label: "全部分类" },
{ value: "口播", label: "口播" },
{ value: "种草", label: "种草" },
{ value: "产品", label: "产品" },
{ value: "品牌", label: "品牌" },
{ value: "混剪", label: "混剪" },
{ value: "Vlog", label: "Vlog" },
];
/** 时长筛选选项 */
export const TEMPLATE_DURATION_OPTIONS = [
{ value: "", label: "全部时长" },
{ value: "short", label: "30秒以内" },
{ value: "medium", label: "30秒-2分钟" },
{ value: "long", label: "2分钟以上" },
];