diff --git a/apps/desktop/src-tauri/src/business/services/video_classification_queue.rs b/apps/desktop/src-tauri/src/business/services/video_classification_queue.rs index aca5034..ea9f031 100644 --- a/apps/desktop/src-tauri/src/business/services/video_classification_queue.rs +++ b/apps/desktop/src-tauri/src/business/services/video_classification_queue.rs @@ -85,6 +85,18 @@ impl VideoClassificationQueue { *status = QueueStatus::Running; drop(status); + // 修复数据库中的日期格式问题 + match self.service.fix_date_formats().await { + Ok(fixed_count) => { + if fixed_count > 0 { + println!("🔧 队列启动时修复了 {} 个任务的日期格式", fixed_count); + } + } + Err(e) => { + println!("⚠️ 修复日期格式时出错: {}", e); + } + } + // 恢复卡住的任务状态 match self.service.recover_stuck_tasks().await { Ok(recovered_count) => { diff --git a/apps/desktop/src-tauri/src/business/services/video_classification_service.rs b/apps/desktop/src-tauri/src/business/services/video_classification_service.rs index 97d3e4d..3a80220 100644 --- a/apps/desktop/src-tauri/src/business/services/video_classification_service.rs +++ b/apps/desktop/src-tauri/src/business/services/video_classification_service.rs @@ -323,6 +323,11 @@ impl VideoClassificationService { self.video_repo.recover_stuck_tasks().await } + /// 修复数据库中的日期格式问题 + pub async fn fix_date_formats(&self) -> Result { + self.video_repo.fix_date_formats().await + } + /// 重试失败的任务 pub async fn retry_failed_task(&self, _task_id: &str) -> Result<()> { // 这里需要实现重试逻辑 diff --git a/apps/desktop/src-tauri/src/data/repositories/video_classification_repository.rs b/apps/desktop/src-tauri/src/data/repositories/video_classification_repository.rs index 407d6ab..ff395a7 100644 --- a/apps/desktop/src-tauri/src/data/repositories/video_classification_repository.rs +++ b/apps/desktop/src-tauri/src/data/repositories/video_classification_repository.rs @@ -346,8 +346,24 @@ impl VideoClassificationRepository { error_message: row.get(11)?, started_at: row.get::<_, Option>(12)?.and_then(|s| chrono::DateTime::parse_from_rfc3339(&s).ok()).map(|dt| dt.with_timezone(&Utc)), completed_at: row.get::<_, Option>(13)?.and_then(|s| chrono::DateTime::parse_from_rfc3339(&s).ok()).map(|dt| dt.with_timezone(&Utc)), - created_at: chrono::DateTime::parse_from_rfc3339(&row.get::<_, String>(14)?).map_err(|_e| rusqlite::Error::InvalidColumnType(14, "created_at".to_string(), rusqlite::types::Type::Text))?.with_timezone(&Utc), - updated_at: chrono::DateTime::parse_from_rfc3339(&row.get::<_, String>(15)?).map_err(|_e| rusqlite::Error::InvalidColumnType(15, "updated_at".to_string(), rusqlite::types::Type::Text))?.with_timezone(&Utc), + created_at: { + let created_at_str: String = row.get(14)?; + chrono::DateTime::parse_from_rfc3339(&created_at_str) + .map_err(|e| { + println!("❌ 解析created_at失败: '{}', 错误: {}", created_at_str, e); + rusqlite::Error::InvalidColumnType(14, "created_at".to_string(), rusqlite::types::Type::Text) + })? + .with_timezone(&Utc) + }, + updated_at: { + let updated_at_str: String = row.get(15)?; + chrono::DateTime::parse_from_rfc3339(&updated_at_str) + .map_err(|e| { + println!("❌ 解析updated_at失败: '{}', 错误: {}", updated_at_str, e); + rusqlite::Error::InvalidColumnType(15, "updated_at".to_string(), rusqlite::types::Type::Text) + })? + .with_timezone(&Utc) + }, }) })?; @@ -594,17 +610,80 @@ impl VideoClassificationRepository { } // 重置任务状态 + let now_rfc3339 = chrono::Utc::now().to_rfc3339(); let updated = conn.execute( "UPDATE video_classification_tasks - SET status = ?, started_at = NULL, updated_at = datetime('now') + SET status = ?, started_at = NULL, updated_at = ? WHERE status = ? OR status = ?", - [&pending_json, &uploading_json, &analyzing_json] + [&pending_json, &now_rfc3339, &uploading_json, &analyzing_json] )?; println!("✅ 已恢复 {} 个任务状态为Pending", updated); Ok(updated) } + /// 修复数据库中的日期格式问题 + /// 将SQLite格式的日期转换为RFC3339格式 + pub async fn fix_date_formats(&self) -> Result { + let conn = self.database.get_connection(); + let conn = conn.lock().unwrap(); + + println!("🔧 开始修复数据库中的日期格式..."); + + // 查询所有可能有问题的任务 + let mut stmt = conn.prepare( + "SELECT id, created_at, updated_at FROM video_classification_tasks" + )?; + + let rows: Vec<(String, String, String)> = stmt.query_map([], |row| { + Ok(( + row.get::<_, String>(0)?, + row.get::<_, String>(1)?, + row.get::<_, String>(2)?, + )) + })?.collect::, _>>()?; + + let mut fixed_count = 0; + + for (id, created_at, updated_at) in rows { + let mut needs_update = false; + let mut new_created_at = created_at.clone(); + let mut new_updated_at = updated_at.clone(); + + // 检查并修复created_at + if chrono::DateTime::parse_from_rfc3339(&created_at).is_err() { + // 尝试解析SQLite格式的日期 + if let Ok(dt) = chrono::NaiveDateTime::parse_from_str(&created_at, "%Y-%m-%d %H:%M:%S") { + new_created_at = dt.and_utc().to_rfc3339(); + needs_update = true; + println!("🔧 修复created_at: {} -> {}", created_at, new_created_at); + } + } + + // 检查并修复updated_at + if chrono::DateTime::parse_from_rfc3339(&updated_at).is_err() { + // 尝试解析SQLite格式的日期 + if let Ok(dt) = chrono::NaiveDateTime::parse_from_str(&updated_at, "%Y-%m-%d %H:%M:%S") { + new_updated_at = dt.and_utc().to_rfc3339(); + needs_update = true; + println!("🔧 修复updated_at: {} -> {}", updated_at, new_updated_at); + } + } + + // 更新记录 + if needs_update { + conn.execute( + "UPDATE video_classification_tasks SET created_at = ?, updated_at = ? WHERE id = ?", + [&new_created_at, &new_updated_at, &id] + )?; + fixed_count += 1; + } + } + + println!("✅ 已修复 {} 个任务的日期格式", fixed_count); + Ok(fixed_count) + } + /// 根据ID获取分类任务 pub async fn get_task_by_id(&self, task_id: &str) -> Result> { let conn = self.database.get_connection();