From 920b0462b5371064bdb7283954d007dc01ff19f6 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 10 Jul 2025 22:26:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=81=E8=A3=85jsonrpc=E9=80=9A=E4=BF=A1?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/commands/examples.rs | 194 +++++++++++++++++++++++++++++ src-tauri/src/commands/template.rs | 45 ++++--- src-tauri/src/lib.rs | 1 + src-tauri/src/macros.rs | 129 +++++++++++++++++++ src-tauri/src/python_executor.rs | 94 ++++++++++++++ src-tauri/tauri.conf.json | 2 +- 6 files changed, 441 insertions(+), 24 deletions(-) create mode 100644 src-tauri/src/commands/examples.rs create mode 100644 src-tauri/src/macros.rs diff --git a/src-tauri/src/commands/examples.rs b/src-tauri/src/commands/examples.rs new file mode 100644 index 0000000..c596a10 --- /dev/null +++ b/src-tauri/src/commands/examples.rs @@ -0,0 +1,194 @@ +/// Examples of using the generic Python progress support + +use serde::{Deserialize, Serialize}; +use crate::python_executor::execute_python_action_with_progress; +use crate::{python_action_command, simple_python_command}; +use tauri::AppHandle; + +#[derive(Debug, Deserialize)] +pub struct VideoGenerationRequest { + pub image_path: String, + pub prompt: String, + pub output_path: String, +} + +#[derive(Debug, Deserialize)] +pub struct DataProcessingRequest { + pub input_file: String, + pub output_file: String, + pub processing_type: String, +} + +// Example 1: Using the macro for simple commands (no parameters) +simple_python_command! { + name: get_system_status, + module: "python_core.utils.system_monitor", + action: "get_status", + event: "system-status-progress" +} + +// Example 2: Using the macro for commands with request objects +python_action_command! { + name: process_video_with_progress, + module: "python_core.ai_video.video_generator", + action: "generate", + event: "video-generation-progress", + request: VideoGenerationRequest, + params: |req| [ + ("--image_path", req.image_path.as_str()), + ("--prompt", req.prompt.as_str()), + ("--output_path", req.output_path.as_str()) + ] +} + +// Example 3: Using the macro for data processing +python_action_command! { + name: process_data_with_progress, + module: "python_core.services.data_processor", + action: "process", + event: "data-processing-progress", + request: DataProcessingRequest, + params: |req| [ + ("--input_file", req.input_file.as_str()), + ("--output_file", req.output_file.as_str()), + ("--type", req.processing_type.as_str()) + ] +} + +// Example 4: Using the macro for individual parameters +python_action_command! { + name: backup_database_with_progress, + module: "python_core.services.database_manager", + action: "backup", + event: "database-backup-progress", + params: [ + "--backup_path" => backup_path: String, + "--compression" => compression_type: String + ] +} + +// Example 5: Manual implementation for complex cases +#[tauri::command] +pub async fn complex_task_with_progress( + app: AppHandle, + task_config: serde_json::Value, +) -> Result { + // Extract parameters from complex config + let task_type = task_config.get("type") + .and_then(|v| v.as_str()) + .unwrap_or("default"); + + let priority = task_config.get("priority") + .and_then(|v| v.as_str()) + .unwrap_or("normal"); + + let params = &[ + ("--config", serde_json::to_string(&task_config).unwrap().as_str()), + ("--type", task_type), + ("--priority", priority), + ]; + + execute_python_action_with_progress( + app, + "python_core.services.task_processor", + "execute_complex_task", + params, + "complex-task-progress", + None, + ).await +} + +// Example 6: Batch operations +#[tauri::command] +pub async fn batch_convert_files_with_progress( + app: AppHandle, + file_paths: Vec, + output_format: String, +) -> Result { + // Serialize file paths as JSON for Python + let files_json = serde_json::to_string(&file_paths) + .map_err(|e| format!("Failed to serialize file paths: {}", e))?; + + let params = &[ + ("--files", files_json.as_str()), + ("--format", output_format.as_str()), + ]; + + execute_python_action_with_progress( + app, + "python_core.services.file_converter", + "batch_convert", + params, + "file-conversion-progress", + None, + ).await +} + +// Example 7: Machine Learning Training +#[derive(Debug, Deserialize)] +pub struct TrainingRequest { + pub dataset_path: String, + pub model_type: String, + pub epochs: u32, + pub learning_rate: f64, +} + +python_action_command! { + name: train_model_with_progress, + module: "python_core.ml.trainer", + action: "train", + event: "model-training-progress", + request: TrainingRequest, + params: |req| [ + ("--dataset", req.dataset_path.as_str()), + ("--model", req.model_type.as_str()), + ("--epochs", req.epochs.to_string().as_str()), + ("--lr", req.learning_rate.to_string().as_str()) + ] +} + +/* +Frontend Usage Examples: + +// TypeScript/JavaScript +import { listen } from '@tauri-apps/api/event' +import { invoke } from '@tauri-apps/api/core' + +// Example 1: Simple command +const unlisten1 = await listen('system-status-progress', (event) => { + console.log('System status:', event.payload) +}) +const result1 = await invoke('get_system_status') + +// Example 2: Video generation +const unlisten2 = await listen('video-generation-progress', (event) => { + const progress = event.payload + updateProgressBar(progress.progress) + updateStatusMessage(progress.message) +}) + +const videoRequest = { + image_path: '/path/to/image.jpg', + prompt: 'A beautiful sunset', + output_path: '/path/to/output.mp4' +} +const result2 = await invoke('process_video_with_progress', { request: videoRequest }) + +// Example 3: Batch file conversion +const unlisten3 = await listen('file-conversion-progress', (event) => { + const progress = event.payload + if (progress.details?.current_file) { + console.log(`Processing: ${progress.details.current_file}`) + } +}) + +const result3 = await invoke('batch_convert_files_with_progress', { + filePaths: ['/file1.txt', '/file2.txt'], + outputFormat: 'pdf' +}) + +// Clean up listeners +unlisten1() +unlisten2() +unlisten3() +*/ diff --git a/src-tauri/src/commands/template.rs b/src-tauri/src/commands/template.rs index 9017f2d..edc91c6 100644 --- a/src-tauri/src/commands/template.rs +++ b/src-tauri/src/commands/template.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use crate::python_executor::{execute_python_command, execute_python_with_events}; +use crate::python_executor::{execute_python_command, execute_python_action_with_progress}; use tauri::AppHandle; #[derive(Debug, Deserialize)] @@ -50,17 +50,16 @@ pub async fn batch_import_templates_with_progress( app: AppHandle, request: BatchImportRequest ) -> Result { - let args = vec![ - "-m".to_string(), - "python_core.services.template_manager".to_string(), - "--action".to_string(), - "batch_import".to_string(), - "--source_folder".to_string(), - request.source_folder, - ]; + let params = &[("--source_folder", request.source_folder.as_str())]; - // Execute with progress monitoring via Tauri events - execute_python_with_events(app, &args, None, "template-import-progress").await + execute_python_action_with_progress( + app, + "python_core.services.template_manager", + "batch_import", + params, + "template-import-progress", + None, + ).await } #[tauri::command] @@ -112,18 +111,18 @@ pub async fn generate_video_with_progress( prompt: String, output_path: String, ) -> Result { - let args = vec![ - "-m".to_string(), - "python_core.ai_video.video_generator".to_string(), - "--image_path".to_string(), - image_path, - "--prompt".to_string(), - prompt, - "--output_path".to_string(), - output_path, + let params = &[ + ("--image_path", image_path.as_str()), + ("--prompt", prompt.as_str()), + ("--output_path", output_path.as_str()), ]; - // Execute with progress monitoring via Tauri events - // Frontend can listen to "video-generation-progress" event - execute_python_with_events(app, &args, None, "video-generation-progress").await + execute_python_action_with_progress( + app, + "python_core.ai_video.video_generator", + "generate", + params, + "video-generation-progress", + None, + ).await } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 1e476d1..ac9ec10 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,5 +1,6 @@ mod commands; mod python_executor; +mod macros; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { diff --git a/src-tauri/src/macros.rs b/src-tauri/src/macros.rs new file mode 100644 index 0000000..cbe4523 --- /dev/null +++ b/src-tauri/src/macros.rs @@ -0,0 +1,129 @@ +/// Macros for creating Python commands with progress support + +/// Create a Tauri command that executes a Python action with progress +/// +/// # Example +/// ```rust +/// python_action_command! { +/// name: batch_import_templates_with_progress, +/// module: "python_core.services.template_manager", +/// action: "batch_import", +/// event: "template-import-progress", +/// request: BatchImportRequest, +/// params: |req| [("--source_folder", req.source_folder.as_str())] +/// } +/// ``` +#[macro_export] +macro_rules! python_action_command { + ( + name: $name:ident, + module: $module:expr, + action: $action:expr, + event: $event:expr, + request: $request_type:ty, + params: |$req:ident| [$($param_key:expr, $param_value:expr),* $(,)?] + ) => { + #[tauri::command] + pub async fn $name( + app: tauri::AppHandle, + request: $request_type + ) -> Result { + let $req = &request; + let params = &[ + $(($param_key, $param_value)),* + ]; + + $crate::python_executor::execute_python_action_with_progress( + app, + $module, + $action, + params, + $event, + None, + ).await + } + }; + + ( + name: $name:ident, + module: $module:expr, + action: $action:expr, + event: $event:expr, + params: [$($param_key:expr => $param_name:ident: $param_type:ty),* $(,)?] + ) => { + #[tauri::command] + pub async fn $name( + app: tauri::AppHandle, + $($param_name: $param_type),* + ) -> Result { + let params = &[ + $(($param_key, $param_name.as_str())),* + ]; + + $crate::python_executor::execute_python_action_with_progress( + app, + $module, + $action, + params, + $event, + None, + ).await + } + }; + + ( + name: $name:ident, + module: $module:expr, + action: $action:expr, + event: $event:expr + ) => { + #[tauri::command] + pub async fn $name( + app: tauri::AppHandle + ) -> Result { + $crate::python_executor::execute_python_action_with_progress( + app, + $module, + $action, + &[], + $event, + None, + ).await + } + }; +} + +/// Helper macro to create simple Python action commands +/// +/// # Example +/// ```rust +/// simple_python_command! { +/// name: get_all_templates, +/// module: "python_core.services.template_manager", +/// action: "get_templates", +/// event: "template-list-progress" +/// } +/// ``` +#[macro_export] +macro_rules! simple_python_command { + ( + name: $name:ident, + module: $module:expr, + action: $action:expr, + event: $event:expr + ) => { + #[tauri::command] + pub async fn $name(app: tauri::AppHandle) -> Result { + $crate::python_executor::execute_python_action_with_progress( + app, + $module, + $action, + &[], + $event, + None, + ).await + } + }; +} + +// Macros are automatically available when the module is included diff --git a/src-tauri/src/python_executor.rs b/src-tauri/src/python_executor.rs index 91e2e93..ddbba56 100644 --- a/src-tauri/src/python_executor.rs +++ b/src-tauri/src/python_executor.rs @@ -146,6 +146,100 @@ pub async fn execute_python_with_events( execute_python_command_with_progress(app, args, config, Some(progress_callback)).await } +/// Python command builder for easier command construction +#[allow(dead_code)] +pub struct PythonCommandBuilder { + module: String, + args: Vec<(String, String)>, +} + +#[allow(dead_code)] +impl PythonCommandBuilder { + pub fn new(module: &str) -> Self { + Self { + module: module.to_string(), + args: Vec::new(), + } + } + + pub fn arg(mut self, key: &str, value: &str) -> Self { + self.args.push((key.to_string(), value.to_string())); + self + } + + pub fn action(self, action: &str) -> Self { + self.arg("--action", action) + } + + pub fn build(self) -> Vec { + let mut result = vec![ + "-m".to_string(), + self.module, + ]; + + for (key, value) in self.args { + result.push(key); + result.push(value); + } + + result + } +} + +/// Execute a Python module with progress support +#[allow(dead_code)] +pub async fn execute_python_module_with_progress( + app: tauri::AppHandle, + module: &str, + action: &str, + params: Vec<(&str, &str)>, + event_name: &str, + config: Option, +) -> Result { + let mut builder = PythonCommandBuilder::new(module).action(action); + + for (key, value) in params { + builder = builder.arg(key, value); + } + + let args = builder.build(); + execute_python_with_events(app, &args, config, event_name).await +} + +/// Helper function to create Python module commands with progress +/// +/// # Arguments +/// * `app` - Tauri app handle +/// * `module` - Python module path (e.g., "python_core.services.template_manager") +/// * `action` - Action to perform (e.g., "batch_import") +/// * `params` - Additional parameters as key-value pairs +/// * `event_name` - Event name for progress updates +/// * `config` - Optional executor configuration +#[allow(dead_code)] +pub async fn execute_python_action_with_progress( + app: tauri::AppHandle, + module: &str, + action: &str, + params: &[(&str, &str)], + event_name: &str, + config: Option, +) -> Result { + let mut args = vec![ + "-m".to_string(), + module.to_string(), + "--action".to_string(), + action.to_string(), + ]; + + // Add additional parameters + for (key, value) in params { + args.push(key.to_string()); + args.push(value.to_string()); + } + + execute_python_with_events(app, &args, config, event_name).await +} + /// Internal implementation for Python command execution async fn execute_python_internal

( _app: tauri::AppHandle, diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 14ddca7..48c39d8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -38,7 +38,7 @@ "icons/icon.icns", "icons/icon.ico" ], - "category": "VideoUtility", + "category": "Video", "shortDescription": "Professional video editing software", "longDescription": "MixVideo V2 is a modern video editing software built with Tauri and Python, featuring professional editing tools, AI-assisted editing, and advanced audio processing capabilities." }