111
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/// API 异常类
|
||||
/// API 異常類
|
||||
class ApiException implements Exception {
|
||||
final String message;
|
||||
final String code;
|
||||
@@ -12,7 +12,7 @@ class ApiException implements Exception {
|
||||
|
||||
factory ApiException.unauthorized([String? message]) {
|
||||
return ApiException(
|
||||
message: message ?? '未授权',
|
||||
message: message ?? '未授權',
|
||||
code: '0002',
|
||||
statusCode: 401,
|
||||
);
|
||||
@@ -20,14 +20,14 @@ class ApiException implements Exception {
|
||||
|
||||
factory ApiException.networkError([String? message]) {
|
||||
return ApiException(
|
||||
message: message ?? '网络错误',
|
||||
message: message ?? '網絡錯誤',
|
||||
code: 'NETWORK_ERROR',
|
||||
);
|
||||
}
|
||||
|
||||
factory ApiException.serverError([String? message]) {
|
||||
return ApiException(
|
||||
message: message ?? '服务器错误',
|
||||
message: message ?? '服務器錯誤',
|
||||
code: 'SERVER_ERROR',
|
||||
statusCode: 500,
|
||||
);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/// API 响应状态码
|
||||
/// API 響應狀態碼
|
||||
class ResponseCode {
|
||||
static const String success = '0000';
|
||||
static const String unauthorized = '0002';
|
||||
static const String kycRequired = 'KYC_REQUIRED';
|
||||
}
|
||||
|
||||
/// API 响应模型
|
||||
/// API 響應模型
|
||||
class ApiResponse<T> {
|
||||
final bool success;
|
||||
final String? message;
|
||||
|
||||
@@ -5,7 +5,7 @@ import '../storage/local_storage.dart';
|
||||
import 'api_exception.dart';
|
||||
import 'api_response.dart';
|
||||
|
||||
/// 网络配置常量
|
||||
/// 網絡配置常量
|
||||
class NetworkConfig {
|
||||
static const String baseUrl = ApiEndpoints.baseUrl;
|
||||
static const Duration connectTimeout = Duration(seconds: 15);
|
||||
@@ -13,11 +13,11 @@ class NetworkConfig {
|
||||
static const Duration sendTimeout = Duration(seconds: 15);
|
||||
}
|
||||
|
||||
/// Dio 网络客户端
|
||||
/// Dio 網絡客戶端
|
||||
class DioClient {
|
||||
late final Dio _dio;
|
||||
|
||||
/// 未授权回调(token 过期时触发)
|
||||
/// 未授權回調(token 過期時觸發)
|
||||
VoidCallback? onUnauthorized;
|
||||
|
||||
DioClient() {
|
||||
@@ -43,7 +43,7 @@ class DioClient {
|
||||
]);
|
||||
}
|
||||
|
||||
/// GET 请求
|
||||
/// GET 請求
|
||||
Future<ApiResponse<T>> get<T>(
|
||||
String path, {
|
||||
Map<String, dynamic>? queryParameters,
|
||||
@@ -57,7 +57,7 @@ class DioClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// POST 请求
|
||||
/// POST 請求
|
||||
Future<ApiResponse<T>> post<T>(
|
||||
String path, {
|
||||
dynamic data,
|
||||
@@ -71,7 +71,7 @@ class DioClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Multipart 文件上传
|
||||
/// Multipart 文件上傳
|
||||
Future<ApiResponse<T>> upload<T>(
|
||||
String path, {
|
||||
required FormData formData,
|
||||
@@ -96,21 +96,21 @@ class DioClient {
|
||||
final data = response.data;
|
||||
if (data is Map<String, dynamic>) {
|
||||
final apiResponse = ApiResponse.fromJson(data, fromJson);
|
||||
// 检测业务层未授权(后端返回 HTTP 200 + code "0002")
|
||||
// 注意:不再自动清除用户数据,避免误判
|
||||
// 只有在 HTTP 401 时才清除用户数据
|
||||
// 檢測業務層未授權(後端返回 HTTP 200 + code "0002")
|
||||
// 注意:不再自動清除用戶數據,避免誤判
|
||||
// 只有在 HTTP 401 時才清除用戶數據
|
||||
if (apiResponse.isUnauthorized) {
|
||||
debugPrint('业务层未授权响应: ${apiResponse.message}');
|
||||
// 不再自动调用 onUnauthorized,避免刷新时误判
|
||||
debugPrint('業務層未授權響應: ${apiResponse.message}');
|
||||
// 不再自動調用 onUnauthorized,避免刷新時誤判
|
||||
// onUnauthorized?.call();
|
||||
}
|
||||
return apiResponse;
|
||||
}
|
||||
return ApiResponse.fail('响应数据格式错误');
|
||||
return ApiResponse.fail('響應數據格式錯誤');
|
||||
}
|
||||
|
||||
ApiResponse<T> _handleError<T>(DioException e) {
|
||||
// 详细错误日志
|
||||
// 詳細錯誤日誌
|
||||
debugPrint('=== Network Error ===');
|
||||
debugPrint('Type: ${e.type}');
|
||||
debugPrint('Message: ${e.message}');
|
||||
@@ -122,7 +122,7 @@ class DioClient {
|
||||
if (_isUnauthorized(e)) {
|
||||
_clearUserData();
|
||||
onUnauthorized?.call();
|
||||
return ApiResponse.unauthorized('登录已过期,请重新登录');
|
||||
return ApiResponse.unauthorized('登錄已過期,請重新登錄');
|
||||
}
|
||||
|
||||
final message = _getErrorMessage(e);
|
||||
@@ -140,28 +140,28 @@ class DioClient {
|
||||
String _getErrorMessage(DioException e) {
|
||||
switch (e.type) {
|
||||
case DioExceptionType.connectionTimeout:
|
||||
return '连接超时,请检查网络';
|
||||
return '連接超時,請檢查網絡';
|
||||
case DioExceptionType.sendTimeout:
|
||||
return '发送超时,请重试';
|
||||
return '發送超時,請重試';
|
||||
case DioExceptionType.receiveTimeout:
|
||||
return '响应超时,请重试';
|
||||
return '響應超時,請重試';
|
||||
case DioExceptionType.connectionError:
|
||||
return '网络连接失败,请检查网络设置';
|
||||
return '網絡連接失敗,請檢查網絡設置';
|
||||
case DioExceptionType.badResponse:
|
||||
final statusCode = e.response?.statusCode;
|
||||
if (statusCode == 500) {
|
||||
return '服务器内部错误';
|
||||
return '服務器內部錯誤';
|
||||
} else if (statusCode == 502 || statusCode == 503) {
|
||||
return '服务暂时不可用';
|
||||
return '服務暫時不可用';
|
||||
}
|
||||
return '服务器错误 ($statusCode)';
|
||||
return '服務器錯誤 ($statusCode)';
|
||||
default:
|
||||
return e.message ?? '网络请求失败';
|
||||
return e.message ?? '網絡請求失敗';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 日志拦截器
|
||||
/// 日誌攔截器
|
||||
class _LoggingInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
@@ -195,7 +195,7 @@ class _LoggingInterceptor extends Interceptor {
|
||||
}
|
||||
}
|
||||
|
||||
/// 认证拦截器
|
||||
/// 認證攔截器
|
||||
class _AuthInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
|
||||
Reference in New Issue
Block a user