import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:pretty_dio_logger/pretty_dio_logger.dart'; import 'package:wow_english/utils/toast_util.dart'; import '../core/user_util.dart'; import 'api_response/api_response_entity.dart'; import 'api_response/raw_data.dart'; import 'config.dart'; import 'exception.dart'; import 'token_interceptor.dart'; part 'apis.dart'; RequestClient requestClient = RequestClient(); class RequestClient { late Dio _dio; RequestClient() { _dio = Dio(BaseOptions(baseUrl: RequestConfig.baseUrl, connectTimeout: RequestConfig.connectTimeout)); _dio.interceptors.add(TokenInterceptor()); if (kDebugMode) { _dio.interceptors .add(PrettyDioLogger(requestHeader: true, requestBody: true, responseHeader: true, maxWidth: 120)); } } Future request( String url, { required String method, Map? queryParameters, data, Map? headers, Function(ApiResponse)? onResponse, bool Function(ApiException)? onError, }) async { try { Options options = Options() ..method = method ..headers = headers; data = _convertRequestData(data); Response response = await _dio.request(url, queryParameters: queryParameters, data: data, options: options); debugPrint("response.body type=${response.data.runtimeType}"); return _handleResponse(response, onResponse); } catch (e) { debugPrint("e type=${e.runtimeType}"); if (e is ApiException && e.code == 405) { showToast('登录已失效,请重新登录!', duration: const Duration(seconds: 3)); UserUtil.logout(); return null; } var exception = ApiException.from(e); if (onError?.call(exception) != true) { throw exception; } } return null; } _convertRequestData(data) { if (data != null) { data = jsonDecode(jsonEncode(data)); } return data; } /// get Future get( String url, { Map? queryParameters, Map? headers, bool showLoading = true, Function(ApiResponse)? onResponse, bool Function(ApiException)? onError, }) { return request(url, method: 'GET', queryParameters: queryParameters, headers: headers, onResponse: onResponse, onError: onError); } /// post Future post( String url, { Map? queryParameters, data, Map? headers, bool showLoading = true, Function(ApiResponse)? onResponse, bool Function(ApiException)? onError, }) { return request(url, method: "POST", queryParameters: queryParameters, data: data, headers: headers, onResponse: onResponse, onError: onError); } /// delete Future delete( String url, { Map? queryParameters, data, Map? headers, bool showLoading = true, Function(ApiResponse)? onResponse, bool Function(ApiException)? onError, }) { return request(url, method: "DELETE", queryParameters: queryParameters, data: data, headers: headers, onResponse: onResponse, onError: onError); } /// put Future put( String url, { Map? queryParameters, data, Map? headers, bool showLoading = true, Function(ApiResponse)? onResponse, bool Function(ApiException)? onError, }) { return request(url, method: "PUT", queryParameters: queryParameters, data: data, headers: headers, onResponse: onResponse, onError: onError); } /// 请求响应内容处理 T? _handleResponse( Response response, Function(ApiResponse)? onResponse, ) { int statusCode = response.statusCode ?? -1; // 200..299 成功响应 if (statusCode >= 200 && statusCode <= 299) { if (T.toString() == (RawData).toString()) { RawData raw = RawData(); raw.value = response.data; return raw as T; } else { // 应对response的header中content-type: [text/html;charset=utf-8]的情况 // 实际上都是json格式返回 Map json; if (response.data is String) { json = jsonDecode(response.data); } else { json = response.data; } ApiResponse apiResponse = ApiResponse.fromJson(json); onResponse?.call(apiResponse); return _handleBusinessResponse(apiResponse); } } else { ApiException exception = ApiException(response.statusCode, ApiException.unknownException); debugPrint("_handleResponse exception type=${exception.runtimeType}"); throw exception; } } /// 业务内容处理 T? _handleBusinessResponse(ApiResponse response) { if (response.code == RequestConfig.successCode) { return response.data; } else { ApiException exception = ApiException(response.code, response.msg); debugPrint("_handleBusinessResponse exception type=${exception.runtimeType}"); throw exception; } } }