From a4dd4bcc8a8c51c4e206f7e29f8d5e284455a6f1 Mon Sep 17 00:00:00 2001 From: wonfen Date: Thu, 27 Feb 2025 14:49:55 +0800 Subject: [PATCH] feat: enhance merge config validation and error handling --- src-tauri/src/cmds.rs | 114 +++++++++++++++++++++++++++++++++---- src-tauri/src/core/core.rs | 41 ++++++++++++- src/locales/en.json | 15 ++++- src/locales/zh.json | 19 ++++++- src/pages/_layout.tsx | 27 +++++++++ 5 files changed, 198 insertions(+), 18 deletions(-) diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index c9c65dd4..0b628598 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -187,24 +187,57 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR } // 在异步操作前完成所有文件操作 - let (file_path, original_content) = { + let (file_path, original_content, is_merge_file) = { let profiles = Config::profiles(); let profiles_guard = profiles.latest(); let item = wrap_err!(profiles_guard.get_item(&index))?; + // 确定是否为merge类型文件 + let is_merge = item.itype.as_ref().map_or(false, |t| t == "merge"); let content = wrap_err!(item.read_file())?; let path = item.file.clone().ok_or("file field is null")?; let profiles_dir = wrap_err!(dirs::app_profiles_dir())?; - (profiles_dir.join(path), content) + (profiles_dir.join(path), content, is_merge) }; // 保存新的配置文件 wrap_err!(fs::write(&file_path, file_data.clone().unwrap()))?; - let file_path_str = file_path.to_string_lossy(); - println!("[cmd配置save] 开始验证配置文件: {}", file_path_str); + let file_path_str = file_path.to_string_lossy().to_string(); + println!("[cmd配置save] 开始验证配置文件: {}, 是否为merge文件: {}", file_path_str, is_merge_file); - // 验证配置文件 - match CoreManager::global().validate_config_file(&file_path_str).await { + // 对于 merge 文件,只进行语法验证,不进行后续内核验证 + if is_merge_file { + println!("[cmd配置save] 检测到merge文件,只进行语法验证"); + match CoreManager::global().validate_config_file(&file_path_str, Some(true)).await { + Ok((true, _)) => { + println!("[cmd配置save] merge文件语法验证通过"); + // 成功后尝试更新整体配置 + if let Err(e) = CoreManager::global().update_config().await { + println!("[cmd配置save] 更新整体配置时发生错误: {}", e); + log::warn!(target: "app", "更新整体配置时发生错误: {}", e); + } + return Ok(()); + } + Ok((false, error_msg)) => { + println!("[cmd配置save] merge文件语法验证失败: {}", error_msg); + // 恢复原始配置文件 + wrap_err!(fs::write(&file_path, original_content))?; + // 发送合并文件专用错误通知 + let result = (false, error_msg.clone()); + handle_yaml_validation_notice(&result, "合并配置文件"); + return Ok(()); + } + Err(e) => { + println!("[cmd配置save] 验证过程发生错误: {}", e); + // 恢复原始配置文件 + wrap_err!(fs::write(&file_path, original_content))?; + return Err(e.to_string()); + } + } + } + + // 非merge文件使用完整验证流程 + match CoreManager::global().validate_config_file(&file_path_str, None).await { Ok((true, _)) => { println!("[cmd配置save] 验证成功"); Ok(()) @@ -214,18 +247,27 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR // 恢复原始配置文件 wrap_err!(fs::write(&file_path, original_content))?; - // 智能判断是否为脚本错误 + // 智能判断错误类型 let is_script_error = file_path_str.ends_with(".js") || - error_msg.contains("Script syntax error") || - error_msg.contains("Script must contain a main function") || - error_msg.contains("Failed to read script file"); + error_msg.contains("Script syntax error") || + error_msg.contains("Script must contain a main function") || + error_msg.contains("Failed to read script file"); - if is_script_error { + if error_msg.contains("YAML syntax error") || + error_msg.contains("Failed to read file:") || + (!file_path_str.ends_with(".js") && !is_script_error) { + // 普通YAML错误使用YAML通知处理 + println!("[cmd配置save] YAML配置文件验证失败,发送通知"); + let result = (false, error_msg.clone()); + handle_yaml_validation_notice(&result, "YAML配置文件"); + } else if is_script_error { // 脚本错误使用专门的通知处理 + println!("[cmd配置save] 脚本文件验证失败,发送通知"); let result = (false, error_msg.clone()); handle_script_validation_notice(&result, "脚本文件"); } else { // 普通配置错误使用一般通知 + println!("[cmd配置save] 其他类型验证失败,发送一般通知"); handle::Handle::notice_message("config_validate::error", &error_msg); } @@ -593,7 +635,7 @@ pub fn handle_script_validation_notice(result: &(bool, String), file_type: &str) pub async fn validate_script_file(file_path: String) -> CmdResult { log::info!(target: "app", "验证脚本文件: {}", file_path); - match CoreManager::global().validate_config_file(&file_path).await { + match CoreManager::global().validate_config_file(&file_path, None).await { Ok(result) => { handle_script_validation_notice(&result, "脚本文件"); Ok(result.0) // 返回验证结果布尔值 @@ -606,3 +648,51 @@ pub async fn validate_script_file(file_path: String) -> CmdResult { } } } + +/// 处理YAML验证相关的所有消息通知 +/// 统一通知接口,保持消息类型一致性 +pub fn handle_yaml_validation_notice(result: &(bool, String), file_type: &str) { + if !result.0 { + let error_msg = &result.1; + println!("[通知] 处理{}验证错误: {}", file_type, error_msg); + + // 检查是否为merge文件 + let is_merge_file = file_type.contains("合并"); + + // 根据错误消息内容判断错误类型 + let status = if error_msg.starts_with("File not found:") { + "config_validate::file_not_found" + } else if error_msg.starts_with("Failed to read file:") { + "config_validate::yaml_read_error" + } else if error_msg.starts_with("YAML syntax error:") { + if is_merge_file { + "config_validate::merge_syntax_error" + } else { + "config_validate::yaml_syntax_error" + } + } else if error_msg.contains("mapping values are not allowed") { + if is_merge_file { + "config_validate::merge_mapping_error" + } else { + "config_validate::yaml_mapping_error" + } + } else if error_msg.contains("did not find expected key") { + if is_merge_file { + "config_validate::merge_key_error" + } else { + "config_validate::yaml_key_error" + } + } else { + // 如果是其他类型错误,根据文件类型作为一般错误处理 + if is_merge_file { + "config_validate::merge_error" + } else { + "config_validate::yaml_error" + } + }; + + log::warn!(target: "app", "{} 验证失败: {}", file_type, error_msg); + println!("[通知] 发送通知: status={}, msg={}", status, error_msg); + handle::Handle::notice_message(status, error_msg); + } +} diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 59dd226a..78d546b7 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -240,7 +240,7 @@ impl CoreManager { } /// 验证指定的配置文件 - pub async fn validate_config_file(&self, config_path: &str) -> Result<(bool, String)> { + pub async fn validate_config_file(&self, config_path: &str, is_merge_file: Option) -> Result<(bool, String)> { // 检查文件是否存在 if !std::path::Path::new(config_path).exists() { let error_msg = format!("File not found: {}", config_path); @@ -248,6 +248,12 @@ impl CoreManager { return Ok((false, error_msg)); } + // 如果是合并文件且不是强制验证,执行语法检查但不进行完整验证 + if is_merge_file.unwrap_or(false) { + println!("[core配置验证] 检测到Merge文件,仅进行语法检查: {}", config_path); + return self.validate_file_syntax(config_path).await; + } + // 检查是否为脚本文件 let is_script = if config_path.ends_with(".js") { true @@ -345,7 +351,8 @@ impl CoreManager { Ok(content) => content, Err(err) => { let error_msg = format!("Failed to read script file: {}", err); - //handle::Handle::notice_message("config_validate::script_error", &error_msg); + log::warn!(target: "app", "脚本语法错误: {}", err); + //handle::Handle::notice_message("config_validate::script_syntax_error", &error_msg); return Ok((false, error_msg)); } }; @@ -440,4 +447,34 @@ impl CoreManager { } } } + + /// 只进行文件语法检查,不进行完整验证 + async fn validate_file_syntax(&self, config_path: &str) -> Result<(bool, String)> { + println!("[core配置语法检查] 开始检查文件: {}", config_path); + + // 读取文件内容 + let content = match std::fs::read_to_string(config_path) { + Ok(content) => content, + Err(err) => { + let error_msg = format!("Failed to read file: {}", err); + println!("[core配置语法检查] 无法读取文件: {}", error_msg); + return Ok((false, error_msg)); + } + }; + + // 对YAML文件尝试解析,只检查语法正确性 + println!("[core配置语法检查] 进行YAML语法检查"); + match serde_yaml::from_str::(&content) { + Ok(_) => { + println!("[core配置语法检查] YAML语法检查通过"); + Ok((true, String::new())) + }, + Err(err) => { + // 使用标准化的前缀,以便错误处理函数能正确识别 + let error_msg = format!("YAML syntax error: {}", err); + println!("[core配置语法检查] YAML语法错误: {}", error_msg); + Ok((false, error_msg)) + } + } + } } \ No newline at end of file diff --git a/src/locales/en.json b/src/locales/en.json index 666f67a5..7fbccfeb 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -451,5 +451,18 @@ "File Not Found": "File missing, changes reverted", "Script File Error": "Script file error, changes reverted", "Core Changed Successfully": "Core changed successfully", - "Failed to Change Core": "Failed to change core" + "Failed to Change Core": "Failed to change core", + "YAML Syntax Error": "YAML syntax error, changes reverted", + "YAML Read Error": "YAML read error, changes reverted", + "YAML Mapping Error": "YAML mapping error, changes reverted", + "YAML Key Error": "YAML key error, changes reverted", + "YAML Error": "YAML error, changes reverted", + "Merge File Syntax Error": "Merge file syntax error, changes reverted", + "Merge File Mapping Error": "Merge file mapping error, changes reverted", + "Merge File Key Error": "Merge file key error, changes reverted", + "Merge File Error": "Merge file error, changes reverted", + "Validate YAML File": "Validate YAML File", + "Validate Merge File": "Validate Merge File", + "Validation Success": "Validation Success", + "Validation Failed": "Validation Failed" } diff --git a/src/locales/zh.json b/src/locales/zh.json index b2006425..df2f2a72 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -135,9 +135,9 @@ "Hidden": "隐藏代理组", "Group Name Required": "代理组名称不能为空", "Group Name Already Exists": "代理组名称已存在", - "Extend Config": "扩展配置", + "Extend Config": "扩展覆写配置", "Extend Script": "扩展脚本", - "Global Merge": "全局扩展配置", + "Global Merge": "全局扩展覆写配置", "Global Script": "全局扩展脚本", "Type": "类型", "Name": "名称", @@ -444,5 +444,18 @@ "File Not Found": "文件丢失,变更已撤销", "Script File Error": "脚本文件错误,变更已撤销", "Core Changed Successfully": "内核切换成功", - "Failed to Change Core": "无法切换内核" + "Failed to Change Core": "无法切换内核", + "YAML Syntax Error": "YAML语法错误,变更已撤销", + "YAML Read Error": "YAML读取错误,变更已撤销", + "YAML Mapping Error": "YAML映射错误,变更已撤销", + "YAML Key Error": "YAML键错误,变更已撤销", + "YAML Error": "YAML错误,变更已撤销", + "Merge File Syntax Error": "覆写文件语法错误,变更已撤销", + "Merge File Mapping Error": "覆写文件映射错误,变更已撤销", + "Merge File Key Error": "覆写文件键错误,变更已撤销", + "Merge File Error": "覆写文件错误,变更已撤销", + "Validate YAML File": "验证YAML文件", + "Validate Merge File": "验证覆写文件", + "Validation Success": "验证成功", + "Validation Failed": "验证失败" } diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index 82155fcd..c5d6b048 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -84,6 +84,33 @@ const handleNoticeMessage = ( case "config_validate::file_not_found": Notice.error(`${t("File Not Found")} ${msg}`); break; + case "config_validate::yaml_syntax_error": + Notice.error(`${t("YAML Syntax Error")} ${msg}`); + break; + case "config_validate::yaml_read_error": + Notice.error(`${t("YAML Read Error")} ${msg}`); + break; + case "config_validate::yaml_mapping_error": + Notice.error(`${t("YAML Mapping Error")} ${msg}`); + break; + case "config_validate::yaml_key_error": + Notice.error(`${t("YAML Key Error")} ${msg}`); + break; + case "config_validate::yaml_error": + Notice.error(`${t("YAML Error")} ${msg}`); + break; + case "config_validate::merge_syntax_error": + Notice.error(`${t("Merge File Syntax Error")} ${msg}`); + break; + case "config_validate::merge_mapping_error": + Notice.error(`${t("Merge File Mapping Error")} ${msg}`); + break; + case "config_validate::merge_key_error": + Notice.error(`${t("Merge File Key Error")} ${msg}`); + break; + case "config_validate::merge_error": + Notice.error(`${t("Merge File Error")} ${msg}`); + break; case "config_core::change_success": Notice.success(`${t("Core Changed Successfully")}: ${msg}`); break;