222 lines
7.5 KiB
Dart
222 lines
7.5 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'package:get/get.dart' as getx;
|
|
import 'package:dio/dio.dart';
|
|
import 'package:making_school_asignment_app/common/utils/utils.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';
|
|
|
|
import '../job/user_info_detail.dart';
|
|
import '../utils/storage.dart';
|
|
|
|
class RequestTool {
|
|
static late Dio _dio;
|
|
// 初始化请求配置
|
|
static _init() {
|
|
BaseOptions options = BaseOptions(
|
|
baseUrl: RequestConfig().baseUrl,
|
|
connectTimeout: const Duration(milliseconds: RequestConfig.connectTimeout),
|
|
receiveTimeout: const Duration(milliseconds: RequestConfig.receiveTimeout),
|
|
);
|
|
_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!;
|
|
}
|
|
|
|
// DIO
|
|
Dio getDio() => _dio;
|
|
|
|
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<String, String> 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) {
|
|
const isProd = bool.fromEnvironment('dart.vm.product');
|
|
if (!isProd && RequestConfig.requestDataPrinting) {
|
|
toPrint(val: response.data, toPrintJson: true);
|
|
}
|
|
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 {
|
|
late getx.Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
|
|
|
|
@override
|
|
void onError(DioException error, ErrorInterceptorHandler handler) {
|
|
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;
|
|
|
|
if (errorMap is String && errorMap.length > 0) {
|
|
try {
|
|
var errorModel = jsonDecode(errorMap);
|
|
var error = errorModel['error'];
|
|
if (error != null && error["message"] != null) {
|
|
message = error["message"];
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
// 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), () {
|
|
if (getx.Get.currentRoute != Routes.login) {
|
|
UserStore.to.erase();
|
|
StorageService.to.erase();
|
|
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 = '请求错误';
|
|
}
|
|
if (message == '用户登录失效,请重新登录' && userInfo.value?.id == null) {
|
|
return handler.next(error);
|
|
}
|
|
Future.delayed(const Duration(milliseconds: 600), () => ToastUtils.showError(message));
|
|
return handler.next(error);
|
|
}
|
|
}
|