/** * 素材相关 API */ import apiClient from './client'; export interface AssetItem { id: string; workspace_id: string; project_id: string; library_id: string; name: string; storage_key: string; mime_type: string; metadata: Record; file_size?: number; status?: string; classification_status?: string | null; quality_score?: number | null; } export interface AssetLibraryItem { id: string; workspace_id: string; project_id: string; name: string; kind: 'video' | 'voice' | 'image'; asset_count?: number; total_size?: number; } export interface IngestJob { id: string; workspace_id: string; project_id: string; library_id: string; storage_key: string; status: 'pending' | 'processing' | 'completed' | 'failed'; error_message: string; result_asset_id: string; } export interface ClassificationJob { id: string; workspace_id: string; project_id: string; asset_id: string; status: 'pending' | 'processing' | 'completed' | 'failed'; classification: string; confidence: number; error_message: string; } export interface ProjectAssetDiagnosis { workspace_id: string; project_id: string; readiness_score: number; readiness_label: string; total_assets: number; ready_assets: number; video_assets: number; image_assets: number; voice_assets: number; total_duration_seconds: number; estimated_video_count: number; used_assets: number; unused_assets: number; pending_review_assets: number; smart_views: Array<{ key: string; label: string; count: number; description: string }>; gaps: Array<{ key: string; severity: 'critical' | 'warning' | 'info'; message: string; recommendation: string }>; } export const getProjectAssetDiagnosis = async (projectId: string): Promise => { const response = await apiClient.get(`/projects/${projectId}/asset-diagnosis`); return response.data; }; export const getAssetLibraries = async (projectId: string): Promise => { const response = await apiClient.get('/asset-libraries', { params: { project_id: projectId }, }); return response.data.items; }; export const createAssetLibrary = async (data: { workspace_id: string; project_id: string; name: string; kind: 'video' | 'voice' | 'image'; }): Promise => { const response = await apiClient.post('/asset-libraries', data); return response.data; }; export const getAssets = async (libraryId: string): Promise => { const response = await apiClient.get('/assets', { params: { library_id: libraryId }, }); return response.data.items; }; export const updateAssetReviewStatus = async ( assetId: string, reviewStatus: 'pending_review' | 'approved' | 'rejected' ): Promise => { const response = await apiClient.patch(`/assets/${assetId}/review`, { review_status: reviewStatus, }); return response.data; }; export const uploadAsset = async ( formData: FormData ): Promise<{ storage_key: string; ingest_job_id: string; url: string }> => { const response = await apiClient.post('/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' }, timeout: 30 * 60 * 1000, }); return response.data; }; export const prepareDirectUpload = async (data: { workspace_id: string; project_id: string; library_id: string; filename: string; content_type: string; file_size: number; }): Promise<{ upload_url: string; method: string; storage_key: string; expires_at: string; fields: Record; max_size_bytes: number; }> => { const response = await apiClient.post('/upload/direct/prepare', data); return response.data; }; export const completeDirectUpload = async (data: { workspace_id: string; project_id: string; library_id: string; storage_key: string; }): Promise<{ storage_key: string; ingest_job_id: string }> => { const response = await apiClient.post('/upload/direct/complete', data); return response.data; }; export const uploadAssetDirect = async (data: { file: File; workspace_id: string; project_id: string; library_id: string; }): Promise<{ storage_key: string; ingest_job_id: string }> => { const prepared = await prepareDirectUpload({ workspace_id: data.workspace_id, project_id: data.project_id, library_id: data.library_id, filename: data.file.name, content_type: data.file.type || 'application/octet-stream', file_size: data.file.size, }); const directForm = new FormData(); Object.entries(prepared.fields).forEach(([key, value]) => directForm.append(key, value)); directForm.append('file', data.file); const uploadResponse = await fetch(prepared.upload_url, { method: prepared.method, body: directForm, }); if (!uploadResponse.ok) { throw new Error(`OSS direct upload failed: ${uploadResponse.status}`); } return completeDirectUpload({ workspace_id: data.workspace_id, project_id: data.project_id, library_id: data.library_id, storage_key: prepared.storage_key, }); }; export const getIngestJob = async (jobId: string): Promise => { const response = await apiClient.get(`/ingest-jobs/${jobId}`); return response.data; }; export const submitClassificationJob = async (data: { workspace_id: string; project_id: string; asset_id: string; }): Promise => { const response = await apiClient.post('/classification-jobs', data); return response.data; }; export const getClassificationJob = async (jobId: string): Promise => { const response = await apiClient.get(`/classification-jobs/${jobId}`); return response.data; };