use thiserror::Error; /// 客户端错误类型定义 #[derive(Debug, Error)] pub enum ClientError { #[error("API客户端未初始化")] ClientNotInitialized, #[error("网络请求失败: {context} - {source}")] NetworkError { #[source] source: reqwest::Error, context: String, }, #[error("数据序列化失败: {operation} - {source}")] SerializationError { #[source] source: serde_json::Error, operation: String, }, #[error("RSA加密错误: {message}")] RsaError { message: String }, #[error("AES加密错误: {message}")] AesError { message: String }, #[error("服务器错误: 状态码={status}, 消息={message}")] ServerError { status: u16, message: String }, #[error("API业务错误: 代码={code}, 消息={message}")] ApiBusinessError { code: i32, message: String }, #[error("配置错误: {message}")] ConfigError { message: String }, #[error("Steam账号错误: {message}")] SteamAccountError { message: String }, #[error("机器码生成失败: {message}")] MachineCodeError { message: String }, #[error("存储操作失败: {message}")] StorageError { message: String }, #[error("反调试检测: {message}")] AntiDebugError { message: String }, #[error("代码完整性检查失败: {message}")] IntegrityError { message: String }, #[error("未知错误: {message}")] UnknownError { message: String }, } /// 为Tauri兼容的错误转换 /// 在生产环境隐藏敏感错误信息,在开发环境显示详细错误 impl From for String { fn from(error: ClientError) -> String { // 生产环境:简化错误信息,但保留后端返回的具体业务错误消息 if !cfg!(debug_assertions) { match error { ClientError::NetworkError { .. } => "网络连接失败,请检查网络设置".to_string(), ClientError::ServerError { .. } => "服务器响应异常,请稍后重试".to_string(), ClientError::ApiBusinessError { message, .. } => message, // 保留后端返回的具体错误消息 ClientError::ClientNotInitialized => "应用初始化失败,请重启应用".to_string(), ClientError::AntiDebugError { .. } => "安全检查失败,程序将退出".to_string(), ClientError::IntegrityError { .. } => "完整性检查失败,程序将退出".to_string(), _ => "操作失败,请稍后重试".to_string(), } } else { // 开发环境:显示详细错误信息 error.to_string() } } } /// 为reqwest::Error实现From trait impl From for ClientError { fn from(error: reqwest::Error) -> Self { network_error(error, "网络请求失败") } } /// 为serde_json::Error实现From trait impl From for ClientError { fn from(error: serde_json::Error) -> Self { serialization_error(error, "JSON序列化失败") } } /// 错误上下文辅助函数 #[allow(dead_code)] pub trait ResultExt { fn with_context(self, f: F) -> Result where F: FnOnce() -> S, S: Into; } impl ResultExt for Result where E: std::error::Error + Send + Sync + 'static, { fn with_context(self, f: F) -> Result where F: FnOnce() -> S, S: Into, { self.map_err(|e| ClientError::UnknownError { message: format!("{}: {}", f().into(), e), }) } } /// 网络错误上下文包装 pub fn network_error(error: reqwest::Error, context: impl Into) -> ClientError { ClientError::NetworkError { source: error, context: context.into(), } } /// 序列化错误上下文包装 pub fn serialization_error(error: serde_json::Error, operation: impl Into) -> ClientError { ClientError::SerializationError { source: error, operation: operation.into(), } } /// RSA错误包装 pub fn rsa_error(message: impl Into) -> ClientError { ClientError::RsaError { message: message.into(), } } /// AES错误包装 pub fn aes_error(message: impl Into) -> ClientError { ClientError::AesError { message: message.into(), } } /// 配置错误包装 pub fn config_error(message: impl Into) -> ClientError { ClientError::ConfigError { message: message.into(), } } /// Steam账号错误包装 #[allow(dead_code)] pub fn steam_error(message: impl Into) -> ClientError { ClientError::SteamAccountError { message: message.into(), } } /// 存储错误包装 #[allow(dead_code)] pub fn storage_error(message: impl Into) -> ClientError { ClientError::StorageError { message: message.into(), } } /// 反调试错误包装 #[allow(dead_code)] pub fn anti_debug_error(message: impl Into) -> ClientError { ClientError::AntiDebugError { message: message.into(), } } /// 完整性错误包装 pub fn integrity_error(message: impl Into) -> ClientError { ClientError::IntegrityError { message: message.into(), } }