Skip to main content

openlark_core/error/
codes.rs

1//! Error Codes Definition
2//!
3//! 统一的错误码系统,提供标准化的错误标识和映射。
4
5use super::traits::ErrorSeverity;
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9/// 标准错误码枚举
10///
11/// 涵盖所有可能的标准错误情况,包括HTTP状态码、飞书API错误码、
12/// 网络错误码、系统错误码等。
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub enum ErrorCode {
15    // 成功状态
16    /// 成功
17    Success = 0,
18
19    // HTTP 标准错误码
20    /// 请求参数错误
21    BadRequest = 400,
22    /// 未认证
23    Unauthorized = 401,
24    /// 禁止访问
25    Forbidden = 403,
26    /// 资源不存在
27    NotFound = 404,
28    /// 方法不允许
29    MethodNotAllowed = 405,
30    /// 请求冲突
31    Conflict = 409,
32    /// 请求频率过高
33    TooManyRequests = 429,
34
35    // 服务器错误码
36    /// 内部服务器错误
37    InternalServerError = 500,
38    /// 网关错误
39    BadGateway = 502,
40    /// 服务不可用
41    ServiceUnavailable = 503,
42    /// 网关超时
43    GatewayTimeout = 504,
44
45    // 飞书API错误码 - 认证相关
46    /// 应用票据无效
47    AppTicketInvalid = 10012,
48    /// 应用状态异常
49    AppStatusException = 10013,
50    /// 应用权限不足
51    AppPermissionDenied = 19001,
52    /// 访问令牌无效
53    AccessTokenInvalid = 99991671,
54    /// 访问令牌格式错误/无效
55    AccessTokenFormatInvalid = 99991661,
56    /// 应用访问令牌无效
57    AppAccessTokenInvalid = 99991664,
58    /// 租户访问令牌无效
59    TenantAccessTokenInvalid = 99991663,
60    /// SSO 访问令牌无效
61    SsoTokenInvalid = 99991670,
62    /// 缺少所需权限
63    PermissionMissing = 99991672,
64    /// 访问令牌缺少权限
65    AccessTokenNoPermission = 99991676,
66    /// 访问令牌已过期(飞书通用码)
67    AccessTokenExpiredV2 = 99991677,
68
69    // 会话 / 身份类
70    /// 用户会话已失效
71    UserSessionInvalid = 99991641,
72    /// 用户会话不存在
73    UserSessionNotFound = 99991642,
74    /// 用户会话超时
75    UserSessionTimeout = 99991645,
76    /// 用户身份解析失败
77    UserIdentityInvalid = 99991669,
78    /// 用户类型不支持
79    UserTypeNotSupportedV2 = 99991674,
80    /// 用户身份不匹配
81    UserIdentityMismatch = 99991675,
82    /// 用户ID非法
83    UserIdInvalid = 99992351,
84    /// OpenID 非法
85    OpenIdInvalid = 99992352,
86    /// UnionID 非法
87    UnionIdInvalid = 99992353,
88
89    // 飞书API错误码 - 资源相关
90    /// 应用未安装
91    AppNotInstalled = 10003,
92    /// 用户不存在
93    UserNotFound = 60001,
94    /// 用户状态异常
95    UserStatusException = 60002,
96    /// 部门不存在
97    DepartmentNotFound = 60003,
98    /// 群组不存在
99    ChatNotFound = 70001,
100    /// 群组类型不支持
101    ChatTypeNotSupported = 70002,
102    /// 消息不存在
103    MessageNotFound = 80001,
104    /// 消息类型不支持
105    MessageTypeNotSupported = 80002,
106    /// 文件不存在
107    FileNotFound = 90001,
108    /// 文件大小超限
109    FileSizeExceeded = 90002,
110    /// 文件类型不支持
111    FileTypeNotSupported = 90003,
112
113    // 飞书API错误码 - 业务相关
114    /// 日历不存在
115    CalendarNotFound = 110001,
116    /// 日程不存在
117    EventNotFound = 110002,
118    /// 日程冲突
119    EventConflict = 110003,
120    /// 文档不存在
121    DocumentNotFound = 120001,
122    /// 文档权限不足
123    DocumentPermissionDenied = 120002,
124    /// 文档已锁定
125    DocumentLocked = 120003,
126    /// 工作表不存在
127    SheetNotFound = 120011,
128    /// 表格不存在
129    TableNotFound = 120021,
130
131    // 网络和传输错误码
132    /// 网络连接超时
133    NetworkTimeout = 999001,
134    /// 网络连接失败
135    NetworkConnectionFailed = 999002,
136    /// DNS解析失败
137    DnsResolutionFailed = 999003,
138    /// SSL证书错误
139    SslCertificateError = 999004,
140    /// 连接被拒绝
141    ConnectionRefused = 999005,
142
143    // 序列化错误码
144    /// JSON解析错误
145    SerializationError = 999010,
146    /// 数据格式错误
147    DataFormatError = 999011,
148    /// 编码错误
149    EncodingError = 999012,
150
151    // 认证和授权错误码
152    /// 身份验证失败
153    AuthenticationFailed = 999020,
154    /// 权限被拒绝
155    PermissionDenied = 999021,
156    /// 令牌已过期
157    TokenExpired = 999022,
158    /// 无效签名
159    InvalidSignature = 999023,
160
161    // 验证错误码
162    /// 参数验证失败
163    ValidationError = 999030,
164    /// 缺少必需参数
165    MissingRequiredParameter = 999031,
166    /// 参数格式错误
167    InvalidParameterFormat = 999032,
168    /// 参数值超出范围
169    ParameterOutOfRange = 999033,
170
171    // 业务逻辑错误码
172    /// 业务逻辑错误
173    BusinessError = 999040,
174    /// 操作不被支持
175    OperationNotSupported = 999041,
176    /// 资源状态冲突
177    ResourceConflict = 999042,
178
179    // 系统错误码
180    /// 系统内部错误
181    InternalError = 999050,
182    /// 配置错误
183    ConfigurationError = 999051,
184    /// 资源耗尽
185    ResourceExhausted = 999052,
186
187    // 限流错误码
188    /// 请求频率限制
189    RateLimitExceeded = 999060,
190
191    // 响应大小错误码
192    /// 响应体大小超过限制
193    ResponseTooLarge = 41300,
194
195    // 缓存错误码
196    /// 缓存未命中
197    CacheMiss = 999070,
198    /// 缓存服务不可用
199    CacheServiceUnavailable = 999071,
200
201    // 安全错误码
202    /// 安全策略违规
203    SecurityPolicyViolation = 999080,
204    /// 访问被拒绝
205    AccessDenied = 999081,
206
207    // 未知错误
208    /// 未知错误
209    Unknown = 999999,
210}
211
212impl ErrorCode {
213    /// 从数值创建错误码
214    pub fn from_code(code: i32) -> Self {
215        match code {
216            c if (200..=299).contains(&c) => Self::Success,
217            0 => Self::Success,
218
219            // HTTP 标准错误码
220            400 => Self::BadRequest,
221            401 => Self::Unauthorized,
222            403 => Self::Forbidden,
223            404 => Self::NotFound,
224            405 => Self::MethodNotAllowed,
225            409 => Self::Conflict,
226            429 => Self::TooManyRequests,
227
228            // 服务器错误码
229            500 => Self::InternalServerError,
230            502 => Self::BadGateway,
231            503 => Self::ServiceUnavailable,
232            504 => Self::GatewayTimeout,
233
234            // 飞书API错误码
235            10003 => Self::AppNotInstalled,
236            10012 => Self::AppTicketInvalid,
237            10013 => Self::AppStatusException,
238            19001 => Self::AppPermissionDenied,
239            60001 => Self::UserNotFound,
240            60002 => Self::UserStatusException,
241            60003 => Self::DepartmentNotFound,
242            70001 => Self::ChatNotFound,
243            70002 => Self::ChatTypeNotSupported,
244            80001 => Self::MessageNotFound,
245            80002 => Self::MessageTypeNotSupported,
246            90001 => Self::FileNotFound,
247            90002 => Self::FileSizeExceeded,
248            90003 => Self::FileTypeNotSupported,
249            110001 => Self::CalendarNotFound,
250            110002 => Self::EventNotFound,
251            110003 => Self::EventConflict,
252            120001 => Self::DocumentNotFound,
253            120002 => Self::DocumentPermissionDenied,
254            120003 => Self::DocumentLocked,
255            120011 => Self::SheetNotFound,
256            120021 => Self::TableNotFound,
257            99991661 => Self::AccessTokenFormatInvalid,
258            99991671 => Self::AccessTokenInvalid,
259            99991664 => Self::AppAccessTokenInvalid,
260            99991663 => Self::TenantAccessTokenInvalid,
261            99991670 => Self::SsoTokenInvalid,
262            99991672 => Self::PermissionMissing,
263            99991676 => Self::AccessTokenNoPermission,
264            99991677 => Self::AccessTokenExpiredV2,
265            99991641 => Self::UserSessionInvalid,
266            99991642 => Self::UserSessionNotFound,
267            99991645 => Self::UserSessionTimeout,
268            99991669 => Self::UserIdentityInvalid,
269            99991674 => Self::UserTypeNotSupportedV2,
270            99991675 => Self::UserIdentityMismatch,
271            99992351 => Self::UserIdInvalid,
272            99992352 => Self::OpenIdInvalid,
273            99992353 => Self::UnionIdInvalid,
274
275            // 网络错误码
276            999001 => Self::NetworkTimeout,
277            999002 => Self::NetworkConnectionFailed,
278            999003 => Self::DnsResolutionFailed,
279            999004 => Self::SslCertificateError,
280            999005 => Self::ConnectionRefused,
281
282            // 序列化错误码
283            999010 => Self::SerializationError,
284            999011 => Self::DataFormatError,
285            999012 => Self::EncodingError,
286
287            // 认证和授权错误码
288            999020 => Self::AuthenticationFailed,
289            999021 => Self::PermissionDenied,
290            999022 => Self::TokenExpired,
291            999023 => Self::InvalidSignature,
292
293            // 验证错误码
294            999030 => Self::ValidationError,
295            999031 => Self::MissingRequiredParameter,
296            999032 => Self::InvalidParameterFormat,
297            999033 => Self::ParameterOutOfRange,
298
299            // 业务逻辑错误码
300            999040 => Self::BusinessError,
301            999041 => Self::OperationNotSupported,
302            999042 => Self::ResourceConflict,
303
304            // 系统错误码
305            999050 => Self::InternalError,
306            999051 => Self::ConfigurationError,
307            999052 => Self::ResourceExhausted,
308
309            // 限流错误码
310            999060 => Self::RateLimitExceeded,
311
312            // 响应大小错误码
313            41300 => Self::ResponseTooLarge,
314
315            // 缓存错误码
316            999070 => Self::CacheMiss,
317            999071 => Self::CacheServiceUnavailable,
318
319            // 安全错误码
320            999080 => Self::SecurityPolicyViolation,
321            999081 => Self::AccessDenied,
322
323            _ => Self::Unknown,
324        }
325    }
326
327    /// 获取数值形式
328    pub fn as_code(&self) -> i32 {
329        *self as i32
330    }
331
332    /// 获取错误码的描述
333    pub fn description(&self) -> &'static str {
334        match self {
335            Self::Success => "操作成功",
336
337            // HTTP 标准错误码描述
338            Self::BadRequest => "请求参数错误",
339            Self::Unauthorized => "未认证",
340            Self::Forbidden => "禁止访问",
341            Self::NotFound => "资源不存在",
342            Self::MethodNotAllowed => "方法不允许",
343            Self::Conflict => "请求冲突",
344            Self::TooManyRequests => "请求频率过高",
345
346            // 服务器错误码描述
347            Self::InternalServerError => "内部服务器错误",
348            Self::BadGateway => "网关错误",
349            Self::ServiceUnavailable => "服务不可用",
350            Self::GatewayTimeout => "网关超时",
351
352            // 飞书API错误码描述
353            Self::AppNotInstalled => "应用未安装",
354            Self::AppTicketInvalid => "应用票据无效",
355            Self::AppStatusException => "应用状态异常",
356            Self::AppPermissionDenied => "应用权限不足",
357            Self::UserNotFound => "用户不存在",
358            Self::UserStatusException => "用户状态异常",
359            Self::DepartmentNotFound => "部门不存在",
360            Self::ChatNotFound => "群组不存在",
361            Self::ChatTypeNotSupported => "群组类型不支持",
362            Self::MessageNotFound => "消息不存在",
363            Self::MessageTypeNotSupported => "消息类型不支持",
364            Self::FileNotFound => "文件不存在",
365            Self::FileSizeExceeded => "文件大小超限",
366            Self::FileTypeNotSupported => "文件类型不支持",
367            Self::CalendarNotFound => "日历不存在",
368            Self::EventNotFound => "日程不存在",
369            Self::EventConflict => "日程冲突",
370            Self::DocumentNotFound => "文档不存在",
371            Self::DocumentPermissionDenied => "文档权限不足",
372            Self::DocumentLocked => "文档已锁定",
373            Self::SheetNotFound => "工作表不存在",
374            Self::TableNotFound => "表格不存在",
375            Self::AccessTokenFormatInvalid => "访问令牌格式错误",
376            Self::AccessTokenInvalid => "访问令牌无效",
377            Self::AppAccessTokenInvalid => "应用访问令牌无效",
378            Self::TenantAccessTokenInvalid => "租户访问令牌无效",
379            Self::SsoTokenInvalid => "SSO 访问令牌无效",
380            Self::PermissionMissing => "缺少所需权限",
381            Self::AccessTokenNoPermission => "访问令牌权限不足",
382            Self::AccessTokenExpiredV2 => "访问令牌已过期",
383            Self::UserSessionInvalid => "用户会话已失效",
384            Self::UserSessionNotFound => "用户会话不存在",
385            Self::UserSessionTimeout => "用户会话超时",
386            Self::UserIdentityInvalid => "用户身份解析失败",
387            Self::UserTypeNotSupportedV2 => "用户类型不支持",
388            Self::UserIdentityMismatch => "用户身份不匹配",
389            Self::UserIdInvalid => "用户ID非法",
390            Self::OpenIdInvalid => "OpenID 非法",
391            Self::UnionIdInvalid => "UnionID 非法",
392
393            // 网络错误码描述
394            Self::NetworkTimeout => "网络连接超时",
395            Self::NetworkConnectionFailed => "网络连接失败",
396            Self::DnsResolutionFailed => "DNS解析失败",
397            Self::SslCertificateError => "SSL证书错误",
398            Self::ConnectionRefused => "连接被拒绝",
399
400            // 序列化错误码描述
401            Self::SerializationError => "JSON解析错误",
402            Self::DataFormatError => "数据格式错误",
403            Self::EncodingError => "编码错误",
404
405            // 认证和授权错误码描述
406            Self::AuthenticationFailed => "身份验证失败",
407            Self::PermissionDenied => "权限被拒绝",
408            Self::TokenExpired => "令牌已过期",
409            Self::InvalidSignature => "无效签名",
410
411            // 验证错误码描述
412            Self::ValidationError => "参数验证失败",
413            Self::MissingRequiredParameter => "缺少必需参数",
414            Self::InvalidParameterFormat => "参数格式错误",
415            Self::ParameterOutOfRange => "参数值超出范围",
416
417            // 业务逻辑错误码描述
418            Self::BusinessError => "业务逻辑错误",
419            Self::OperationNotSupported => "操作不被支持",
420            Self::ResourceConflict => "资源状态冲突",
421
422            // 系统错误码描述
423            Self::InternalError => "系统内部错误",
424            Self::ConfigurationError => "配置错误",
425            Self::ResourceExhausted => "资源耗尽",
426
427            // 限流错误码描述
428            Self::RateLimitExceeded => "请求频率限制",
429
430            // 响应大小错误码描述
431            Self::ResponseTooLarge => "响应体大小超过限制",
432
433            // 缓存错误码描述
434            Self::CacheMiss => "缓存未命中",
435            Self::CacheServiceUnavailable => "缓存服务不可用",
436
437            // 安全错误码描述
438            Self::SecurityPolicyViolation => "安全策略违规",
439            Self::AccessDenied => "访问被拒绝",
440
441            Self::Unknown => "未知错误",
442        }
443    }
444
445    /// 获取详细的错误说明
446    pub fn detailed_description(&self) -> &'static str {
447        match self {
448            Self::Success => "请求已成功处理",
449
450            Self::BadRequest => "请求参数格式错误或缺少必需参数,请检查请求内容",
451            Self::Unauthorized => "身份验证失败,请检查访问令牌是否有效",
452            Self::Forbidden => "权限不足,无法访问请求的资源",
453            Self::NotFound => "请求的资源不存在或已被删除",
454            Self::MethodNotAllowed => "当前API不支持此HTTP方法",
455            Self::Conflict => "请求与当前资源状态冲突,请检查资源状态",
456            Self::TooManyRequests => "请求频率超过限制,请降低请求频率后重试",
457
458            Self::InternalServerError => "服务器内部错误,请稍后重试或联系技术支持",
459            Self::BadGateway => "网关服务器错误,请检查网络连接或稍后重试",
460            Self::ServiceUnavailable => "服务暂时不可用,请稍后重试",
461            Self::GatewayTimeout => "网关超时,请稍后重试",
462
463            Self::AppNotInstalled => "应用未安装到当前企业,请在飞书管理后台安装应用",
464            Self::AppTicketInvalid => "应用票据已失效,SDK会自动重新申请",
465            Self::AppStatusException => "应用状态异常,请检查应用是否正常启用",
466            Self::AppPermissionDenied => "应用缺少执行此操作的权限,请在开发者后台配置相应权限",
467            Self::UserNotFound => "指定的用户不存在,请检查用户ID是否正确",
468            Self::UserStatusException => "用户状态异常,可能已被禁用或删除",
469            Self::DepartmentNotFound => "指定的部门不存在,请检查部门ID是否正确",
470            Self::ChatNotFound => "指定的群组不存在或机器人未加入该群组",
471            Self::ChatTypeNotSupported => "当前群组类型不支持此操作",
472            Self::MessageNotFound => "指定的消息不存在或已被删除",
473            Self::MessageTypeNotSupported => "不支持的消息类型",
474            Self::FileNotFound => "指定的文件不存在或已被删除",
475            Self::FileSizeExceeded => "文件大小超出限制,请压缩后重试",
476            Self::FileTypeNotSupported => "不支持的文件类型",
477            Self::CalendarNotFound => "指定的日历不存在",
478            Self::EventNotFound => "指定的日程不存在或已被删除",
479            Self::EventConflict => "日程时间冲突,请选择其他时间",
480            Self::DocumentNotFound => "指定的文档不存在或已被删除",
481            Self::DocumentPermissionDenied => "文档权限不足,请联系文档所有者授权",
482            Self::DocumentLocked => "文档已被其他用户锁定,请稍后再试",
483            Self::SheetNotFound => "指定的工作表不存在",
484            Self::TableNotFound => "指定的表格不存在",
485            Self::AccessTokenFormatInvalid => "访问令牌格式或内容无效,请重新获取或检查传参",
486            Self::AccessTokenInvalid => "用户访问令牌无效或失效,需要重新获取用户授权",
487            Self::AppAccessTokenInvalid => "应用访问令牌无效,请检查应用ID和密钥配置",
488            Self::TenantAccessTokenInvalid => "租户访问令牌无效,请检查应用是否正确安装到企业",
489            Self::SsoTokenInvalid => "SSO 访问令牌无效,请重新登录或检查 SSO 配置",
490            Self::PermissionMissing => "缺少所需权限,请在开发者后台开通对应权限范围",
491            Self::AccessTokenNoPermission => "访问令牌权限不足,请重新授权所需 scope",
492            Self::AccessTokenExpiredV2 => "访问令牌已过期,需要重新获取",
493            Self::UserSessionInvalid => "用户会话失效,请重新登录或刷新会话",
494            Self::UserSessionNotFound => "未找到有效用户会话,请重新登录",
495            Self::UserSessionTimeout => "用户会话已超时,请重新登录",
496            Self::UserIdentityInvalid => "用户身份解析失败,请检查传入的身份标识",
497            Self::UserTypeNotSupportedV2 => "当前用户类型不支持该操作",
498            Self::UserIdentityMismatch => "用户身份不匹配,请检查 user_id/open_id 组合",
499            Self::UserIdInvalid => "用户ID非法,请检查参数格式",
500            Self::OpenIdInvalid => "OpenID 非法,请检查参数格式",
501            Self::UnionIdInvalid => "UnionID 非法,请检查参数格式",
502
503            Self::NetworkTimeout => "网络请求超时,请检查网络连接或增加超时时间",
504            Self::NetworkConnectionFailed => "网络连接失败,请检查网络设置和服务器状态",
505            Self::DnsResolutionFailed => "DNS解析失败,请检查域名设置或网络配置",
506            Self::SslCertificateError => "SSL证书验证失败,请检查证书配置或系统时间",
507            Self::ConnectionRefused => "连接被拒绝,请检查服务器状态和防火墙设置",
508
509            Self::SerializationError => "JSON序列化或反序列化失败,请检查数据格式",
510            Self::DataFormatError => "数据格式不正确,请检查输入数据结构",
511            Self::EncodingError => "数据编码错误,请检查字符编码设置",
512
513            Self::AuthenticationFailed => "身份验证失败,请检查凭据是否正确",
514            Self::PermissionDenied => "权限不足,无法执行此操作",
515            Self::TokenExpired => "访问令牌已过期,需要重新获取",
516            Self::InvalidSignature => "签名验证失败,请检查签名算法和密钥",
517
518            Self::ValidationError => "输入数据验证失败,请检查数据格式和内容",
519            Self::MissingRequiredParameter => "缺少必需的参数,请检查请求参数完整性",
520            Self::InvalidParameterFormat => "参数格式不正确,请按照要求格式提供参数",
521            Self::ParameterOutOfRange => "参数值超出允许范围,请检查参数值是否有效",
522
523            Self::BusinessError => "业务逻辑处理失败,请检查操作条件和业务规则",
524            Self::OperationNotSupported => "当前操作不被支持,请检查API文档或使用替代方法",
525            Self::ResourceConflict => "资源状态冲突,请检查资源当前状态或等待后重试",
526
527            Self::InternalError => "系统内部错误,请联系技术支持",
528            Self::ConfigurationError => "系统配置错误,请检查配置文件或环境变量",
529            Self::ResourceExhausted => "系统资源耗尽,请稍后重试或增加资源配额",
530
531            Self::RateLimitExceeded => "请求频率超过限制,请降低请求频率后重试",
532
533            Self::ResponseTooLarge => "响应体大小超过限制,请减小请求范围或联系管理员调整限制",
534
535            Self::CacheMiss => "缓存中未找到数据,将从数据源获取",
536            Self::CacheServiceUnavailable => "缓存服务不可用,将直接访问数据源",
537
538            Self::SecurityPolicyViolation => "操作违反安全策略,请检查操作权限和安全设置",
539            Self::AccessDenied => "访问被拒绝,请检查访问权限和身份验证",
540
541            Self::Unknown => "未知错误,请联系技术支持获取帮助",
542        }
543    }
544
545    /// 判断是否为成功状态
546    pub fn is_success(&self) -> bool {
547        matches!(self, Self::Success)
548    }
549
550    /// 判断是否为客户端错误 (4xx)
551    pub fn is_client_error(&self) -> bool {
552        let code = *self as i32;
553        (400..=499).contains(&code) && code != 429
554    }
555
556    /// 判断是否为服务器错误 (5xx)
557    pub fn is_server_error(&self) -> bool {
558        let code = *self as i32;
559        (500..=599).contains(&code)
560    }
561
562    /// 判断是否为网络相关错误
563    pub fn is_network_error(&self) -> bool {
564        matches!(
565            self,
566            Self::NetworkTimeout
567                | Self::NetworkConnectionFailed
568                | Self::DnsResolutionFailed
569                | Self::SslCertificateError
570                | Self::ConnectionRefused
571        )
572    }
573
574    /// 判断是否为认证相关错误
575    pub fn is_auth_error(&self) -> bool {
576        matches!(
577            self,
578            Self::Unauthorized
579                | Self::AccessTokenFormatInvalid
580                | Self::AccessTokenInvalid
581                | Self::AppAccessTokenInvalid
582                | Self::TenantAccessTokenInvalid
583                | Self::SsoTokenInvalid
584                | Self::AuthenticationFailed
585                | Self::TokenExpired
586                | Self::AccessTokenExpiredV2
587                | Self::InvalidSignature
588                | Self::UserSessionInvalid
589                | Self::UserSessionNotFound
590                | Self::UserSessionTimeout
591                | Self::UserIdentityInvalid
592                | Self::UserTypeNotSupportedV2
593                | Self::UserIdentityMismatch
594                | Self::UserIdInvalid
595                | Self::OpenIdInvalid
596                | Self::UnionIdInvalid
597        )
598    }
599
600    /// 判断是否为权限相关错误
601    pub fn is_permission_error(&self) -> bool {
602        matches!(
603            self,
604            Self::Forbidden
605                | Self::AppPermissionDenied
606                | Self::DocumentPermissionDenied
607                | Self::PermissionDenied
608                | Self::PermissionMissing
609                | Self::AccessTokenNoPermission
610                | Self::AccessDenied
611        )
612    }
613
614    /// 判断是否为可重试错误
615    pub fn is_retryable(&self) -> bool {
616        match self {
617            Self::Success => false,
618            Self::TooManyRequests => true,
619            Self::InternalServerError => true,
620            Self::BadGateway => true,
621            Self::ServiceUnavailable => true,
622            Self::GatewayTimeout => true,
623            Self::NetworkTimeout => true,
624            Self::NetworkConnectionFailed => true,
625            Self::ConnectionRefused => true,
626            Self::CacheServiceUnavailable => true,
627            Self::RateLimitExceeded => true,
628            _ => false,
629        }
630    }
631
632    /// 获取建议的重试延迟时间(秒)
633    pub fn suggested_retry_delay(&self) -> Option<u64> {
634        match self {
635            Self::TooManyRequests => Some(60),
636            Self::InternalServerError => Some(5),
637            Self::BadGateway => Some(3),
638            Self::ServiceUnavailable => Some(10),
639            Self::GatewayTimeout => Some(5),
640            Self::NetworkTimeout => Some(3),
641            Self::NetworkConnectionFailed => Some(5),
642            Self::ConnectionRefused => Some(10),
643            Self::RateLimitExceeded => Some(30),
644            _ => None,
645        }
646    }
647
648    /// 获取HTTP状态码
649    pub fn http_status(&self) -> Option<u16> {
650        match self {
651            Self::ResponseTooLarge => Some(413),
652            _ => {
653                let code = *self as i32;
654                if (100..=599).contains(&code) {
655                    Some(code as u16)
656                } else {
657                    None
658                }
659            }
660        }
661    }
662
663    /// 从HTTP状态码创建错误码
664    pub fn from_http_status(status: u16) -> Self {
665        Self::from_code(status as i32)
666    }
667
668    // === 与thiserror CoreError配合的新方法 ===
669
670    /// 根据错误类型自动选择合适的错误码
671    ///
672    /// 为CoreError枚举变体提供最佳的错误码匹配
673    pub fn for_error_type(error_type: &str) -> Self {
674        match error_type {
675            // 网络相关错误
676            "Network" | "network" => Self::NetworkConnectionFailed,
677
678            // 认证相关错误
679            "Authentication" | "authentication" => Self::AuthenticationFailed,
680            "TokenExpired" | "token_expired" => Self::TokenExpired,
681
682            // 权限相关错误
683            "Permission" | "permission" => Self::PermissionDenied,
684            "Forbidden" | "forbidden" => Self::Forbidden,
685
686            // 验证相关错误
687            "Validation" | "validation" => Self::ValidationError,
688            "ApiError" | "api_error" => Self::BusinessError,
689
690            // 配置相关错误
691            "Configuration" | "configuration" => Self::ConfigurationError,
692
693            // 序列化相关错误
694            "Serialization" | "serialization" => Self::SerializationError,
695
696            // 系统相关错误
697            "Internal" | "internal" => Self::InternalError,
698            "Unknown" | "unknown" => Self::Unknown,
699
700            // HTTP状态码映射
701            "BadRequest" | "bad_request" => Self::BadRequest,
702            "Unauthorized" | "unauthorized" => Self::Unauthorized,
703            "NotFound" | "not_found" => Self::NotFound,
704            "Conflict" | "conflict" => Self::Conflict,
705            "TooManyRequests" | "too_many_requests" => Self::TooManyRequests,
706            "InternalServerError" | "internal_server_error" => Self::InternalServerError,
707            "ServiceUnavailable" | "service_unavailable" => Self::ServiceUnavailable,
708
709            // 默认为未知错误
710            _ => Self::Unknown,
711        }
712    }
713
714    /// 创建网络相关错误码
715    pub fn network() -> Self {
716        Self::NetworkConnectionFailed
717    }
718
719    /// 创建认证相关错误码
720    pub fn authentication() -> Self {
721        Self::AuthenticationFailed
722    }
723
724    /// 创建权限相关错误码
725    pub fn permission() -> Self {
726        Self::PermissionDenied
727    }
728
729    /// 创建验证相关错误码
730    pub fn validation() -> Self {
731        Self::ValidationError
732    }
733
734    /// 创建配置相关错误码
735    pub fn configuration() -> Self {
736        Self::ConfigurationError
737    }
738
739    /// 创建系统内部错误码
740    pub fn internal() -> Self {
741        Self::InternalError
742    }
743
744    /// 创建序列化错误码
745    pub fn serialization() -> Self {
746        Self::SerializationError
747    }
748
749    /// 创建未知错误码
750    pub fn unknown() -> Self {
751        Self::Unknown
752    }
753
754    /// 从字符串描述智能推断错误码
755    ///
756    /// 根据错误消息的关键词自动推断最合适的错误码
757    pub fn from_message(message: &str) -> Self {
758        let msg_lower = message.to_lowercase();
759
760        // 网络相关关键词
761        if msg_lower.contains("network")
762            || msg_lower.contains("connection")
763            || msg_lower.contains("timeout")
764            || msg_lower.contains("dns")
765        {
766            return Self::NetworkConnectionFailed;
767        }
768
769        // 认证相关关键词
770        if msg_lower.contains("auth")
771            || msg_lower.contains("token")
772            || msg_lower.contains("unauthorized")
773        {
774            return Self::AuthenticationFailed;
775        }
776
777        // 权限相关关键词
778        if msg_lower.contains("permission")
779            || msg_lower.contains("forbidden")
780            || msg_lower.contains("access denied")
781        {
782            return Self::PermissionDenied;
783        }
784
785        // 验证相关关键词
786        if msg_lower.contains("invalid")
787            || msg_lower.contains("validation")
788            || msg_lower.contains("parameter")
789        {
790            return Self::ValidationError;
791        }
792
793        // 配置相关关键词
794        if msg_lower.contains("config") || msg_lower.contains("setting") {
795            return Self::ConfigurationError;
796        }
797
798        // 序列化相关关键词
799        if msg_lower.contains("json")
800            || msg_lower.contains("serialize")
801            || msg_lower.contains("parse")
802        {
803            return Self::SerializationError;
804        }
805
806        // 资源相关关键词
807        if msg_lower.contains("not found") || msg_lower.contains("missing") {
808            return Self::NotFound;
809        }
810
811        // 服务相关关键词
812        if msg_lower.contains("unavailable") || msg_lower.contains("service") {
813            return Self::ServiceUnavailable;
814        }
815
816        Self::Unknown
817    }
818
819    /// 判断是否应该触发重试策略
820    ///
821    /// 提供更细粒度的重试判断逻辑
822    pub fn should_retry(&self, attempt: u32) -> bool {
823        if !self.is_retryable() {
824            return false;
825        }
826
827        match self {
828            // 限制重试次数的错误类型
829            Self::TooManyRequests | Self::RateLimitExceeded => attempt < 5,
830            Self::NetworkTimeout | Self::NetworkConnectionFailed => attempt < 3,
831            Self::InternalServerError | Self::BadGateway | Self::GatewayTimeout => attempt < 2,
832            _ => attempt < 3,
833        }
834    }
835
836    /// 获取重试的指数退避延迟时间(毫秒)
837    ///
838    /// 提供智能的退避策略
839    pub fn exponential_backoff_delay(&self, attempt: u32) -> Option<u64> {
840        if !self.should_retry(attempt) {
841            return None;
842        }
843
844        let base_delay = self.suggested_retry_delay().unwrap_or(1);
845        let max_delay = match self {
846            Self::TooManyRequests => 300,   // 5分钟
847            Self::RateLimitExceeded => 180, // 3分钟
848            _ => 60,                        // 1分钟
849        };
850
851        // 指数退避公式: base_delay * 2^(attempt-1)
852        let delay = base_delay * 2u64.pow(attempt.saturating_sub(1));
853        Some(delay.min(max_delay))
854    }
855
856    /// 获取错误的严重程度
857    pub fn severity(&self) -> ErrorSeverity {
858        match self {
859            Self::Success => ErrorSeverity::Info,
860
861            // 客户端错误通常是警告级别
862            Self::BadRequest
863            | Self::Forbidden
864            | Self::NotFound
865            | Self::MethodNotAllowed
866            | Self::Conflict
867            | Self::ValidationError
868            | Self::MissingRequiredParameter
869            | Self::InvalidParameterFormat
870            | Self::ParameterOutOfRange
871            | Self::ResponseTooLarge => ErrorSeverity::Warning,
872
873            // 认证和权限错误是错误级别
874            Self::Unauthorized
875            | Self::AccessTokenInvalid
876            | Self::AppAccessTokenInvalid
877            | Self::TenantAccessTokenInvalid
878            | Self::AuthenticationFailed
879            | Self::TokenExpired
880            | Self::PermissionDenied
881            | Self::AccessDenied => ErrorSeverity::Error,
882
883            // 服务器和网络错误是严重错误
884            Self::InternalServerError
885            | Self::BadGateway
886            | Self::ServiceUnavailable
887            | Self::GatewayTimeout
888            | Self::NetworkTimeout
889            | Self::NetworkConnectionFailed
890            | Self::DnsResolutionFailed
891            | Self::SslCertificateError
892            | Self::ConnectionRefused
893            | Self::InternalError
894            | Self::ConfigurationError
895            | Self::ResourceExhausted => ErrorSeverity::Critical,
896
897            // 其他错误根据具体情况
898            _ => ErrorSeverity::Error,
899        }
900    }
901
902    /// 获取用户友好的恢复建议
903    pub fn recovery_suggestion(&self) -> &'static str {
904        match self {
905            Self::BadRequest => "请检查请求参数是否正确",
906            Self::Unauthorized => "请重新进行身份验证",
907            Self::Forbidden => "请联系管理员获取相应权限",
908            Self::NotFound => "请确认资源是否存在",
909            Self::TooManyRequests => "请降低请求频率后重试",
910            Self::NetworkConnectionFailed => "请检查网络连接",
911            Self::TokenExpired => "请重新获取访问令牌",
912            Self::ServiceUnavailable => "服务暂时不可用,请稍后重试",
913            Self::InternalServerError => "系统内部错误,请联系技术支持",
914            Self::ValidationError => "请检查输入参数格式",
915            Self::ConfigurationError => "请检查系统配置",
916            Self::ResponseTooLarge => "请减小请求范围或联系管理员调整响应大小限制",
917            Self::Unknown => "发生未知错误,请联系技术支持",
918            _ => "请稍后重试,如问题持续请联系技术支持",
919        }
920    }
921
922    /// 判断是否为用户操作导致的错误
923    pub fn is_user_error(&self) -> bool {
924        matches!(
925            self,
926            Self::BadRequest
927                | Self::Unauthorized
928                | Self::Forbidden
929                | Self::ValidationError
930                | Self::MissingRequiredParameter
931                | Self::InvalidParameterFormat
932                | Self::ParameterOutOfRange
933                | Self::AccessTokenInvalid
934                | Self::TokenExpired
935        )
936    }
937
938    /// 判断是否为系统问题导致的错误
939    pub fn is_system_error(&self) -> bool {
940        matches!(
941            self,
942            Self::InternalServerError
943                | Self::BadGateway
944                | Self::ServiceUnavailable
945                | Self::GatewayTimeout
946                | Self::NetworkTimeout
947                | Self::NetworkConnectionFailed
948                | Self::DnsResolutionFailed
949                | Self::SslCertificateError
950                | Self::ConnectionRefused
951                | Self::InternalError
952                | Self::ConfigurationError
953                | Self::ResourceExhausted
954        )
955    }
956
957    /// 获取日志级别建议
958    pub fn log_level(&self) -> &'static str {
959        match self.severity() {
960            ErrorSeverity::Info => "info",
961            ErrorSeverity::Warning => "warn",
962            ErrorSeverity::Error => "error",
963            ErrorSeverity::Critical => "error",
964        }
965    }
966}
967
968impl fmt::Display for ErrorCode {
969    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
970        write!(f, "{} ({})", self.description(), self.as_code())
971    }
972}
973
974/// 错误码分类
975#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
976pub enum ErrorCategory {
977    /// 成功
978    Success,
979    /// 认证错误
980    Authentication,
981    /// 权限错误
982    Permission,
983    /// 参数错误
984    Parameter,
985    /// 资源错误
986    Resource,
987    /// 服务器错误
988    Server,
989    /// 网络错误
990    Network,
991    /// 业务错误
992    Business,
993    /// 系统错误
994    System,
995    /// 限流错误
996    RateLimit,
997    /// 其他错误
998    Other,
999}
1000
1001impl ErrorCode {
1002    /// 获取错误码分类
1003    pub fn category(&self) -> ErrorCategory {
1004        match self {
1005            Self::Success => ErrorCategory::Success,
1006
1007            // 认证相关
1008            Self::Unauthorized
1009            | Self::AppTicketInvalid
1010            | Self::AccessTokenFormatInvalid
1011            | Self::AccessTokenInvalid
1012            | Self::AppAccessTokenInvalid
1013            | Self::TenantAccessTokenInvalid
1014            | Self::SsoTokenInvalid
1015            | Self::AuthenticationFailed
1016            | Self::TokenExpired
1017            | Self::AccessTokenExpiredV2
1018            | Self::InvalidSignature
1019            | Self::UserSessionInvalid
1020            | Self::UserSessionNotFound
1021            | Self::UserSessionTimeout
1022            | Self::UserIdentityInvalid
1023            | Self::UserTypeNotSupportedV2
1024            | Self::UserIdentityMismatch
1025            | Self::UserIdInvalid
1026            | Self::OpenIdInvalid
1027            | Self::UnionIdInvalid => ErrorCategory::Authentication,
1028
1029            // 权限相关
1030            Self::Forbidden
1031            | Self::AppPermissionDenied
1032            | Self::DocumentPermissionDenied
1033            | Self::PermissionDenied
1034            | Self::PermissionMissing
1035            | Self::AccessTokenNoPermission
1036            | Self::AccessDenied
1037            | Self::SecurityPolicyViolation => ErrorCategory::Permission,
1038
1039            // 参数相关
1040            Self::BadRequest
1041            | Self::ValidationError
1042            | Self::MissingRequiredParameter
1043            | Self::InvalidParameterFormat
1044            | Self::ParameterOutOfRange
1045            | Self::ChatTypeNotSupported
1046            | Self::MessageTypeNotSupported
1047            | Self::FileTypeNotSupported => ErrorCategory::Parameter,
1048
1049            // 资源相关
1050            Self::NotFound
1051            | Self::AppNotInstalled
1052            | Self::UserNotFound
1053            | Self::UserStatusException
1054            | Self::DepartmentNotFound
1055            | Self::ChatNotFound
1056            | Self::MessageNotFound
1057            | Self::FileNotFound
1058            | Self::FileSizeExceeded
1059            | Self::CalendarNotFound
1060            | Self::EventNotFound
1061            | Self::DocumentNotFound
1062            | Self::DocumentLocked
1063            | Self::SheetNotFound
1064            | Self::TableNotFound => ErrorCategory::Resource,
1065
1066            // 服务器相关
1067            Self::InternalServerError
1068            | Self::BadGateway
1069            | Self::ServiceUnavailable
1070            | Self::GatewayTimeout
1071            | Self::AppStatusException
1072            | Self::InternalError
1073            | Self::CacheServiceUnavailable => ErrorCategory::Server,
1074
1075            // 网络相关
1076            Self::NetworkTimeout
1077            | Self::NetworkConnectionFailed
1078            | Self::DnsResolutionFailed
1079            | Self::SslCertificateError
1080            | Self::ConnectionRefused => ErrorCategory::Network,
1081
1082            // 业务相关
1083            Self::Conflict
1084            | Self::EventConflict
1085            | Self::BusinessError
1086            | Self::OperationNotSupported
1087            | Self::ResourceConflict => ErrorCategory::Business,
1088
1089            // 系统相关
1090            Self::MethodNotAllowed
1091            | Self::SerializationError
1092            | Self::DataFormatError
1093            | Self::EncodingError
1094            | Self::ConfigurationError
1095            | Self::ResourceExhausted
1096            | Self::ResponseTooLarge => ErrorCategory::System,
1097
1098            // 限流相关
1099            Self::TooManyRequests | Self::RateLimitExceeded => ErrorCategory::RateLimit,
1100
1101            // 其他
1102            _ => ErrorCategory::Other,
1103        }
1104    }
1105}
1106
1107#[cfg(test)]
1108mod tests {
1109    use super::*;
1110
1111    #[test]
1112    fn test_error_code_conversion() {
1113        assert_eq!(ErrorCode::from_code(0), ErrorCode::Success);
1114        assert_eq!(ErrorCode::from_code(404), ErrorCode::NotFound);
1115        assert_eq!(ErrorCode::from_code(999999), ErrorCode::Unknown);
1116    }
1117
1118    /// `from_code` 是飞书通用码的唯一映射路径(#546 映射收敛 seam)。
1119    #[test]
1120    fn from_code_is_sole_feishu_common_code_mapper() {
1121        let cases = [
1122            (99991661, ErrorCode::AccessTokenFormatInvalid),
1123            (99991663, ErrorCode::TenantAccessTokenInvalid),
1124            (99991664, ErrorCode::AppAccessTokenInvalid),
1125            (99991670, ErrorCode::SsoTokenInvalid),
1126            (99991671, ErrorCode::AccessTokenInvalid),
1127            (99991672, ErrorCode::PermissionMissing),
1128            (99991676, ErrorCode::AccessTokenNoPermission),
1129            (99991677, ErrorCode::AccessTokenExpiredV2),
1130            (99991641, ErrorCode::UserSessionInvalid),
1131            (99991642, ErrorCode::UserSessionNotFound),
1132            (99991645, ErrorCode::UserSessionTimeout),
1133            (99991669, ErrorCode::UserIdentityInvalid),
1134            (99991674, ErrorCode::UserTypeNotSupportedV2),
1135            (99991675, ErrorCode::UserIdentityMismatch),
1136            (99992351, ErrorCode::UserIdInvalid),
1137            (99992352, ErrorCode::OpenIdInvalid),
1138            (99992353, ErrorCode::UnionIdInvalid),
1139        ];
1140        for (raw, expected) in cases {
1141            assert_eq!(
1142                ErrorCode::from_code(raw),
1143                expected,
1144                "from_code({raw}) must be the sole feishu-code mapping path"
1145            );
1146        }
1147        // 未知码:from_code → Unknown(不再有 Option::None 的并行路径)
1148        assert_eq!(ErrorCode::from_code(12345678), ErrorCode::Unknown);
1149    }
1150
1151    #[test]
1152    fn test_error_code_properties() {
1153        let not_found = ErrorCode::NotFound;
1154        assert_eq!(not_found.as_code(), 404);
1155        assert_eq!(not_found.description(), "资源不存在");
1156        assert!(not_found.is_client_error());
1157        assert!(!not_found.is_server_error());
1158        assert!(!not_found.is_retryable());
1159
1160        let timeout = ErrorCode::NetworkTimeout;
1161        assert!(timeout.is_network_error());
1162        assert!(timeout.is_retryable());
1163        assert_eq!(timeout.suggested_retry_delay(), Some(3));
1164    }
1165
1166    #[test]
1167    fn test_http_status_conversion() {
1168        assert_eq!(ErrorCode::from_http_status(200), ErrorCode::Success);
1169        assert_eq!(ErrorCode::from_http_status(404), ErrorCode::NotFound);
1170        assert_eq!(
1171            ErrorCode::from_http_status(500),
1172            ErrorCode::InternalServerError
1173        );
1174    }
1175
1176    #[test]
1177    fn test_error_categories() {
1178        let auth_error = ErrorCode::Unauthorized;
1179        assert_eq!(auth_error.category(), ErrorCategory::Authentication);
1180
1181        let perm_error = ErrorCode::Forbidden;
1182        assert_eq!(perm_error.category(), ErrorCategory::Permission);
1183
1184        let net_error = ErrorCode::NetworkTimeout;
1185        assert_eq!(net_error.category(), ErrorCategory::Network);
1186    }
1187
1188    #[test]
1189    fn test_error_code_display() {
1190        let error = ErrorCode::AccessTokenInvalid;
1191        let display = format!("{error}");
1192        assert!(display.contains("访问令牌无效"));
1193        assert!(display.contains("99991671"));
1194    }
1195
1196    #[test]
1197    fn test_new_error_code_methods() {
1198        // 测试便利创建方法
1199        assert_eq!(ErrorCode::network(), ErrorCode::NetworkConnectionFailed);
1200        assert_eq!(ErrorCode::authentication(), ErrorCode::AuthenticationFailed);
1201        assert_eq!(ErrorCode::permission(), ErrorCode::PermissionDenied);
1202        assert_eq!(ErrorCode::validation(), ErrorCode::ValidationError);
1203        assert_eq!(ErrorCode::configuration(), ErrorCode::ConfigurationError);
1204        assert_eq!(ErrorCode::internal(), ErrorCode::InternalError);
1205        assert_eq!(ErrorCode::serialization(), ErrorCode::SerializationError);
1206        assert_eq!(ErrorCode::unknown(), ErrorCode::Unknown);
1207    }
1208
1209    #[test]
1210    fn test_for_error_type() {
1211        assert_eq!(
1212            ErrorCode::for_error_type("Network"),
1213            ErrorCode::NetworkConnectionFailed
1214        );
1215        assert_eq!(
1216            ErrorCode::for_error_type("authentication"),
1217            ErrorCode::AuthenticationFailed
1218        );
1219        assert_eq!(
1220            ErrorCode::for_error_type("Validation"),
1221            ErrorCode::ValidationError
1222        );
1223        assert_eq!(
1224            ErrorCode::for_error_type("unknown_type"),
1225            ErrorCode::Unknown
1226        );
1227    }
1228
1229    #[test]
1230    fn test_from_message() {
1231        assert_eq!(
1232            ErrorCode::from_message("Network connection failed"),
1233            ErrorCode::NetworkConnectionFailed
1234        );
1235        assert_eq!(
1236            ErrorCode::from_message("Authentication token invalid"),
1237            ErrorCode::AuthenticationFailed
1238        );
1239        assert_eq!(
1240            ErrorCode::from_message("Permission denied"),
1241            ErrorCode::PermissionDenied
1242        );
1243        assert_eq!(
1244            ErrorCode::from_message("Invalid parameter"),
1245            ErrorCode::ValidationError
1246        );
1247        assert_eq!(
1248            ErrorCode::from_message("JSON parse error"),
1249            ErrorCode::SerializationError
1250        );
1251        assert_eq!(
1252            ErrorCode::from_message("Unknown error occurred"),
1253            ErrorCode::Unknown
1254        );
1255    }
1256
1257    #[test]
1258    fn test_retry_logic() {
1259        let retryable_error = ErrorCode::NetworkTimeout;
1260        assert!(retryable_error.should_retry(0));
1261        assert!(retryable_error.should_retry(1));
1262        assert!(!retryable_error.should_retry(3)); // 超过最大重试次数
1263
1264        let non_retryable_error = ErrorCode::BadRequest;
1265        assert!(!non_retryable_error.should_retry(0));
1266
1267        // 测试指数退避
1268        let delay = retryable_error.exponential_backoff_delay(2);
1269        assert!(delay.is_some());
1270        assert!(delay.unwrap() > 1); // 第二次重试应该有更长的延迟
1271    }
1272
1273    #[test]
1274    fn test_error_severity() {
1275        assert_eq!(ErrorCode::Success.severity(), ErrorSeverity::Info);
1276        assert_eq!(ErrorCode::BadRequest.severity(), ErrorSeverity::Warning);
1277        assert_eq!(ErrorCode::Unauthorized.severity(), ErrorSeverity::Error);
1278        assert_eq!(
1279            ErrorCode::InternalServerError.severity(),
1280            ErrorSeverity::Critical
1281        );
1282    }
1283
1284    #[test]
1285    fn test_recovery_suggestions() {
1286        let suggestion = ErrorCode::NetworkConnectionFailed.recovery_suggestion();
1287        assert!(suggestion.contains("网络"));
1288
1289        let suggestion = ErrorCode::TokenExpired.recovery_suggestion();
1290        assert!(suggestion.contains("令牌"));
1291
1292        let suggestion = ErrorCode::ValidationError.recovery_suggestion();
1293        assert!(suggestion.contains("参数"));
1294    }
1295
1296    #[test]
1297    fn test_user_vs_system_errors() {
1298        // 用户错误
1299        assert!(ErrorCode::BadRequest.is_user_error());
1300        assert!(ErrorCode::Unauthorized.is_user_error());
1301        assert!(ErrorCode::ValidationError.is_user_error());
1302
1303        // 系统错误
1304        assert!(ErrorCode::InternalServerError.is_system_error());
1305        assert!(ErrorCode::NetworkTimeout.is_system_error());
1306        assert!(ErrorCode::ServiceUnavailable.is_system_error());
1307
1308        // 交叉验证
1309        assert!(!ErrorCode::BadRequest.is_system_error());
1310        assert!(!ErrorCode::InternalServerError.is_user_error());
1311    }
1312
1313    #[test]
1314    fn test_log_levels() {
1315        assert_eq!(ErrorCode::Success.log_level(), "info");
1316        assert_eq!(ErrorCode::BadRequest.log_level(), "warn");
1317        assert_eq!(ErrorCode::Unauthorized.log_level(), "error");
1318        assert_eq!(ErrorCode::InternalServerError.log_level(), "error");
1319    }
1320}
1321
1322#[cfg(test)]
1323mod severity_tests {
1324    use super::*;
1325
1326    #[test]
1327    fn test_error_severity_basic() {
1328        assert_eq!(ErrorSeverity::Info.as_level(), 0);
1329        assert_eq!(ErrorSeverity::Warning.as_level(), 1);
1330        assert_eq!(ErrorSeverity::Error.as_level(), 2);
1331        assert_eq!(ErrorSeverity::Critical.as_level(), 3);
1332    }
1333
1334    #[test]
1335    fn test_error_severity_ordering() {
1336        assert!(ErrorSeverity::Info < ErrorSeverity::Warning);
1337        assert!(ErrorSeverity::Warning < ErrorSeverity::Error);
1338        assert!(ErrorSeverity::Error < ErrorSeverity::Critical);
1339    }
1340
1341    #[test]
1342    fn test_error_severity_from_level() {
1343        assert_eq!(ErrorSeverity::from_level(0), ErrorSeverity::Info);
1344        assert_eq!(ErrorSeverity::from_level(1), ErrorSeverity::Warning);
1345        assert_eq!(ErrorSeverity::from_level(2), ErrorSeverity::Error);
1346        assert_eq!(ErrorSeverity::from_level(3), ErrorSeverity::Critical);
1347        assert_eq!(ErrorSeverity::from_level(99), ErrorSeverity::Error); // 无效值默认为Error
1348    }
1349
1350    #[test]
1351    fn test_error_severity_properties() {
1352        assert!(!ErrorSeverity::Info.requires_immediate_action());
1353        assert!(!ErrorSeverity::Warning.requires_immediate_action());
1354        assert!(ErrorSeverity::Error.requires_immediate_action());
1355        assert!(ErrorSeverity::Critical.requires_immediate_action());
1356
1357        assert!(!ErrorSeverity::Info.requires_user_intervention());
1358        assert!(!ErrorSeverity::Warning.requires_user_intervention());
1359        assert!(ErrorSeverity::Error.requires_user_intervention());
1360        assert!(ErrorSeverity::Critical.requires_user_intervention());
1361
1362        assert!(ErrorSeverity::Info.is_auto_recoverable());
1363        assert!(ErrorSeverity::Warning.is_auto_recoverable());
1364        assert!(!ErrorSeverity::Error.is_auto_recoverable());
1365        assert!(!ErrorSeverity::Critical.is_auto_recoverable());
1366    }
1367
1368    #[test]
1369    fn test_error_severity_display() {
1370        assert_eq!(format!("{}", ErrorSeverity::Info), "信息");
1371        assert_eq!(format!("{}", ErrorSeverity::Warning), "警告");
1372        assert_eq!(format!("{}", ErrorSeverity::Error), "错误");
1373        assert_eq!(format!("{}", ErrorSeverity::Critical), "严重错误");
1374    }
1375}