import 'package:dio/dio.dart'; abstract class ApiException implements Exception { final String message; final int? statusCode; const ApiException(this.message, {this.statusCode}); factory ApiException.fromDioError(Object error) { if (error is ApiException) return error; if (error is DioException) { final response = error.response; final statusCode = response?.statusCode; final data = response?.data; String detail; if (data is Map) { detail = (data['detail'] ?? data['message'] ?? data['error'])?.toString() ?? '请求失败'; } else { detail = '请求失败'; } final localized = _localizeError(detail, statusCode); if (statusCode == 401) { return UnauthorizedException(localized); } if (statusCode == 422) { return ValidationException( localized, errors: data, statusCode: statusCode, ); } return ServerException(localized, statusCode: statusCode); } return const ServerException('网络错误'); } static String _localizeError(String detail, int? statusCode) { if (statusCode == 403) { return '没有权限执行此操作'; } if (statusCode == 404) { return '请求的资源不存在'; } if (statusCode == 429) { return '请求过于频繁,请稍后再试'; } if (statusCode != null && statusCode >= 500) { return '服务器错误,请稍后再试'; } return detail; } } class ServerException extends ApiException { const ServerException(super.message, {super.statusCode}); } class UnauthorizedException extends ApiException { const UnauthorizedException([super.message = '请重新登录']) : super(statusCode: 401); } class ValidationException extends ApiException { final Map? errors; const ValidationException(super.message, {this.errors, super.statusCode}); }