import 'dart:convert'; import 'package:get/get.dart' as get_package; import 'package:dio/dio.dart'; import 'package:sk_base_mobile/models/base_response.dart'; import 'package:sk_base_mobile/util/logger_util.dart'; import 'package:sk_base_mobile/config.dart'; import 'package:sk_base_mobile/services/storage.service.dart'; import 'package:sk_base_mobile/store/auth.store.dart'; import 'package:sk_base_mobile/util/snack_bar.util.dart'; import '../constants/constants.dart'; class DioService extends get_package.GetxService { static DioService get to => get_package.Get.find(); static Dio get dio => _dio; static late Dio _dio; List whiteList = [Urls.login]; BaseOptions dioBaseOptions = BaseOptions( connectTimeout: const Duration(seconds: GloablConfig.DIO_TIMEOUT), baseUrl: GloablConfig.BASE_URL, followRedirects: true); late CancelToken cancelToken; /// Initialize the dio instance Future init() async { _dio = Dio(dioBaseOptions); _dio.interceptors.add(InterceptorsWrapper( onRequest: onRequest, onResponse: onResponse, onError: onError)); cancelToken = CancelToken(); return this; } void onError(DioException e, ErrorInterceptorHandler handler) async { if (whiteList.contains(e.requestOptions.path)) { return handler.next(e); } if (GloablConfig.DEBUG) { LoggerUtil().info( "[Service-dio] Error found on ${e.requestOptions.method} ${e.requestOptions.uri}"); } if (e.type == DioExceptionType.connectionTimeout) { // It occurs when url is opened timeout. await SnackBarUtil().error(TextEnum.serverErrorMsg); } else if (e.type == DioExceptionType.connectionError) { // It occurs when url is opened timeout. await SnackBarUtil().error(TextEnum.serverErrorMsg); } else if (e.type == DioExceptionType.sendTimeout) { // It occurs when url is sent timeout. // await SnackBarUtil().error( // 'The server is busy, please try again.', // ); } else if (e.type == DioExceptionType.receiveTimeout) { //It occurs when receiving timeout // await SnackBarUtil().error( // 'The server is busy, please try again.', // ); } else if (e.type == DioExceptionType.badResponse) { // When the server response, but with a incorrect status, such as 404, 503... if (e.response?.statusCode == 400) { await SnackBarUtil().error( e.response?.data['message'], ); } else if (e.response?.statusCode == 401) { // dio.lock(); LoggerUtil().error('[Service-dio] logout:${e.response}'); Future.delayed(Duration(seconds: 1), () { AuthStore().logout(force: true); }); SnackBarUtil().error('请重新登录'); } else if (e.response?.statusCode == 403) { await SnackBarUtil().error( '${e.response?.data['message']}.', ); // await AuthStore().logout(force: true); } else if (e.response?.statusCode == 409) { await SnackBarUtil().error(e.response?.data['message']); } else if (e.response?.statusCode == 500) { await SnackBarUtil() .error('The server is busy, please try again later'); } else if (e.response?.statusCode == 404) { LoggerUtil().error('[Service-dio] logout:${e.response}'); // await AuthStore().logout(force: true); } else if (e.response?.statusCode == 422) { await SnackBarUtil().error(e.response?.data['message']); } } else if (e.type == DioExceptionType.cancel) { // When the request is cancelled, dio will throw a error with this type. LoggerUtil().error("[Service-dio] 请求取消"); } else { //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null. LoggerUtil().error("[Service-dio] 未知错误:$e"); if ((e.error?.toString() ?? '') .toString() .contains("HandshakeException")) { // Just a network failure } else { await SnackBarUtil().error(e.error.toString()); // AuthStore().logout(force: true); } } return handler.next(e); } whiteListFilter(String url) => url.endsWith('_allow_anonymous=true'); void onRequest(RequestOptions options, RequestInterceptorHandler handler) { if (!whiteList.contains(options.path)) { String? token = StorageService.to.getString(CacheKeys.token, isWithUser: false); if (options.headers['Authorization'] == null && token != null) { options.headers["Authorization"] = "Bearer $token"; } options.headers['device-id'] = StorageService.to.getString( CacheKeys.deviceUUID, isWithUser: false); // 设备id或者udid,保证当前设备唯一值。 options.headers["platform"] = "iOS"; options.headers['model'] = StorageService.to .getString(CacheKeys.deviceModel, isWithUser: false); // 设备型号 } // if (GloablConfig.DEBUG && (options.data is! FormData)) { // LoggerUtil().info( // '[Service-dio] url: ${options.path}, params: ${jsonEncode(options.queryParameters)}, body: ${jsonEncode(options.data)}, Header:${jsonEncode(options.headers)}'); // } handler.next(options); } void onResponse(Response response, ResponseInterceptorHandler handler) async { /* LoggerUtil().info('[Service-dio] ${response.data}'); */ if (whiteList.contains(response.requestOptions.path)) { handler.next(response); return; } if (response.data != null && response.data is Map) { if (response.data['code'] == 200) { // if (GloablConfig.DEBUG) LoggerUtil().info(response.data['data']); response.data = response.data['data']; // 分页数据处理 if (response.data != null && response.data is Map && response.data['meta'] != null && response.data['items'] != null) { response.data = PaginationData.fromJson(response.data); } } else if (response.data['message'] != null) { await SnackBarUtil().error(response.data['message']); } } handler.next(response); } }