639f73b16d
CI/CD Pipeline / Frontend Lint (push) Failing after 53s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 59s
CI/CD Pipeline / Unit Tests (push) Successful in 1m55s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m4s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 2m26s
CI/CD Pipeline / Build Staging API Image (push) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Has been skipped
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m33s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 1m11s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m8s
# Conflicts: # apps/web/src/api/products.ts # apps/web/src/pages/products/ProductLibrary.tsx
147 lines
4.6 KiB
TypeScript
147 lines
4.6 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 };
|
|
};
|