diff --git a/Cargo.lock b/Cargo.lock index d46aeaa..6a555d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,6 +1672,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + [[package]] name = "httparse" version = "1.10.1" @@ -2304,6 +2310,7 @@ name = "mixvideo-desktop" version = "0.1.9" dependencies = [ "anyhow", + "base64 0.22.1", "chrono", "dirs 5.0.1", "lazy_static", @@ -4184,6 +4191,7 @@ dependencies = [ "gtk", "heck 0.5.0", "http 1.3.1", + "http-range", "jni", "libc", "log", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 109e4f5..136cb4d 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] tauri-build = { version = "2", features = [] } [dependencies] -tauri = { version = "2", features = [] } +tauri = { version = "2", features = ["protocol-asset"] } tauri-plugin-opener = "2" tauri-plugin-fs = "2" tauri-plugin-dialog = "2" @@ -33,6 +33,7 @@ thiserror = "1.0" dirs = "5.0" md5 = "0.7" lazy_static = "1.4" +base64 = "0.22" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "chrono"] } tracing-appender = "0.2" diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index b330042..60981b4 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -11,10 +11,6 @@ pub mod presentation; pub mod app_state; pub mod config; -// 测试模块 -#[cfg(test)] -mod tests; - use app_state::AppState; use presentation::commands; use tauri::Manager; @@ -78,6 +74,7 @@ pub fn run() { commands::material_commands::detect_video_scenes, commands::material_commands::generate_video_thumbnail, commands::material_commands::generate_and_save_segment_thumbnail, + commands::material_commands::read_thumbnail_as_data_url, commands::material_commands::test_scene_detection, commands::material_commands::get_material_segments, commands::material_commands::test_video_split, diff --git a/apps/desktop/src-tauri/src/presentation/commands/material_commands.rs b/apps/desktop/src-tauri/src/presentation/commands/material_commands.rs index 0234883..881675f 100644 --- a/apps/desktop/src-tauri/src/presentation/commands/material_commands.rs +++ b/apps/desktop/src-tauri/src/presentation/commands/material_commands.rs @@ -851,6 +851,30 @@ pub async fn generate_and_save_segment_thumbnail( Ok(Some(thumbnail_path_str)) } +/// 读取缩略图文件并转换为base64数据URL +#[command] +pub async fn read_thumbnail_as_data_url(file_path: String) -> Result { + use std::fs; + use base64::{Engine as _, engine::general_purpose}; + + // 去掉Windows长路径前缀 + let clean_path = if file_path.starts_with("\\\\?\\") { + &file_path[4..] + } else { + &file_path + }; + + // 读取文件 + let file_data = fs::read(clean_path) + .map_err(|e| format!("读取文件失败: {}", e))?; + + // 转换为base64 + let base64_data = general_purpose::STANDARD.encode(&file_data); + + // 返回data URL + Ok(format!("data:image/jpeg;base64,{}", base64_data)) +} + /// 测试场景检测命令(用于调试) #[command] pub async fn test_scene_detection(file_path: String) -> Result { diff --git a/apps/desktop/src-tauri/src/tests/integration/binding_management_integration_tests.rs b/apps/desktop/src-tauri/src/tests/integration/binding_management_integration_tests.rs deleted file mode 100644 index ecfda42..0000000 --- a/apps/desktop/src-tauri/src/tests/integration/binding_management_integration_tests.rs +++ /dev/null @@ -1,437 +0,0 @@ -/** - * 绑定管理功能集成测试 - * 测试项目-模板绑定和素材-模特绑定的完整工作流 - */ - -#[cfg(test)] -mod tests { - use super::*; - use crate::data::models::{ - project::Project, - template::Template, - material::{Material, MaterialType, ProcessingStatus}, - model::Model, - project_template_binding::{ProjectTemplateBinding, BindingType, BindingStatus, CreateProjectTemplateBindingRequest}, - }; - use crate::data::repositories::{ - project_repository::ProjectRepository, - template_repository::TemplateRepository, - material_repository::MaterialRepository, - model_repository::ModelRepository, - project_template_binding_repository::ProjectTemplateBindingRepository, - }; - use crate::business::services::{ - project_template_binding_service::ProjectTemplateBindingService, - material_service::MaterialService, - }; - use crate::infrastructure::database::Database; - use std::sync::{Arc, Mutex}; - use uuid::Uuid; - - /// 创建完整的测试数据库 - fn create_integration_test_database() -> Arc> { - let conn = rusqlite::Connection::open_in_memory().unwrap(); - - // 创建所有必要的表 - conn.execute( - "CREATE TABLE projects ( - id TEXT PRIMARY KEY, - name TEXT NOT NULL, - path TEXT NOT NULL, - description TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP - )", - [], - ).unwrap(); - - conn.execute( - "CREATE TABLE templates ( - id TEXT PRIMARY KEY, - name TEXT NOT NULL, - description TEXT, - file_path TEXT NOT NULL, - import_status TEXT NOT NULL, - project_id TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP - )", - [], - ).unwrap(); - - conn.execute( - "CREATE TABLE materials ( - id TEXT PRIMARY KEY, - project_id TEXT NOT NULL, - name TEXT NOT NULL, - original_path TEXT NOT NULL, - file_size INTEGER NOT NULL, - md5_hash TEXT NOT NULL, - material_type TEXT NOT NULL, - processing_status TEXT NOT NULL, - metadata TEXT, - scene_detection TEXT, - model_id TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, - processed_at DATETIME, - error_message TEXT - )", - [], - ).unwrap(); - - conn.execute( - "CREATE TABLE models ( - id TEXT PRIMARY KEY, - name TEXT NOT NULL, - stage_name TEXT, - description TEXT, - avatar_url TEXT, - tags TEXT, - is_active INTEGER DEFAULT 1, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP - )", - [], - ).unwrap(); - - conn.execute( - "CREATE TABLE project_template_bindings ( - id TEXT PRIMARY KEY, - project_id TEXT NOT NULL, - template_id TEXT NOT NULL, - binding_name TEXT, - description TEXT, - priority INTEGER DEFAULT 0, - is_active INTEGER DEFAULT 1, - binding_type TEXT NOT NULL, - binding_status TEXT NOT NULL, - metadata TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, - UNIQUE (project_id, template_id) - )", - [], - ).unwrap(); - - Arc::new(Mutex::new(conn)) - } - - /// 创建测试数据 - struct TestData { - project: Project, - templates: Vec