import 'dart:convert'; import 'dart:io'; import 'package:get/get.dart' as getx; import 'package:dio/dio.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:making_school_asignment_app/common/api/retrofit_client.dart'; import 'package:making_school_asignment_app/common/config/request_config.dart'; import 'package:making_school_asignment_app/common/job/user_info.dart'; import 'package:making_school_asignment_app/common/store/user_store.dart'; import 'package:making_school_asignment_app/common/utils/toast_utils.dart'; import 'package:making_school_asignment_app/routes/app_pages.dart'; class RequestTool { // 初始化请求配置 static _init() { BaseOptions options = BaseOptions( baseUrl: RequestConfig().baseUrl, connectTimeout: const Duration(milliseconds: RequestConfig.connectTimeout), receiveTimeout: const Duration(milliseconds: RequestConfig.receiveTimeout), ); Dio dio = Dio(options); dio.interceptors.add(AuthInterceptor()); // 添加 token dio.interceptors.add(ResponseHandle()); // 添加 数据返回拦截 dio.interceptors.add(TheError()); // 添加 数据返回拦截 const isProd = bool.fromEnvironment('dart.vm.product'); if (!isProd && RequestConfig.requestDataPrinting) { dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 } return RetrofitClient(dio, baseUrl: RequestConfig().baseUrl); } final RetrofitClient _client; static RequestTool? _instance; RequestTool._internal(this._client); static get instance { if (_instance == null) { RetrofitClient client = _init(); _instance = RequestTool._internal(client); } return _instance!; } RetrofitClient getClient() => _client; } /* * *AuthInterceptor *添加header认证 * */ class AuthInterceptor extends Interceptor { @override onRequest(RequestOptions options, RequestInterceptorHandler handler) async { //获取app版本 PackageInfo packageInfo = await PackageInfo.fromPlatform(); String version = packageInfo.version; // ignore: non_constant_identifier_names String PLATFORM = "android"; //可根据代码进行判断 if (Platform.isIOS) { PLATFORM = "ios"; } else if (Platform.isAndroid) { PLATFORM = "android"; } else if (Platform.isWindows) { PLATFORM = "Windows"; } else if (Platform.isMacOS) { PLATFORM = "macos"; } else if (Platform.isLinux) { PLATFORM = "Linux"; } Map headers = {}; headers["Accept-Charset"] = "utf-8"; headers["Connection"] = "keep-alive"; headers["Accept"] = "*/*"; headers["x-version"] = version; //自己更改配置 headers["x-platform"] = PLATFORM; //获取存储数据 保存header token String? token = UserStore.to.token; String? xToken = UserStore.to.xToken; UserInfo? userInfo = UserStore.to.userInfo.value; if (null != token && token.isNotEmpty) { headers["Authorization"] = token; //添加自己项目中的请求头 进行保存 } if ((userInfo?.isExpired() ?? false) && (xToken?.isNotEmpty ?? false)) { headers["x-Authorization"] = xToken!; } if ((userInfo?.isExpired() ?? false) && userInfo?.termYear != '') { headers["term-year"] = userInfo!.termYear; } options.headers = headers; return super.onRequest(options, handler); } } /* * ResponseHandle * 监听返回响应 **/ class ResponseHandle extends Interceptor { @override void onResponse(Response response, ResponseInterceptorHandler handler) { if (RequestConfig.successCode.contains(response.statusCode)) { // String? token = response.headers.value('access-token'); String? xtoken = response.headers.value('x-access-token'); if (token?.isNotEmpty ?? false) { UserStore.to.setToken(token!); var payloadBase64 = token.split('.')[1]; final normalizedPayload = base64.normalize(payloadBase64); final payloadString = utf8.decode(base64.decode(normalizedPayload)); UserStore.to.setUserInfo(UserInfo.fromJson(jsonDecode(payloadString))); } if (xtoken?.isNotEmpty ?? false) UserStore.to.setXToken(xtoken!); } super.onResponse(response, handler); } } class TheError extends Interceptor { @override void onError(DioException error, ErrorInterceptorHandler handler) { print('----------------'); print(error); print('*************'); var message = '请求错误,请重试'; switch (error.type) { case DioExceptionType.connectionTimeout: message = '请求链接超时'; break; case DioExceptionType.badCertificate: message = '证书错误,清联系管理员'; break; case DioExceptionType.sendTimeout: message = '请求发送超时'; break; case DioExceptionType.receiveTimeout: message = '接收超时时发生'; break; case DioExceptionType.badResponse: if (error.response == null) { print('请求进入异常但是请求response'); } else { Response? response = error.response; if (response != null) { int? statusCode = response.statusCode; var errorMap = response.data; // var runtimeType = errorMap.runtimeType; if (errorMap is Map && errorMap['error'] != null) { message = errorMap['error']?['message'] ?? '请求错误,请重试'; } else { if (statusCode != null) { switch (statusCode) { case 401: message = '用户登录失效,请重新登录'; Future.delayed(const Duration(seconds: 2), () => getx.Get.offAllNamed(Routes.login)); break; case 404: // message = '用户登录失效,请重新登录'; // Future.delayed(const Duration(seconds: 2), () => getx.Get.offAllNamed(Routes.login)); break; default: } } } } } break; case DioExceptionType.cancel: message = '请求已取消'; break; case DioExceptionType.connectionError: message = '当前无网络,请重试'; break; default: message = '请求错误'; } ToastUtils.showError(message); return handler.next(error); } }