封装jsonrpc通信机制

This commit is contained in:
root
2025-07-10 22:26:29 +08:00
parent bda9eb1a6b
commit 920b0462b5
6 changed files with 441 additions and 24 deletions

View 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()
*/

View File

@@ -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
}

View File

@@ -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
View 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

View File

@@ -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,

View File

@@ -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."
}