Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 25257743a7 | |||
| 9566ff5a96 |
@@ -1,243 +0,0 @@
|
|||||||
/**
|
|
||||||
* 模板编辑器 API
|
|
||||||
* 对接后端 /api/v1/templates 路由
|
|
||||||
*/
|
|
||||||
import apiClient from "./client"
|
|
||||||
import type {
|
|
||||||
WatermarkConfig,
|
|
||||||
IntroOutroConfig,
|
|
||||||
PipConfig,
|
|
||||||
FilterConfig,
|
|
||||||
ChromaKeyConfig,
|
|
||||||
StickerConfig,
|
|
||||||
CoverConfig,
|
|
||||||
} from "@/pages/editing-planner/types"
|
|
||||||
|
|
||||||
/* ──────────── 类型定义 ──────────── */
|
|
||||||
|
|
||||||
/** 模板模式(后端枚举值) */
|
|
||||||
export type TemplateMode = "pip" | "voice_over" | "one_take" | "voice_pip"
|
|
||||||
|
|
||||||
/** 模式显示名称映射 */
|
|
||||||
export const MODE_LABELS: Record<TemplateMode, string> = {
|
|
||||||
pip: "混剪",
|
|
||||||
voice_over: "人物口播",
|
|
||||||
one_take: "一镜到底",
|
|
||||||
voice_pip: "口播+混剪",
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 模式颜色映射 */
|
|
||||||
export const MODE_COLORS: Record<TemplateMode, string> = {
|
|
||||||
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[]
|
|
||||||
/** 水印配置(后端就绪后启用) */
|
|
||||||
watermark_config?: WatermarkConfig
|
|
||||||
/** 片头片尾配置(后端就绪后启用) */
|
|
||||||
intro_outro_config?: IntroOutroConfig
|
|
||||||
/** 混剪配置 */
|
|
||||||
pip_config?: PipConfig
|
|
||||||
/** 滤镜调色配置 */
|
|
||||||
filter_config?: FilterConfig
|
|
||||||
/** 绿幕抠像配置 */
|
|
||||||
green_screen_config?: ChromaKeyConfig
|
|
||||||
/** 贴纸配置 */
|
|
||||||
sticker_config?: StickerConfig
|
|
||||||
/** 封面配置 */
|
|
||||||
cover_config?: CoverConfig
|
|
||||||
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<TemplateSegment, "id">[]
|
|
||||||
/** 水印配置(后端就绪后启用) */
|
|
||||||
watermark_config?: WatermarkConfig
|
|
||||||
/** 片头片尾配置(后端就绪后启用) */
|
|
||||||
intro_outro_config?: IntroOutroConfig
|
|
||||||
/** 混剪配置 */
|
|
||||||
pip_config?: PipConfig
|
|
||||||
/** 滤镜调色配置 */
|
|
||||||
filter_config?: FilterConfig
|
|
||||||
/** 绿幕抠像配置 */
|
|
||||||
green_screen_config?: ChromaKeyConfig
|
|
||||||
/** 贴纸配置 */
|
|
||||||
sticker_config?: StickerConfig
|
|
||||||
/** 封面配置 */
|
|
||||||
cover_config?: CoverConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 使用模板生成请求体 */
|
|
||||||
export interface GenerateFromTemplatePayload {
|
|
||||||
voiceover_duration: number
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 验证警告详情 */
|
|
||||||
export interface ValidationWarningDetails {
|
|
||||||
/** 相关字段名 */
|
|
||||||
field?: string
|
|
||||||
/** 期望值 */
|
|
||||||
expected?: string | number
|
|
||||||
/** 实际值 */
|
|
||||||
actual?: string | number
|
|
||||||
/** 建议值 */
|
|
||||||
suggested?: string | number
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 验证/生成响应 */
|
|
||||||
export interface ValidateWarning {
|
|
||||||
code: string
|
|
||||||
message: string
|
|
||||||
details?: ValidationWarningDetails
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 使用模板生成响应 */
|
|
||||||
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<EditingTemplate[]> => {
|
|
||||||
const response = await apiClient.get<ListTemplatesResponse>("/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<EditingTemplate> => {
|
|
||||||
const response = await apiClient.get<EditingTemplate>(`/templates/${id}`)
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 创建模板 */
|
|
||||||
export const createEditingTemplate = async (
|
|
||||||
data: SaveTemplatePayload,
|
|
||||||
): Promise<EditingTemplate> => {
|
|
||||||
const response = await apiClient.post<EditingTemplate>("/templates", data)
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 更新模板 */
|
|
||||||
export const updateEditingTemplate = async (
|
|
||||||
id: string,
|
|
||||||
data: SaveTemplatePayload,
|
|
||||||
): Promise<EditingTemplate> => {
|
|
||||||
const response = await apiClient.patch<EditingTemplate>(`/templates/${id}`, data)
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除模板 */
|
|
||||||
export const deleteEditingTemplate = async (id: string): Promise<void> => {
|
|
||||||
await apiClient.delete(`/templates/${id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获取模板分类列表 */
|
|
||||||
export const getTemplateCategories = async (): Promise<TemplateCategory[]> => {
|
|
||||||
const response = await apiClient.get<ListCategoriesResponse>("/templates/categories/list")
|
|
||||||
return response.data.items
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 使用模板生成视频(调用 validate 端点) */
|
|
||||||
export const generateFromTemplate = async (
|
|
||||||
templateId: string,
|
|
||||||
data: GenerateFromTemplatePayload,
|
|
||||||
): Promise<GenerateFromTemplateResponse> => {
|
|
||||||
const response = await apiClient.post<GenerateFromTemplateResponse>(
|
|
||||||
`/templates/${templateId}/validate`,
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 模板编辑器常量
|
||||||
|
*/
|
||||||
|
import type { TemplateMode } from "./types"
|
||||||
|
|
||||||
|
/** 模式显示名称映射 */
|
||||||
|
export const MODE_LABELS: Record<TemplateMode, string> = {
|
||||||
|
pip: "混剪",
|
||||||
|
voice_over: "人物口播",
|
||||||
|
one_take: "一镜到底",
|
||||||
|
voice_pip: "口播+混剪",
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 模式颜色映射 */
|
||||||
|
export const MODE_COLORS: Record<TemplateMode, string> = {
|
||||||
|
pip: "blue",
|
||||||
|
voice_over: "green",
|
||||||
|
one_take: "orange",
|
||||||
|
voice_pip: "purple",
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* 模板编辑器 API — 目录化入口
|
||||||
|
* 保持与原 editing-planner.ts 相同导出,向后兼容
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 类型
|
||||||
|
export type {
|
||||||
|
TemplateMode,
|
||||||
|
TitleConfig,
|
||||||
|
SubtitleConfig,
|
||||||
|
BgmConfig,
|
||||||
|
TemplateSegment,
|
||||||
|
EditingTemplate,
|
||||||
|
TemplateCategory,
|
||||||
|
SaveTemplatePayload,
|
||||||
|
GenerateFromTemplatePayload,
|
||||||
|
ValidationWarningDetails,
|
||||||
|
ValidateWarning,
|
||||||
|
GenerateFromTemplateResponse,
|
||||||
|
ListTemplatesResponse,
|
||||||
|
ListCategoriesResponse,
|
||||||
|
} from "./types"
|
||||||
|
|
||||||
|
// 常量
|
||||||
|
export { MODE_LABELS, MODE_COLORS } from "./constants"
|
||||||
|
|
||||||
|
// API 函数
|
||||||
|
export {
|
||||||
|
getEditingTemplates,
|
||||||
|
getEditingTemplate,
|
||||||
|
createEditingTemplate,
|
||||||
|
updateEditingTemplate,
|
||||||
|
deleteEditingTemplate,
|
||||||
|
getTemplateCategories,
|
||||||
|
generateFromTemplate,
|
||||||
|
} from "./templates"
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* 模板编辑器 API 函数
|
||||||
|
*/
|
||||||
|
import apiClient from "../client"
|
||||||
|
import type {
|
||||||
|
EditingTemplate,
|
||||||
|
TemplateCategory,
|
||||||
|
SaveTemplatePayload,
|
||||||
|
GenerateFromTemplatePayload,
|
||||||
|
GenerateFromTemplateResponse,
|
||||||
|
ListTemplatesResponse,
|
||||||
|
ListCategoriesResponse,
|
||||||
|
} from "./types"
|
||||||
|
|
||||||
|
/** 获取模板列表 */
|
||||||
|
export const getEditingTemplates = async (params?: {
|
||||||
|
category?: string
|
||||||
|
tag?: string
|
||||||
|
skip?: number
|
||||||
|
limit?: number
|
||||||
|
}): Promise<EditingTemplate[]> => {
|
||||||
|
const response = await apiClient.get<ListTemplatesResponse>("/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<EditingTemplate> => {
|
||||||
|
const response = await apiClient.get<EditingTemplate>(`/templates/${id}`)
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建模板 */
|
||||||
|
export const createEditingTemplate = async (
|
||||||
|
data: SaveTemplatePayload,
|
||||||
|
): Promise<EditingTemplate> => {
|
||||||
|
const response = await apiClient.post<EditingTemplate>("/templates", data)
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新模板 */
|
||||||
|
export const updateEditingTemplate = async (
|
||||||
|
id: string,
|
||||||
|
data: SaveTemplatePayload,
|
||||||
|
): Promise<EditingTemplate> => {
|
||||||
|
const response = await apiClient.patch<EditingTemplate>(`/templates/${id}`, data)
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除模板 */
|
||||||
|
export const deleteEditingTemplate = async (id: string): Promise<void> => {
|
||||||
|
await apiClient.delete(`/templates/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取模板分类列表 */
|
||||||
|
export const getTemplateCategories = async (): Promise<TemplateCategory[]> => {
|
||||||
|
const response = await apiClient.get<ListCategoriesResponse>("/templates/categories/list")
|
||||||
|
return response.data.items
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 使用模板生成视频(调用 validate 端点) */
|
||||||
|
export const generateFromTemplate = async (
|
||||||
|
templateId: string,
|
||||||
|
data: GenerateFromTemplatePayload,
|
||||||
|
): Promise<GenerateFromTemplateResponse> => {
|
||||||
|
const response = await apiClient.post<GenerateFromTemplateResponse>(
|
||||||
|
`/templates/${templateId}/validate`,
|
||||||
|
data,
|
||||||
|
)
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* 模板编辑器类型定义
|
||||||
|
*/
|
||||||
|
import type {
|
||||||
|
WatermarkConfig,
|
||||||
|
IntroOutroConfig,
|
||||||
|
PipConfig,
|
||||||
|
FilterConfig,
|
||||||
|
ChromaKeyConfig,
|
||||||
|
StickerConfig,
|
||||||
|
CoverConfig,
|
||||||
|
} from "@/pages/editing-planner/types"
|
||||||
|
|
||||||
|
/** 模板模式(后端枚举值) */
|
||||||
|
export type TemplateMode = "pip" | "voice_over" | "one_take" | "voice_pip"
|
||||||
|
|
||||||
|
/** 标题配置 */
|
||||||
|
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[]
|
||||||
|
watermark_config?: WatermarkConfig
|
||||||
|
intro_outro_config?: IntroOutroConfig
|
||||||
|
pip_config?: PipConfig
|
||||||
|
filter_config?: FilterConfig
|
||||||
|
green_screen_config?: ChromaKeyConfig
|
||||||
|
sticker_config?: StickerConfig
|
||||||
|
cover_config?: CoverConfig
|
||||||
|
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<TemplateSegment, "id">[]
|
||||||
|
watermark_config?: WatermarkConfig
|
||||||
|
intro_outro_config?: IntroOutroConfig
|
||||||
|
pip_config?: PipConfig
|
||||||
|
filter_config?: FilterConfig
|
||||||
|
green_screen_config?: ChromaKeyConfig
|
||||||
|
sticker_config?: StickerConfig
|
||||||
|
cover_config?: CoverConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 使用模板生成请求体 */
|
||||||
|
export interface GenerateFromTemplatePayload {
|
||||||
|
voiceover_duration: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 验证警告详情 */
|
||||||
|
export interface ValidationWarningDetails {
|
||||||
|
field?: string
|
||||||
|
expected?: string | number
|
||||||
|
actual?: string | number
|
||||||
|
suggested?: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 验证警告 */
|
||||||
|
export interface ValidateWarning {
|
||||||
|
code: string
|
||||||
|
message: string
|
||||||
|
details?: ValidationWarningDetails
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 使用模板生成响应 */
|
||||||
|
export interface GenerateFromTemplateResponse {
|
||||||
|
template: EditingTemplate
|
||||||
|
warnings: ValidateWarning[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表响应(带分页) */
|
||||||
|
export interface ListTemplatesResponse {
|
||||||
|
items: EditingTemplate[]
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 分类列表响应 */
|
||||||
|
export interface ListCategoriesResponse {
|
||||||
|
items: TemplateCategory[]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user