use serde::{Deserialize, Serialize}; use chrono::{DateTime, Utc}; use std::path::PathBuf; /// 批量处理任务状态 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] pub enum BatchTaskStatus { /// 待处理 Pending, /// 处理中 Processing, /// 已完成 Completed, /// 失败 Failed, /// 已取消 Cancelled, } /// 批量处理任务 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BatchProcessingTask { pub id: String, pub name: String, pub workflow_template_id: i64, pub input_folder: PathBuf, pub output_folder: PathBuf, pub status: BatchTaskStatus, pub total_files: u32, pub processed_files: u32, pub failed_files: u32, pub created_at: DateTime, pub started_at: Option>, pub completed_at: Option>, pub error_message: Option, } /// 批量处理文件项 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BatchFileItem { pub id: String, pub batch_task_id: String, pub input_file_path: PathBuf, pub output_file_path: Option, pub status: BatchTaskStatus, pub execution_id: Option, pub error_message: Option, pub processed_at: Option>, } /// 创建批量处理任务请求 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CreateBatchTaskRequest { pub name: String, pub workflow_template_id: i64, pub input_folder: String, pub output_folder: String, pub file_extensions: Vec, // 支持的文件扩展名,如 ["jpg", "png", "jpeg"] pub recursive: bool, // 是否递归扫描子文件夹 } /// 批量处理进度信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BatchProcessingProgress { pub task_id: String, pub status: BatchTaskStatus, pub total_files: u32, pub processed_files: u32, pub failed_files: u32, pub current_file: Option, pub progress_percentage: f32, pub estimated_remaining_time: Option, // 秒 } /// 批量处理统计信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BatchProcessingStats { pub total_tasks: u32, pub active_tasks: u32, pub completed_tasks: u32, pub failed_tasks: u32, pub total_files_processed: u32, pub average_processing_time_per_file: f32, // 秒 } impl BatchProcessingTask { /// 创建新的批量处理任务 pub fn new(request: CreateBatchTaskRequest) -> Self { let now = Utc::now(); Self { id: format!("batch_{}", now.timestamp_millis()), name: request.name, workflow_template_id: request.workflow_template_id, input_folder: PathBuf::from(request.input_folder), output_folder: PathBuf::from(request.output_folder), status: BatchTaskStatus::Pending, total_files: 0, processed_files: 0, failed_files: 0, created_at: now, started_at: None, completed_at: None, error_message: None, } } /// 开始处理 pub fn start_processing(&mut self, total_files: u32) { self.status = BatchTaskStatus::Processing; self.started_at = Some(Utc::now()); self.total_files = total_files; self.processed_files = 0; self.failed_files = 0; } /// 更新进度 pub fn update_progress(&mut self, processed: u32, failed: u32) { self.processed_files = processed; self.failed_files = failed; } /// 完成处理 pub fn complete_processing(&mut self) { self.status = BatchTaskStatus::Completed; self.completed_at = Some(Utc::now()); } /// 标记失败 pub fn mark_failed(&mut self, error_message: String) { self.status = BatchTaskStatus::Failed; self.completed_at = Some(Utc::now()); self.error_message = Some(error_message); } /// 取消处理 pub fn cancel(&mut self) { self.status = BatchTaskStatus::Cancelled; self.completed_at = Some(Utc::now()); } /// 获取进度百分比 pub fn get_progress_percentage(&self) -> f32 { if self.total_files == 0 { return 0.0; } (self.processed_files as f32 / self.total_files as f32) * 100.0 } /// 获取处理时长(秒) pub fn get_duration_seconds(&self) -> Option { if let Some(started_at) = self.started_at { let end_time = self.completed_at.unwrap_or_else(Utc::now); Some((end_time - started_at).num_seconds()) } else { None } } } impl BatchFileItem { /// 创建新的文件项 pub fn new(batch_task_id: String, input_file_path: PathBuf) -> Self { Self { id: format!("file_{}_{}", batch_task_id, input_file_path.file_name().unwrap_or_default().to_string_lossy()), batch_task_id, input_file_path, output_file_path: None, status: BatchTaskStatus::Pending, execution_id: None, error_message: None, processed_at: None, } } /// 开始处理 pub fn start_processing(&mut self, execution_id: i64) { self.status = BatchTaskStatus::Processing; self.execution_id = Some(execution_id); } /// 完成处理 pub fn complete_processing(&mut self, output_file_path: PathBuf) { self.status = BatchTaskStatus::Completed; self.output_file_path = Some(output_file_path); self.processed_at = Some(Utc::now()); } /// 标记失败 pub fn mark_failed(&mut self, error_message: String) { self.status = BatchTaskStatus::Failed; self.error_message = Some(error_message); self.processed_at = Some(Utc::now()); } }