0fcb77b991
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Successful in 1m6s
CI Build & Deploy Pipeline / Build Staging Web Image (push) Successful in 1m49s
CI Build & Deploy Pipeline / Build Production API Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (push) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (push) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 3m1s
CI/CD Pipeline / Unit Tests (push) Successful in 3m20s
CI/CD Pipeline / Integration Tests (push) Successful in 1m29s
CI Build & Deploy Pipeline / Build Staging API Image (push) Successful in 7m4s
CI Build & Deploy Pipeline / Build Staging Worker Image (push) Successful in 7m54s
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 45s
CI Build & Deploy Pipeline / Staging E2E Tests (push) Failing after 2m50s
CI Build & Deploy Pipeline / Staging API Integration Tests (push) Successful in 3m28s
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
140 lines
4.5 KiB
TypeScript
140 lines
4.5 KiB
TypeScript
/**
|
|
* 成品 / 视频相关 API
|
|
* 包含:列表查询、复核状态、批量下载
|
|
* 后端无 /products 路由,实际从 /generation/tasks 端点获取数据
|
|
*/
|
|
import apiClient from "./client"
|
|
import { getGenerationTaskResults } from "./editPlans"
|
|
import type { GeneratedVideo } from "./editPlans"
|
|
|
|
/** 复核状态 */
|
|
export type ReviewStatus = "pending_review" | "approved" | "rejected"
|
|
|
|
/** 成品条目 */
|
|
export interface ProductItem {
|
|
id: string
|
|
title: string
|
|
video_url?: string
|
|
thumbnail_url?: string
|
|
duration_seconds?: number
|
|
file_size?: number
|
|
resolution?: string
|
|
status: "processing" | "completed" | "failed"
|
|
/** 复核状态 */
|
|
review_status?: ReviewStatus
|
|
/** 所属项目 ID */
|
|
project_id?: string
|
|
/** 所属项目名称 */
|
|
project_name?: string
|
|
/** 查重率(百分比) */
|
|
duplicate_rate?: number
|
|
created_at?: string
|
|
updated_at?: string
|
|
}
|
|
|
|
/** 列表查询参数 */
|
|
export interface ProductListParams {
|
|
page?: number
|
|
page_size?: number
|
|
project_id?: string
|
|
review_status?: ReviewStatus | "all"
|
|
}
|
|
|
|
/** 分页响应 */
|
|
export interface ProductListResponse {
|
|
items: ProductItem[]
|
|
total: number
|
|
page: number
|
|
page_size: number
|
|
}
|
|
|
|
/** 批量下载任务状态 */
|
|
export interface BatchDownloadStatus {
|
|
job_id: string
|
|
status: "processing" | "completed" | "failed"
|
|
/** 完成后返回的下载 URL */
|
|
download_url?: string
|
|
/** 进度百分比 */
|
|
progress?: number
|
|
}
|
|
|
|
/**
|
|
* 将 generation task 数据映射为 ProductItem 格式
|
|
*/
|
|
function mapTaskToProductItem(task: GeneratedVideo): ProductItem {
|
|
return {
|
|
id: task.id,
|
|
title: task.name || "未命名视频",
|
|
video_url: task.file_url,
|
|
thumbnail_url: task.thumbnail_url,
|
|
duration_seconds: task.duration,
|
|
file_size: task.file_size,
|
|
resolution: task.width && task.height ? `${task.width}x${task.height}` : undefined,
|
|
status:
|
|
task.status === "completed"
|
|
? "completed"
|
|
: task.status === "failed"
|
|
? "failed"
|
|
: "processing",
|
|
review_status: task.review_status as ReviewStatus | undefined,
|
|
project_id: task.project_id,
|
|
created_at: task.created_at,
|
|
updated_at: task.updated_at,
|
|
}
|
|
}
|
|
|
|
/** 获取成品列表(支持分页和筛选)— 实际从 generation tasks 获取 */
|
|
export const getProducts = async (params?: ProductListParams): Promise<ProductItem[]> => {
|
|
const response = await apiClient.get("/generation/tasks", { params })
|
|
const tasks = response.data.items || response.data || []
|
|
return tasks.map(mapTaskToProductItem)
|
|
}
|
|
|
|
/** 获取单个成品详情 — 通过 task ID 获取结果 */
|
|
export const getProduct = async (productId: string): Promise<ProductItem> => {
|
|
const response = await apiClient.get(`/generation/tasks/${productId}`)
|
|
return mapTaskToProductItem(response.data)
|
|
}
|
|
|
|
/** 删除成品 — 删除 generation task */
|
|
export const deleteProduct = async (productId: string): Promise<void> => {
|
|
await apiClient.delete(`/generation/tasks/${productId}`)
|
|
}
|
|
|
|
/** 获取成品下载链接 — 从 generation task results 获取 */
|
|
export const getProductDownloadUrl = async (
|
|
productId: string,
|
|
): Promise<{ url: string; expires_at: string }> => {
|
|
const videos = await getGenerationTaskResults(productId)
|
|
const video = videos[0]
|
|
if (!video?.download_url) throw new Error("下载链接不可用")
|
|
return { url: video.download_url, expires_at: "" }
|
|
}
|
|
|
|
/** 更新复核状态 — TODO: 后端暂无对应端点,暂存本地状态 */
|
|
export const updateReviewStatus = async (
|
|
productId: string,
|
|
status: ReviewStatus,
|
|
): Promise<ProductItem> => {
|
|
// 后端暂无 /generation/tasks/{id}/review 端点
|
|
// 暂时返回当前状态,后续可扩展
|
|
const product = await getProduct(productId)
|
|
return { ...product, review_status: status }
|
|
}
|
|
|
|
/** 发起批量下载 — TODO: 后端暂无对应端点 */
|
|
export const batchDownload = async (videoIds: string[]): Promise<{ job_id: string }> => {
|
|
// 后端暂无 /generation/tasks/batch-download 端点
|
|
// 暂时返回模拟 job_id,后续可扩展
|
|
console.warn("[batchDownload] 后端暂无批量下载端点", videoIds)
|
|
return { job_id: `mock-${Date.now()}` }
|
|
}
|
|
|
|
/** 查询批量下载状态 — TODO: 后端暂无对应端点 */
|
|
export const getBatchDownloadStatus = async (jobId: string): Promise<BatchDownloadStatus> => {
|
|
// 后端暂无 /generation/tasks/batch-download/{jobId} 端点
|
|
// 暂时返回模拟状态,后续可扩展
|
|
console.warn("[getBatchDownloadStatus] 后端暂无批量下载状态端点", jobId)
|
|
return { job_id: jobId, status: "processing", progress: 0 }
|
|
}
|