379 lines
11 KiB
Dart
379 lines
11 KiB
Dart
import 'dart:convert';
|
||
import 'dart:io';
|
||
|
||
import 'package:circle_app/common/errorcode.dart';
|
||
import 'package:circle_app/util/util.dart';
|
||
import 'package:dio/dio.dart';
|
||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||
|
||
import '../util/SharedPreferencesHelper.dart';
|
||
import '../util/device.dart';
|
||
import 'api.dart';
|
||
import 'package:connectivity/connectivity.dart';
|
||
|
||
const String baseUrl = Api.baseUrl;
|
||
|
||
/// Dio 请求方法
|
||
|
||
enum DioMethod {
|
||
get,
|
||
post,
|
||
put,
|
||
delete,
|
||
}
|
||
|
||
class DioManager {
|
||
factory DioManager() => getInstance();
|
||
|
||
static DioManager get instance => getInstance();
|
||
static DioManager? _instance;
|
||
|
||
static DioManager getInstance() {
|
||
if (_instance == null) {
|
||
_instance = DioManager._init();
|
||
}
|
||
return _instance!;
|
||
}
|
||
|
||
Dio? _dio;
|
||
|
||
DioManager._init() {
|
||
_dio ??= Dio(BaseOptions(
|
||
// 请求基地址
|
||
baseUrl: baseUrl,
|
||
// 连接服务器超时时间,单位是毫秒
|
||
connectTimeout: const Duration(seconds: 30),
|
||
// 接收数据的最长时限
|
||
receiveTimeout: const Duration(seconds: 30),
|
||
));
|
||
_dio!.interceptors.add(LogInterceptor(
|
||
responseBody: true,
|
||
));
|
||
// _dio!.interceptors.add(ConnectivityInterceptor());
|
||
}
|
||
|
||
Future download(String urlPath, String savePath,
|
||
ProgressCallback progressCallback) async {
|
||
return await _dio!
|
||
.download(urlPath, savePath, onReceiveProgress: progressCallback);
|
||
}
|
||
|
||
/// get请求
|
||
/// [isShowErrorToast] 出现错误的情况是否自动弹窗提示错误,默认true
|
||
/// [isAddTokenInHeader] 请求头是否添加token
|
||
/// [fromJson]是将json转为model的方法
|
||
Future get<T>({
|
||
required String url,
|
||
bool isShowErrorToast = true,
|
||
bool isAddTokenInHeader = true,
|
||
Map<String, dynamic>? params,
|
||
}) async {
|
||
return await requestHttp(
|
||
url,
|
||
method: DioMethod.get,
|
||
isShowErrorToast: isShowErrorToast,
|
||
params: params,
|
||
);
|
||
}
|
||
|
||
/// post 请求
|
||
Future post<T>(
|
||
{required String url,
|
||
Map<String, dynamic>? params,
|
||
bool isAddTokenInHeader = true,
|
||
bool isShowErrorToast = true,
|
||
FormData? formData,
|
||
CancelToken? cancelToken,
|
||
ProgressCallback? onSendProgress,
|
||
ProgressCallback? onReceiveProgress}) async {
|
||
return await requestHttp<T>(url,
|
||
method: DioMethod.post,
|
||
isShowErrorToast: isShowErrorToast,
|
||
params: params,
|
||
formData: formData,
|
||
cancelToken: cancelToken,
|
||
onSendProgress: onSendProgress,
|
||
onReceiveProgress: onReceiveProgress);
|
||
}
|
||
|
||
/// put 请求
|
||
Future put<T>({
|
||
required String url,
|
||
Map<String, dynamic>? params,
|
||
bool isAddTokenInHeader = true,
|
||
bool isShowErrorToast = true,
|
||
FormData? formData,
|
||
CancelToken? cancelToken,
|
||
ProgressCallback? onSendProgress,
|
||
ProgressCallback? onReceiveProgress,
|
||
}) async {
|
||
return await requestHttp<T>(
|
||
url,
|
||
method: DioMethod.put,
|
||
// 修改请求方法为 put
|
||
isShowErrorToast: isShowErrorToast,
|
||
params: params,
|
||
formData: formData,
|
||
cancelToken: cancelToken,
|
||
onSendProgress: onSendProgress,
|
||
onReceiveProgress: onReceiveProgress,
|
||
);
|
||
}
|
||
|
||
Future delete<T>({
|
||
required String url,
|
||
Map<String, dynamic>? params,
|
||
bool isAddTokenInHeader = true,
|
||
bool isShowErrorToast = true,
|
||
FormData? formData,
|
||
CancelToken? cancelToken,
|
||
ProgressCallback? onSendProgress,
|
||
ProgressCallback? onReceiveProgress,
|
||
}) async {
|
||
return await requestHttp<T>(
|
||
url,
|
||
method: DioMethod.delete,
|
||
// 修改请求方法为 delete
|
||
isShowErrorToast: isShowErrorToast,
|
||
params: params,
|
||
formData: formData,
|
||
cancelToken: cancelToken,
|
||
onSendProgress: onSendProgress,
|
||
onReceiveProgress: onReceiveProgress,
|
||
);
|
||
}
|
||
|
||
/// Dio request 方法
|
||
Future requestHttp<T>(String url,
|
||
{DioMethod method = DioMethod.get,
|
||
Map<String, dynamic>? params,
|
||
bool isShowErrorToast = true,
|
||
bool isAddTokenInHeader = true,
|
||
FormData? formData,
|
||
CancelToken? cancelToken,
|
||
ProgressCallback? onSendProgress,
|
||
ProgressCallback? onReceiveProgress}) async {
|
||
const methodValues = {
|
||
DioMethod.get: 'get',
|
||
DioMethod.post: 'post',
|
||
DioMethod.delete: 'delete',
|
||
DioMethod.put: 'put'
|
||
};
|
||
var connectivityResult = await Connectivity().checkConnectivity();
|
||
|
||
if (connectivityResult == ConnectivityResult.none) {
|
||
// showToast("");
|
||
return {'code': 404, 'msg': '请检查网络连接是否正常'};
|
||
}
|
||
|
||
try {
|
||
Response response;
|
||
|
||
var options = Options();
|
||
bool isAgreemement = await getAgreemement();
|
||
if (isAgreemement) {
|
||
options = Options(method: methodValues[method], headers: {
|
||
"Authorization": await getAuthorization(),
|
||
'VersionName': await getVersionName(),
|
||
'VersionCode': await getVersionCode(),
|
||
'Platform': Platform.isIOS ? '1' : '0',
|
||
'OsVersion': await getDeviceId(),
|
||
'Imei': await getImei(),
|
||
'Brand': await getBrand(),
|
||
});
|
||
} else {
|
||
options = Options(method: methodValues[method], headers: {
|
||
"Authorization": await getAuthorization(),
|
||
'VersionName': await getVersionName(),
|
||
'VersionCode': await getVersionCode(),
|
||
'Platform': Platform.isIOS ? '1' : '0',
|
||
});
|
||
}
|
||
|
||
print(">>>>>$params");
|
||
|
||
/// 不同请求方法,不同的请求参数,按实际项目需求分.
|
||
/// 这里 get 是 queryParameters,其它用 data. FormData 也是 data
|
||
/// 注意: 只有 post 方法支持发送 FormData.
|
||
switch (method) {
|
||
case DioMethod.get:
|
||
response = await _dio!
|
||
.request(url, queryParameters: params, options: options);
|
||
break;
|
||
case DioMethod.post:
|
||
response = await _dio!.post(url,
|
||
data: params, cancelToken: cancelToken, options: options);
|
||
break;
|
||
case DioMethod.put:
|
||
response =
|
||
await _dio!.put(url, data: json.encode(params), options: options);
|
||
break;
|
||
case DioMethod.delete:
|
||
response = await _dio!
|
||
.delete(url, queryParameters: params, options: options);
|
||
break;
|
||
default:
|
||
// 如果有formData参数,说明是传文件,忽略params的参数
|
||
if (formData != null) {
|
||
response = await _dio!.post(url,
|
||
data: formData,
|
||
cancelToken: cancelToken,
|
||
onSendProgress: onSendProgress,
|
||
onReceiveProgress: onReceiveProgress);
|
||
} else {
|
||
response = await _dio!.request(url,
|
||
data: params, cancelToken: cancelToken, options: options);
|
||
}
|
||
}
|
||
// json转model
|
||
String jsonStr = json.encode(response.data);
|
||
Map<String, dynamic> responseMap = json.decode(jsonStr);
|
||
if (responseMap["code"] == 5003 || responseMap["code"] == 30003) {
|
||
showOKToast(responseMap['msg']);
|
||
pushLoginPage();
|
||
} else {
|
||
switch (responseMap["code"]) {
|
||
case 4001:
|
||
case 4002:
|
||
case 4003:
|
||
case 4004:
|
||
case 4100:
|
||
case 4101:
|
||
case 4102:
|
||
case 5002:
|
||
case 5001:
|
||
case 5000:
|
||
pushLoginPage();
|
||
break;
|
||
}
|
||
if (responseMap["code"] != 200 && responseMap["code"] != 10000 && !url.contains(Api.checkWxNumState)) {
|
||
showOKToast(responseMap['msg']);
|
||
}
|
||
}
|
||
return responseMap;
|
||
} on DioException catch (e) {
|
||
SharedPreferencesHelper sp = await SharedPreferencesHelper.getInstance();
|
||
if (sp.getString(SharedPreferencesHelper.LOGINPHONE) == '18800000100') {
|
||
return {'code': 500, 'msg': ''};
|
||
}
|
||
// // DioError是指返回值不为200的情况
|
||
// logger.shout('DioError报错${e.type}:${e.error.toString()}');
|
||
// // 对错误进行判断
|
||
// onErrorInterceptor(e);
|
||
// // 判断是否断网了
|
||
// String? errorMsg = isNetworkConnected
|
||
// ? e.requestOptions.extra["errorMsg"]
|
||
// : "网络连接断开,请检查网络设置";
|
||
return {'code': 500, 'msg': '服务器开小差了,请重试'};
|
||
} catch (e) {
|
||
SharedPreferencesHelper sp = await SharedPreferencesHelper.getInstance();
|
||
if (sp.getString(SharedPreferencesHelper.LOGINPHONE) == '18800000100') {
|
||
return {'code': 500, 'msg': ''};
|
||
}
|
||
// 其他一些意外的报错
|
||
return {'code': 500, 'msg': '加载中...'};
|
||
}
|
||
}
|
||
//
|
||
// // 错误判断
|
||
// void onErrorInterceptor(DioError err) {
|
||
// // 异常分类
|
||
// switch (err.type) {
|
||
// // 4xx 5xx response
|
||
// case DioErrorType.response:
|
||
// err.requestOptions.extra["errorMsg"] = err.response?.data ?? "连接异常";
|
||
// break;
|
||
// case DioErrorType.connectTimeout:
|
||
// err.requestOptions.extra["errorMsg"] = "连接超时";
|
||
// break;
|
||
// case DioErrorType.sendTimeout:
|
||
// err.requestOptions.extra["errorMsg"] = "发送超时";
|
||
// break;
|
||
// case DioErrorType.receiveTimeout:
|
||
// err.requestOptions.extra["errorMsg"] = "接收超时";
|
||
// break;
|
||
// case DioErrorType.cancel:
|
||
// err.requestOptions.extra["errorMsg"] =
|
||
// err.message.isNotEmpty ? err.message : "取消连接";
|
||
// break;
|
||
// case DioErrorType.other:
|
||
// default:
|
||
// err.requestOptions.extra["errorMsg"] = "连接异常";
|
||
// break;
|
||
// }
|
||
// }
|
||
}
|
||
|
||
class BaseResponse<T> {
|
||
int code;
|
||
String msg;
|
||
dynamic? data;
|
||
|
||
BaseResponse({required this.code, required this.msg, required this.data});
|
||
|
||
isSuccess() {
|
||
return code == 200;
|
||
}
|
||
|
||
factory BaseResponse.fromJson(
|
||
Map<String, dynamic> json, T Function(dynamic) fromJsonData) {
|
||
dynamic dataJson = json['data'];
|
||
T? data;
|
||
|
||
if (dataJson != null) {
|
||
if (dataJson is String) {
|
||
// 处理 dataJson 是 String 类型的情况
|
||
// 例如,可以直接将其赋值给 data 变量
|
||
data = null; // 根据你的需求修改赋值语句
|
||
} else if (dataJson is Map<String, dynamic>) {
|
||
// 处理 dataJson 是 Map<String, dynamic> 类型的情况
|
||
if (fromJsonData != null) {
|
||
data = fromJsonData(dataJson);
|
||
} else {
|
||
throw Exception('未提供 fromJsonData 函数来解析数据。');
|
||
}
|
||
} else if (dataJson is List) {
|
||
data = fromJsonData(dataJson);
|
||
} else {
|
||
throw Exception('无效的数据格式。期望是 String 或 Map<String, dynamic> 类型。');
|
||
}
|
||
}
|
||
|
||
return BaseResponse(
|
||
code: json['code'],
|
||
msg: json['msg'],
|
||
data: data,
|
||
);
|
||
}
|
||
}
|
||
|
||
class ConnectivityInterceptor extends Interceptor {
|
||
@override
|
||
Future<void> onRequest(
|
||
RequestOptions options, RequestInterceptorHandler handler) async {
|
||
if (!await isInternetAvailable()) {
|
||
showOKToast("请检查网络连接是否正常");
|
||
}
|
||
return handler.next(options);
|
||
}
|
||
|
||
Future<bool> isInternetAvailable() async {
|
||
var connectivityResult = await Connectivity().checkConnectivity();
|
||
return connectivityResult != ConnectivityResult.none;
|
||
}
|
||
}
|
||
|
||
class QnTokenData {
|
||
final String token;
|
||
final String cdnPrefix;
|
||
|
||
QnTokenData({required this.token, required this.cdnPrefix});
|
||
|
||
factory QnTokenData.fromJson(Map<String, dynamic> json) {
|
||
return QnTokenData(
|
||
token: json['token'],
|
||
cdnPrefix: json['cdn_prefix'],
|
||
);
|
||
}
|
||
}
|