封装jsonrpc通信机制
This commit is contained in:
194
src-tauri/src/commands/examples.rs
Normal file
194
src-tauri/src/commands/examples.rs
Normal file
@@ -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<String, String> {
|
||||
// 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<String>,
|
||||
output_format: String,
|
||||
) -> Result<String, String> {
|
||||
// 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()
|
||||
*/
|
||||
@@ -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<String, String> {
|
||||
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<String, String> {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
mod commands;
|
||||
mod python_executor;
|
||||
mod macros;
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
|
||||
129
src-tauri/src/macros.rs
Normal file
129
src-tauri/src/macros.rs
Normal file
@@ -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<String, String> {
|
||||
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<String, String> {
|
||||
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<String, String> {
|
||||
$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<String, String> {
|
||||
$crate::python_executor::execute_python_action_with_progress(
|
||||
app,
|
||||
$module,
|
||||
$action,
|
||||
&[],
|
||||
$event,
|
||||
None,
|
||||
).await
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Macros are automatically available when the module is included
|
||||
@@ -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<String> {
|
||||
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<PythonExecutorConfig>,
|
||||
) -> Result<String, String> {
|
||||
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<PythonExecutorConfig>,
|
||||
) -> Result<String, String> {
|
||||
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<P>(
|
||||
_app: tauri::AppHandle,
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user