From 0063c364f0d763a4686837f0d53da395c91c011a Mon Sep 17 00:00:00 2001 From: Zhicheng Zhang <20331014+zzc-tongji@users.noreply.github.com> Date: Tue, 12 May 2026 18:17:44 +0800 Subject: [PATCH 1/3] update launch task with template variable support --- src-tauri/src/commands/utils.rs | 115 ++++++++++++++++++++++++++++++++ src-tauri/src/mxu_actions.rs | 110 +++++++++++++++++++++++++++++- src/i18n/locales/en-US.ts | 3 +- src/i18n/locales/ja-JP.ts | 3 +- src/i18n/locales/ko-KR.ts | 3 +- src/i18n/locales/zh-CN.ts | 3 +- src/i18n/locales/zh-TW.ts | 3 +- src/types/specialTasks.ts | 1 + 8 files changed, 234 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/commands/utils.rs b/src-tauri/src/commands/utils.rs index d1ad39e2..cdd2fd2a 100644 --- a/src-tauri/src/commands/utils.rs +++ b/src-tauri/src/commands/utils.rs @@ -277,3 +277,118 @@ pub fn build_launch_command( cmd } + +/// 获取当前 instance 所有已勾选 task 的状态 +/// +/// - 输出为数组,按照 instance 中 task 的顺序排列。 +/// - 数组的每项是一个包含两个字符串的数组:[任务名称(i18n), 任务状态("idle","pending","running","succeeded","failed")]。 +pub fn get_checked_task_status_of_instance( + app_handle: Option<&AppHandle>, + instance_id: Option<&str>, +) -> Vec> { + let app_config_state = app_handle + .and_then(|app| { + Some( + app.try_state::>() + .unwrap(), + ) + }) + .unwrap(); + let translations = app_config_state.translations.lock().ok().unwrap(); // content as (dist => locales/interface/.ts) + let config = app_config_state.config.lock().ok().unwrap(); // content as (dist => configs/mxu-.ts) + + // i18n + let language = config + .get("settings") + .and_then(|v| v.get("language")) + .and_then(|v| v.as_str()) + .unwrap_or("system"); + let i18n = translations + .get(match language { + // get i18n task name by (i18n["task..label"]) + "zh-TW" => "zh_tw", + "en-US" => "en_us", + "ja-JP" => "ja_jp", + "ko-KR" => "ko_kr", + _ => "zh_cn", + }) + .unwrap_or_default(); + + // instance (config) + let id = instance_id.unwrap_or(""); + let instance_config_list = config.get("instances"); + let instance_config = instance_config_list + .unwrap() + .as_array() + .unwrap() + .iter() + .find(|inst| inst.get("id").and_then(|v| v.as_str()) == Some(id)) + .unwrap(); + + // instance (runtime) + let maa_state = app_handle + .and_then(|app| Some(app.try_state::>().unwrap())) + .unwrap(); + let instance_runtime_list = maa_state.instances.lock().ok().unwrap(); + let instance_runtime = instance_runtime_list + .get(instance_id.unwrap_or_default()) + .unwrap(); + + return instance_runtime + .task_run_state + .pending_task_ids + .iter() + .filter_map(|&maa_task_id| { + if let Some(selected_task_id) = + instance_runtime.task_run_state.mappings.get(&maa_task_id) + { + if let Some(status) = instance_runtime + .task_run_state + .statuses + .get(selected_task_id) + { + let task_config_list = instance_config.get("tasks").unwrap(); + let task_config = task_config_list + .as_array() + .unwrap() + .iter() + .find(|task| { + task.get("id").and_then(|v| v.as_str()) + == Some(selected_task_id.as_str()) + }) + .unwrap(); + let task_name = task_config + .get("taskName") + .unwrap() + .as_str() + .unwrap() + .to_string(); + let custom_name = task_config + .get("customName") + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); + let task_name_i18n = i18n + .get(format!("task.{}.label", task_name)) + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); + // custom name / task name (i18n) / task name + // => task status ("idle","pending","running","succeeded","failed") + let name: String = if !custom_name.is_empty() { + custom_name + } else if !task_name_i18n.is_empty() { + task_name_i18n + } else { + task_name + }; + Some(vec![name, status.to_string()]) + } else { + None + } + } else { + None + } + }) + .collect(); +} diff --git a/src-tauri/src/mxu_actions.rs b/src-tauri/src/mxu_actions.rs index 3b8d6cf6..efe08f35 100644 --- a/src-tauri/src/mxu_actions.rs +++ b/src-tauri/src/mxu_actions.rs @@ -2,6 +2,7 @@ //! //! 提供 MXU 特有的自定义动作实现,如 MXU_SLEEP 等 +use base64::{engine::general_purpose, Engine as _}; use chrono::TimeZone; use log::{info, warn}; use maa_framework::custom::FnAction; @@ -200,7 +201,62 @@ const MXU_LAUNCH_ACTION: &str = "MXU_LAUNCH_ACTION"; fn mxu_launch_action_fn( _ctx: &maa_framework::context::Context, args: &maa_framework::custom::ActionArgs, + app_handle: Option<&AppHandle>, + instance_id: Option<&str>, ) -> bool { + // + // {{STATUS}} + // + // success - 任务1 + // failed - 任务2 + // pending - 任务3 + // + let task_status = + crate::commands::utils::get_checked_task_status_of_instance(app_handle, instance_id); + let status = task_status + .iter() + .map(|row| format!("{} - {}", row[1], row[0])) + .collect::>() + .join("\n"); + // + // {{S_BASE64}} + // + // c3VjY2VzcyAtIOS7u+WKoTEKZmFpbGVkIC0g5Lu75YqhMgpwZW5kaW5nIC0g5Lu75YqhMw== + // + let s_base64 = general_purpose::STANDARD.encode(&status); + // + // {{S_CSV}} + // + // NAME,STATUS + // 任务1,success + // 任务2,failed + // 任务3,pending + // + let s_csv = format!( + "NAME,STATUS\n{}", + task_status + .iter() + .map(|row| format!("{},{}", row[0], row[1])) + .collect::>() + .join("\n") + ); + // + // {{S_JSON}} + // + // [["任务1","success"],["任务2","failed"],["任务3","pending"]] + // + let s_json = match serde_json::to_string(&task_status) { + Ok(v) => v, + Err(_) => String::from("[]"), + }; + // + // {{S_JSON_BASE64}} + // + // W1si5Lu75YqhMSIsInN1Y2Nlc3MiXSxbIuS7u+WKoTIiLCJmYWlsZWQiXSxbIuS7u+WKoTMiLCJwZW5kaW5nIl1d + // + let s_json_base64 = general_purpose::STANDARD.encode(&s_json); + info!("[MXU_LAUNCH] Generated task(s) status: {}", &s_json); + let param_str = args.param; info!("[MXU_LAUNCH] Received param: {}", param_str); @@ -224,7 +280,12 @@ fn mxu_launch_action_fn( .get("args") .and_then(|v| v.as_str()) .unwrap_or("") - .to_string(); + .to_string() + .replace("{{STATUS}}", &status) + .replace("{{S_BASE64}}", &s_base64) + .replace("{{S_CSV}}", &s_csv) + .replace("{{S_JSON}}", &s_json) + .replace("{{S_JSON_BASE64}}", &s_json_base64); let wait_for_exit = json .get("wait_for_exit") @@ -878,11 +939,56 @@ pub fn register_all_mxu_actions( reg_action!(MXU_SLEEP_ACTION, mxu_sleep_action_fn); reg_action!(MXU_WAITUNTIL_ACTION, mxu_waituntil_action_fn); - reg_action!(MXU_LAUNCH_ACTION, mxu_launch_action_fn); reg_action!(MXU_WEBHOOK_ACTION, mxu_webhook_action_fn); reg_action!(MXU_NOTIFY_ACTION, mxu_notify_action_fn); reg_action!(MXU_POWER_ACTION, mxu_power_action_fn); + // launch + + let launch_app_handle = app_handle.clone(); + let launch_instance_id = instance_id.to_string(); + let launch_wrapper = move |ctx: &maa_framework::context::Context, + args: &maa_framework::custom::ActionArgs| + -> bool { + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + mxu_launch_action_fn( + ctx, + args, + Some(&launch_app_handle), + Some(&launch_instance_id), + ) + })) + .unwrap_or_else(|e| { + let msg = if let Some(s) = e.downcast_ref::<&str>() { + s.to_string() + } else if let Some(s) = e.downcast_ref::() { + s.clone() + } else { + "Unknown panic payload".to_string() + }; + log::error!( + "[MXU] Custom action {} panicked: {}", + MXU_LAUNCH_ACTION, + msg + ); + false + }) + }; + + if let Err(e) = + resource.register_custom_action(MXU_LAUNCH_ACTION, Box::new(FnAction::new(launch_wrapper))) + { + warn!("[MXU] Failed to register {}: {:?}", MXU_LAUNCH_ACTION, e); + failed_count += 1; + } else { + info!( + "[MXU] Custom action {} registered successfully", + MXU_LAUNCH_ACTION + ); + } + + // kill process + let killproc_app_handle = app_handle.clone(); let killproc_instance_id = instance_id.to_string(); let killproc_wrapper = move |ctx: &maa_framework::context::Context, diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index d4f88073..f9f83584 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -140,7 +140,8 @@ export default { programLabel: 'Program Path', programPlaceholder: 'Enter program path or click browse...', argsLabel: 'Additional Arguments', - argsPlaceholder: 'Enter additional arguments (optional)', + argsPlaceholder: 'Enter additional arguments (optional, template variables supported)', + argsDescription: 'Template variables {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} represent the real-time status of selected tasks of the current instance. See https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 for details.', waitLabel: 'Wait for Exit', waitDescription: 'When disabled, continues immediately after launch; when enabled, waits for the process to exit before continuing, suitable for scripts that need to complete synchronously', diff --git a/src/i18n/locales/ja-JP.ts b/src/i18n/locales/ja-JP.ts index 8cd76746..1c74ec23 100644 --- a/src/i18n/locales/ja-JP.ts +++ b/src/i18n/locales/ja-JP.ts @@ -280,7 +280,8 @@ export default { program: 'プログラムパス', programPlaceholder: 'プログラムパスを入力または参照...', args: '追加引数', - argsPlaceholder: '追加引数を入力(オプション)', + argsPlaceholder: '追加パラメータを入力(オプション、テンプレート変数可)', + argsDescription: 'テンプレート変数 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} は、現在のインスタンスの選択されたタスクのリアルタイム状態を表します。詳細は https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 を参照してください。', browse: '参照', waitForExit: '終了を待機', waitForExitHintPre: diff --git a/src/i18n/locales/ko-KR.ts b/src/i18n/locales/ko-KR.ts index b021fcf5..68605da0 100644 --- a/src/i18n/locales/ko-KR.ts +++ b/src/i18n/locales/ko-KR.ts @@ -137,7 +137,8 @@ export default { programLabel: '프로그램 경로', programPlaceholder: '프로그램 경로를 입력하거나 오른쪽 찾아보기를 클릭...', argsLabel: '추가 인수', - argsPlaceholder: '추가 인수 입력 (선택 사항)', + argsPlaceholder: '추가 인수 입력(선택 사항, 템플릿 변수 지원)', + argsDescription: '템플릿 변수 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 는 현재 인스턴스의 선택된 모든 작업의 실시간 상태를 나타냅니다. 자세한 내용은 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 를 참조하세요.', waitLabel: '종료 대기', waitDescription: '비활성화하면 실행 후 즉시 계속합니다. 활성화하면 프로세스 종료 후 계속합니다. 스크립트 등 동기 완료가 필요한 작업에 적합합니다', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 0359f807..ce312b3f 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -136,7 +136,8 @@ export default { programLabel: '程序路径', programPlaceholder: '输入程序路径或点击右侧浏览...', argsLabel: '附加参数', - argsPlaceholder: '输入附加参数(可选)', + argsPlaceholder: '输入附加参数(可选,支持模板变量)', + argsDescription: '模板变量 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 表示 当前实例-所有选定任务-实时状态,详见 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 。', waitLabel: '等待退出', waitDescription: '禁用时启动进程后立即继续;启用时等待进程退出后再继续工作', waitYes: '等待程序退出后继续', diff --git a/src/i18n/locales/zh-TW.ts b/src/i18n/locales/zh-TW.ts index f954a9ab..d2cace2e 100644 --- a/src/i18n/locales/zh-TW.ts +++ b/src/i18n/locales/zh-TW.ts @@ -135,7 +135,8 @@ export default { programLabel: '程式路徑', programPlaceholder: '輸入程式路徑或點擊右側瀏覽...', argsLabel: '附加參數', - argsPlaceholder: '輸入附加參數(可選)', + argsPlaceholder: '輸入附加參數(可選,支持模板變量)', + argsDescription: '模板變量 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 表示 當前實例-所有選定任務-即時狀態,詳見 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 。', waitLabel: '等待退出', waitDescription: '禁用時啟動程序後立即繼續;啟用時等待程序退出後再繼續,適用於執行腳本等需要同步完成的操作', diff --git a/src/types/specialTasks.ts b/src/types/specialTasks.ts index 582bc394..4d3d52b1 100644 --- a/src/types/specialTasks.ts +++ b/src/types/specialTasks.ts @@ -191,6 +191,7 @@ const MXU_LAUNCH_INPUT_OPTION_DEF_INTERNAL: InputOption = { default: '', pipeline_type: 'string', placeholder: 'specialTask.launch.argsPlaceholder', + description: 'specialTask.launch.argsDescription', }, ], pipeline_override: { From b5c307d498400d65a4ea5af12e35a6e211195cd6 Mon Sep 17 00:00:00 2001 From: Zhicheng Zhang <20331014+zzc-tongji@users.noreply.github.com> Date: Thu, 28 May 2026 17:43:39 +0800 Subject: [PATCH 2/3] improve robustness --- src-tauri/src/commands/utils.rs | 125 ++++++++++++++++++++++---------- src/i18n/locales/en-US.ts | 2 +- src/i18n/locales/ja-JP.ts | 2 +- src/i18n/locales/ko-KR.ts | 2 +- src/i18n/locales/zh-CN.ts | 2 +- src/i18n/locales/zh-TW.ts | 2 +- 6 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src-tauri/src/commands/utils.rs b/src-tauri/src/commands/utils.rs index cdd2fd2a..5865a50e 100644 --- a/src-tauri/src/commands/utils.rs +++ b/src-tauri/src/commands/utils.rs @@ -4,6 +4,7 @@ use super::types::{MaaCallbackEvent, MaaState, StateChangedEvent}; use crate::ws_broadcast::{WsBroadcast, WsEvent}; +use log::error; use std::path::PathBuf; use std::sync::Arc; use tauri::{AppHandle, Emitter, Manager}; @@ -286,16 +287,31 @@ pub fn get_checked_task_status_of_instance( app_handle: Option<&AppHandle>, instance_id: Option<&str>, ) -> Vec> { - let app_config_state = app_handle - .and_then(|app| { - Some( - app.try_state::>() - .unwrap(), - ) - }) - .unwrap(); - let translations = app_config_state.translations.lock().ok().unwrap(); // content as (dist => locales/interface/.ts) - let config = app_config_state.config.lock().ok().unwrap(); // content as (dist => configs/mxu-.ts) + let app_config_state = + match app_handle.and_then(|app| app.try_state::>()) { + Some(state) => state, + None => { + error!("[MXU_STATUS] fail to get resource [app_config_state]"); + return vec![]; + } + }; + let translations = match app_config_state.translations.lock() { + Ok(guard) => guard, + Err(e) => { + error!( + "[MXU_STATUS] fail to lock resource [app_config_state.translations]: {:?}", + e + ); + return vec![]; + } + }; + let config = match app_config_state.config.lock() { + Ok(guard) => guard, + Err(e) => { + error!("[MXU_STATUS] fail to lock resource [app_config_state.config]: {:?}", e); + return vec![]; + } + }; // i18n let language = config @@ -316,23 +332,52 @@ pub fn get_checked_task_status_of_instance( // instance (config) let id = instance_id.unwrap_or(""); - let instance_config_list = config.get("instances"); - let instance_config = instance_config_list - .unwrap() - .as_array() - .unwrap() + let instance_config_list = match config.get("instances").and_then(|v| v.as_array()) { + Some(list) => list, + None => { + error!("[MXU_STATUS] config data [configs/mxu-*.json > .instances] should be [array]"); + return vec![]; + } + }; + let instance_config = match instance_config_list .iter() .find(|inst| inst.get("id").and_then(|v| v.as_str()) == Some(id)) - .unwrap(); + { + Some(inst) => inst, + None => { + error!("[MXU_STATUS] config data [configs/mxu-*.json > .instances] should contains [object] item with whose [.id = {}]", id); + return vec![]; + } + }; // instance (runtime) - let maa_state = app_handle - .and_then(|app| Some(app.try_state::>().unwrap())) - .unwrap(); - let instance_runtime_list = maa_state.instances.lock().ok().unwrap(); - let instance_runtime = instance_runtime_list - .get(instance_id.unwrap_or_default()) - .unwrap(); + let maa_state = + match app_handle.and_then(|app| app.try_state::>()) { + Some(state) => state, + None => { + error!("[MXU_STATUS] fail to get resource [maa_state]"); + return vec![]; + } + }; + + let instance_runtime_list = match maa_state.instances.lock() { + Ok(guard) => guard, + Err(e) => { + error!("[MXU_STATUS] fail to lock resource [maa_state]: {:?}", e); + return vec![]; + } + }; + + let instance_runtime = match instance_runtime_list.get(instance_id.unwrap_or_default()) { + Some(runtime) => runtime, + None => { + error!( + "[MXU_STATUS] runtime data [maa_state.instances[{}]] should be [object]", + instance_id.unwrap_or_default() + ); + return vec![]; + } + }; return instance_runtime .task_run_state @@ -347,22 +392,15 @@ pub fn get_checked_task_status_of_instance( .statuses .get(selected_task_id) { - let task_config_list = instance_config.get("tasks").unwrap(); - let task_config = task_config_list - .as_array() - .unwrap() - .iter() - .find(|task| { - task.get("id").and_then(|v| v.as_str()) - == Some(selected_task_id.as_str()) - }) - .unwrap(); + let task_config_list = instance_config.get("tasks")?.as_array()?; + let task_config = task_config_list.iter().find(|task| { + task.get("id").and_then(|v| v.as_str()) == Some(selected_task_id.as_str()) + })?; let task_name = task_config .get("taskName") - .unwrap() - .as_str() - .unwrap() - .to_string(); + .and_then(|v| v.as_str()) + .map(|s| s.to_string()) + .unwrap_or("".to_string()); let custom_name = task_config .get("customName") .and_then(|v| v.as_str()) @@ -371,16 +409,23 @@ pub fn get_checked_task_status_of_instance( let task_name_i18n = i18n .get(format!("task.{}.label", task_name)) .and_then(|v| v.as_str()) - .unwrap_or("") - .to_string(); + .map(|s| s.to_string()) + .unwrap_or("".to_string()); // custom name / task name (i18n) / task name // => task status ("idle","pending","running","succeeded","failed") let name: String = if !custom_name.is_empty() { custom_name } else if !task_name_i18n.is_empty() { task_name_i18n - } else { + } else if !task_name.is_empty(){ task_name + } else { + error!( + "[MXU_STATUS] config data [configs/mxu-*.json > .instances[.id = \"{}\"].tasks[.id = \"{}\"].taskName] should be [string]", + id, + selected_task_id + ); + return None }; Some(vec![name, status.to_string()]) } else { diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index f9f83584..3e13638a 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -141,7 +141,7 @@ export default { programPlaceholder: 'Enter program path or click browse...', argsLabel: 'Additional Arguments', argsPlaceholder: 'Enter additional arguments (optional, template variables supported)', - argsDescription: 'Template variables {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} represent the real-time status of selected tasks of the current instance. See https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 for details.', + argsDescription: 'Template variables {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} represent the real-time status of selected tasks of the current instance. See https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs for details.', waitLabel: 'Wait for Exit', waitDescription: 'When disabled, continues immediately after launch; when enabled, waits for the process to exit before continuing, suitable for scripts that need to complete synchronously', diff --git a/src/i18n/locales/ja-JP.ts b/src/i18n/locales/ja-JP.ts index 1c74ec23..95122a37 100644 --- a/src/i18n/locales/ja-JP.ts +++ b/src/i18n/locales/ja-JP.ts @@ -281,7 +281,7 @@ export default { programPlaceholder: 'プログラムパスを入力または参照...', args: '追加引数', argsPlaceholder: '追加パラメータを入力(オプション、テンプレート変数可)', - argsDescription: 'テンプレート変数 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} は、現在のインスタンスの選択されたタスクのリアルタイム状態を表します。詳細は https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 を参照してください。', + argsDescription: 'テンプレート変数 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} は、現在のインスタンスの選択されたタスクのリアルタイム状態を表します。詳細は https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs を参照してください。', browse: '参照', waitForExit: '終了を待機', waitForExitHintPre: diff --git a/src/i18n/locales/ko-KR.ts b/src/i18n/locales/ko-KR.ts index 68605da0..2941e991 100644 --- a/src/i18n/locales/ko-KR.ts +++ b/src/i18n/locales/ko-KR.ts @@ -138,7 +138,7 @@ export default { programPlaceholder: '프로그램 경로를 입력하거나 오른쪽 찾아보기를 클릭...', argsLabel: '추가 인수', argsPlaceholder: '추가 인수 입력(선택 사항, 템플릿 변수 지원)', - argsDescription: '템플릿 변수 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 는 현재 인스턴스의 선택된 모든 작업의 실시간 상태를 나타냅니다. 자세한 내용은 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 를 참조하세요.', + argsDescription: '템플릿 변수 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 는 현재 인스턴스의 선택된 모든 작업의 실시간 상태를 나타냅니다. 자세한 내용은 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs 를 참조하세요.', waitLabel: '종료 대기', waitDescription: '비활성화하면 실행 후 즉시 계속합니다. 활성화하면 프로세스 종료 후 계속합니다. 스크립트 등 동기 완료가 필요한 작업에 적합합니다', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index ce312b3f..c73c816b 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -137,7 +137,7 @@ export default { programPlaceholder: '输入程序路径或点击右侧浏览...', argsLabel: '附加参数', argsPlaceholder: '输入附加参数(可选,支持模板变量)', - argsDescription: '模板变量 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 表示 当前实例-所有选定任务-实时状态,详见 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 。', + argsDescription: '模板变量 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 表示 当前实例-所有选定任务-实时状态,详见 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs 。', waitLabel: '等待退出', waitDescription: '禁用时启动进程后立即继续;启用时等待进程退出后再继续工作', waitYes: '等待程序退出后继续', diff --git a/src/i18n/locales/zh-TW.ts b/src/i18n/locales/zh-TW.ts index d2cace2e..b51cdcfa 100644 --- a/src/i18n/locales/zh-TW.ts +++ b/src/i18n/locales/zh-TW.ts @@ -136,7 +136,7 @@ export default { programPlaceholder: '輸入程式路徑或點擊右側瀏覽...', argsLabel: '附加參數', argsPlaceholder: '輸入附加參數(可選,支持模板變量)', - argsDescription: '模板變量 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 表示 當前實例-所有選定任務-即時狀態,詳見 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs#L207 。', + argsDescription: '模板變量 {{STATUS}} {{S_BASE64}} {{S_CSV}} {{S_JSON}} {{S_JSON_BASE64}} 表示 當前實例-所有選定任務-即時狀態,詳見 https://github.com/MistEO/MXU/blob/main/src-tauri/src/mxu_actions.rs 。', waitLabel: '等待退出', waitDescription: '禁用時啟動程序後立即繼續;啟用時等待程序退出後再繼續,適用於執行腳本等需要同步完成的操作', From 5134fce71acbe525a91eeff07dc3542ab24981e1 Mon Sep 17 00:00:00 2001 From: Zhicheng Zhang <20331014+zzc-tongji@users.noreply.github.com> Date: Fri, 29 May 2026 10:43:49 +0800 Subject: [PATCH 3/3] update log --- src-tauri/src/commands/utils.rs | 46 +++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src-tauri/src/commands/utils.rs b/src-tauri/src/commands/utils.rs index 5865a50e..66cce33f 100644 --- a/src-tauri/src/commands/utils.rs +++ b/src-tauri/src/commands/utils.rs @@ -4,7 +4,7 @@ use super::types::{MaaCallbackEvent, MaaState, StateChangedEvent}; use crate::ws_broadcast::{WsBroadcast, WsEvent}; -use log::error; +use log::{error, warn}; use std::path::PathBuf; use std::sync::Arc; use tauri::{AppHandle, Emitter, Manager}; @@ -308,7 +308,10 @@ pub fn get_checked_task_status_of_instance( let config = match app_config_state.config.lock() { Ok(guard) => guard, Err(e) => { - error!("[MXU_STATUS] fail to lock resource [app_config_state.config]: {:?}", e); + error!( + "[MXU_STATUS] fail to lock resource [app_config_state.config]: {:?}", + e + ); return vec![]; } }; @@ -345,7 +348,10 @@ pub fn get_checked_task_status_of_instance( { Some(inst) => inst, None => { - error!("[MXU_STATUS] config data [configs/mxu-*.json > .instances] should contains [object] item with whose [.id = {}]", id); + error!( + "[MXU_STATUS] config data [configs/mxu-*.json > .instances] should contains [object] item whose [.id = \"{:?}\"]", + id + ); return vec![]; } }; @@ -363,17 +369,20 @@ pub fn get_checked_task_status_of_instance( let instance_runtime_list = match maa_state.instances.lock() { Ok(guard) => guard, Err(e) => { - error!("[MXU_STATUS] fail to lock resource [maa_state]: {:?}", e); + error!( + "[MXU_STATUS] fail to lock resource [maa_state]: {:?}", + e + ); return vec![]; } }; - let instance_runtime = match instance_runtime_list.get(instance_id.unwrap_or_default()) { + let instance_runtime = match instance_runtime_list.get(id) { Some(runtime) => runtime, None => { error!( - "[MXU_STATUS] runtime data [maa_state.instances[{}]] should be [object]", - instance_id.unwrap_or_default() + "[MXU_STATUS] runtime data [maa_state.instances[\"{:?}\"]] should be [object]", + id ); return vec![]; } @@ -407,7 +416,7 @@ pub fn get_checked_task_status_of_instance( .unwrap_or("") .to_string(); let task_name_i18n = i18n - .get(format!("task.{}.label", task_name)) + .get(format!("task.{:?}.label", task_name)) .and_then(|v| v.as_str()) .map(|s| s.to_string()) .unwrap_or("".to_string()); @@ -420,19 +429,30 @@ pub fn get_checked_task_status_of_instance( } else if !task_name.is_empty(){ task_name } else { - error!( - "[MXU_STATUS] config data [configs/mxu-*.json > .instances[.id = \"{}\"].tasks[.id = \"{}\"].taskName] should be [string]", + warn!( + "[MXU_STATUS] config data [configs/mxu-*.json > .instances[.id = \"{:?}\"].tasks[.id = \"{:?}\"].taskName] should be [non-empty string]", id, selected_task_id ); return None }; - Some(vec![name, status.to_string()]) + return Some(vec![name, status.to_string()]) } else { - None + warn!( + "[MXU_STATUS] status not found in runtime data [maa_state.instances[\"{:?}\"].task_run_state.statuses] for task in config data [configs/mxu-*.json > .instances[.id = \"{:?}\"].tasks[.id = \"{:?}\"]", + id, + id, + selected_task_id + ); + return None } } else { - None + warn!( + "[MXU_STATUS] task not found in config data [configs/mxu-*.json > .instances[.id = \"{:?}\"] related to runtime data [maa_state.instances[\"{:?}\"].task_run_state.pending_task_ids]", + id, + id + ); + return None } }) .collect();