基础库
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

net_util.dart 20 KiB

4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. import 'dart:collection';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'dart:ui';
  5. import 'package:device_info/device_info.dart';
  6. import 'package:dio/adapter.dart';
  7. import 'package:dio/dio.dart';
  8. import 'package:flutter/material.dart';
  9. import 'package:fluttertoast/fluttertoast.dart';
  10. import 'package:imei_plugin/imei_plugin.dart';
  11. import 'package:package_info/package_info.dart';
  12. import 'package:provider/provider.dart';
  13. import 'package:zhiying_comm/util/empty_util.dart';
  14. import 'package:zhiying_comm/zhiying_comm.dart';
  15. import 'encode_util.dart';
  16. import 'global_config.dart';
  17. import 'shared_prefe_util.dart';
  18. import 'time_util.dart';
  19. typedef OnSuccess = dynamic Function(dynamic data);
  20. typedef OnError = dynamic Function(String e);
  21. typedef OnCache = dynamic Function(dynamic data);
  22. final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
  23. enum NetMethod {
  24. GET,
  25. POST,
  26. PUT,
  27. DELETE,
  28. OPTIONS,
  29. PATCH,
  30. UPDATE,
  31. HEAD,
  32. }
  33. class NetUtil {
  34. Dio _dio;
  35. NetUtil._();
  36. static NetUtil _instance;
  37. static NetUtil getInstance() {
  38. if (_instance == null) {
  39. _instance = NetUtil._();
  40. }
  41. return _instance;
  42. }
  43. get dio async {
  44. if (_dio == null) {
  45. var setting = await NativeUtil.getSetting();
  46. String domain = setting['domain']; //'http://www.hairuyi.com/';
  47. _config(domain, proxyUrl: ''); // 192.168.0.66:8866
  48. }
  49. return _dio;
  50. }
  51. /// 配置网络请求,基础地址,代理地址,如:192.168.0.123:8888(代理地址生产环境无效)
  52. /// apiVersion 接口版本
  53. void _config(String baseUrl, {String proxyUrl}) {
  54. _dio = Dio(BaseOptions(
  55. method: "post",
  56. baseUrl: baseUrl,
  57. connectTimeout: 15000,
  58. receiveTimeout: 15000,
  59. contentType: Headers.jsonContentType,
  60. followRedirects: true,
  61. // headers: {'device': 'wx_applet', 'Platform': 'wx_applet'},
  62. validateStatus: (_) {
  63. return true;
  64. }));
  65. _dio.interceptors.add(_NetInterceptors());
  66. // _dio.interceptors.add(LogInterceptor());
  67. const bool inProduction = const bool.fromEnvironment("dart.vm.product");
  68. if (proxyUrl != null && proxyUrl != '' && !inProduction) {
  69. _setProxy(proxyUrl);
  70. }
  71. }
  72. /// 设置代理
  73. void _setProxy(String proxyUrl) {
  74. (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
  75. client.findProxy = (uri) {
  76. return "PROXY $proxyUrl";
  77. };
  78. client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
  79. };
  80. }
  81. static Map<String, dynamic> headParam;
  82. /// 同步请求
  83. static Future<dynamic> post(String path,
  84. {Map<String, dynamic> params, Map<String, dynamic> queryParameters, NetMethod method = NetMethod.POST, bool cache = false, bool showToast = true}) async {
  85. var paramsData = {'postData': params ?? {}, 'queryParameters': queryParameters ?? {}};
  86. // 根据请求参数,获取缓存的Key
  87. String cacheKey = getRequestParamsCachedKey(paramsData, path);
  88. // 参数签名 TODO 加密?
  89. // post请求的参数
  90. Map<String, dynamic> bodyParams = params;
  91. ///只拿一次头部数据
  92. if (NetUtil.headParam == null) {
  93. NetUtil.headParam = await _getMustHeadParams();
  94. }
  95. // token 读取SP缓存中的用户token
  96. String token = await SharedPreferencesUtil.getStringValue(GlobalConfig.SHARED_KEY_TOKEN);
  97. if (EmptyUtil.isEmpty(token) && !bool.fromEnvironment("dart.vm.product")) {
  98. try {
  99. Map setting = await NativeUtil.getSetting();
  100. token = setting['token'];
  101. } catch (e, s) {
  102. print(s);
  103. print(e);
  104. }
  105. }
  106. if (!EmptyUtil.isEmpty(token)) {
  107. // params['token'] = token;
  108. NetUtil.headParam['Authorization'] = 'Bearer ' + token;
  109. }
  110. //获取imei
  111. if (!NetUtil.headParam.containsKey('imei') && path.contains("/api/v1/app/push_dialog")) {
  112. getImei();
  113. }
  114. if (NetUtil.headParam['token'] == null) {}
  115. // 请求头参数
  116. Map<String, dynamic> headParam = NetUtil.headParam;
  117. Response response;
  118. try {
  119. Dio dio = await NetUtil
  120. .getInstance()
  121. .dio;
  122. response = await dio.request(
  123. path,
  124. data: !EmptyUtil.isEmpty(bodyParams) ? bodyParams : null,
  125. options: Options(method: enumToString(method), headers: headParam),
  126. queryParameters: !EmptyUtil.isEmpty(queryParameters) ? queryParameters : null,
  127. );
  128. } on DioError catch (e) {
  129. _formatError(e);
  130. }
  131. try {
  132. var result = response.data is Map ? response.data : jsonDecode(response.data);
  133. // TODO 解密?
  134. if (isSuccess(result)) {
  135. // 缓存成功的数据
  136. if (cache) {
  137. _setCallBackCacheData(cacheKey, response.data is Map ? jsonEncode(response.data) : response.data);
  138. }
  139. return result;
  140. // 缓存返回的数据
  141. } else {
  142. Logger.error('error: ' + result[GlobalConfig.HTTP_RESPONSE_KEY_MSG]);
  143. ///
  144. /// 401000 验证用户失败(不提示Toast)
  145. /// 404004 没有找到对应模块(跳空页面,不提示toast)
  146. ///
  147. if (result[GlobalConfig.HTTP_RESPONSE_KEY_CODE] != 401000 && result[GlobalConfig.HTTP_RESPONSE_KEY_CODE] != 404004) {
  148. if (showToast) {
  149. Fluttertoast.showToast(
  150. msg: result[GlobalConfig.HTTP_RESPONSE_KEY_MSG],
  151. toastLength: Toast.LENGTH_SHORT,
  152. gravity: ToastGravity.BOTTOM,
  153. );
  154. }
  155. }
  156. ///
  157. /// 401003 用户被逼下线
  158. /// 退出登陆(清理token等用户信息)
  159. ///
  160. if (result[GlobalConfig.HTTP_RESPONSE_KEY_CODE]?.toString() == '401003') {
  161. try {
  162. Future.delayed(Duration(seconds: 0)).then((onValue) {
  163. BuildContext context = navigatorKey.currentState.overlay.context;
  164. Provider.of<UserInfoNotifier>(context, listen: false).unLogin();
  165. });
  166. } catch (e, s) {
  167. Logger.error(e, s);
  168. }
  169. }
  170. ///非法用户
  171. if (result[GlobalConfig.HTTP_RESPONSE_KEY_CODE]?.toString() == '401000') {
  172. try {
  173. Future.delayed(Duration(seconds: 0)).then((onValue) async {
  174. String token = await SharedPreferencesUtil.getStringValue(GlobalConfig.SHARED_KEY_TOKEN);
  175. if (token != null && token.length > 2) {
  176. BuildContext context = navigatorKey.currentState.overlay.context;
  177. Provider.of<UserInfoNotifier>(context, listen: false).unLogin();
  178. }
  179. });
  180. } catch (e, s) {
  181. Logger.error(e, s);
  182. }
  183. }
  184. ///
  185. /// 403028 账号被冻结
  186. /// 403029 账号被禁用
  187. /// 提示并且退出登录
  188. ///
  189. if (result[GlobalConfig.HTTP_RESPONSE_KEY_CODE]?.toString() == '403028' || result[GlobalConfig.HTTP_RESPONSE_KEY_CODE]?.toString() == '403029') {
  190. try {
  191. // 提示
  192. Fluttertoast.showToast(
  193. msg: result[GlobalConfig.HTTP_RESPONSE_KEY_MSG],
  194. toastLength: Toast.LENGTH_SHORT,
  195. gravity: ToastGravity.BOTTOM,
  196. );
  197. // 退出登录
  198. Future.delayed(Duration(seconds: 0)).then((onValue) {
  199. BuildContext context = navigatorKey.currentState.overlay.context;
  200. Provider.of<UserInfoNotifier>(context, listen: false).unLogin();
  201. });
  202. } catch (e, s) {
  203. Logger.error(e, s);
  204. }
  205. }
  206. return result;
  207. }
  208. } catch (e) {
  209. return null;
  210. }
  211. }
  212. /// 异步请求
  213. static void request(String path,
  214. {NetMethod method = NetMethod.GET,
  215. Map<String, dynamic> params,
  216. Map<String, dynamic> queryParameters,
  217. OnSuccess onSuccess,
  218. OnError onError,
  219. OnCache onCache,
  220. bool showToast = true}) async {
  221. var paramsData = {'postData': params ?? {}, 'queryParameters': queryParameters ?? {}};
  222. // 根据请求参数,获取缓存的Key
  223. String cacheKey = getRequestParamsCachedKey(paramsData, path);
  224. print("缓存Key" + cacheKey);
  225. // // 读取缓存回调
  226. if (onCache != null) {
  227. await _onCallBackCacheData(onCache, cacheKey);
  228. }
  229. try {
  230. Map result = await NetUtil.post(path, method: method,
  231. params: params,
  232. queryParameters: queryParameters,
  233. showToast: showToast,
  234. cache: onCache != null);
  235. // TODO 解密?
  236. if (isSuccess(result)) {
  237. if (onSuccess != null) {
  238. onSuccess(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
  239. }
  240. return;
  241. }
  242. if (onError != null) {
  243. onError(!EmptyUtil.isEmpty(result)
  244. ? !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_MSG])
  245. ? result[GlobalConfig.HTTP_RESPONSE_KEY_MSG]
  246. : '未知错误'
  247. : '未知错误');
  248. }
  249. } catch (e) {
  250. Logger.error('error: ' + e.toString());
  251. if (onError != null) {
  252. onError(e?.toString() ?? '未知错误');
  253. }
  254. }
  255. return;
  256. }
  257. /// 统一添加必要的参数
  258. // static Future<Map<String, dynamic>> signParams(Map<String, dynamic> params) async {
  259. // // 应用信息
  260. // PackageInfo packageInfo = await PackageInfo.fromPlatform();
  261. // // 原生传的信息
  262. // Map setting = await NativeUtil.getSetting();
  263. //
  264. // if (Platform.isIOS) {
  265. // IosDeviceInfo iosInfo = await DeviceInfoPlugin().iosInfo;
  266. // // 设备
  267. // params["platform"] = "ios";
  268. // // 设备系统版本
  269. // params["system_version"] = iosInfo?.systemVersion;
  270. // // 设备型号 如:iPhone 11pro
  271. // params['device_model'] = iosInfo?.name;
  272. // // 设备型号,如:MLMF2LL/A
  273. // // params['device_number'] = iosInfo?.model;
  274. // // 设备ID
  275. // params['device_id'] = iosInfo?.identifierForVendor;
  276. // } else if (Platform.isAndroid) {
  277. // AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo;
  278. // // 设备
  279. // params["platform"] = "android";
  280. // // 设备系统版本
  281. // params["system_version"] = "Android ${androidInfo?.version?.release}";
  282. // // 设备型号 如:iPhone 11pro
  283. // params['device_model'] = androidInfo?.model;
  284. // // 设备型号,如:MLMF2LL/A
  285. // // params['device_number'] = androidInfo?.id;
  286. // // 设备Id
  287. // params['device_id'] = androidInfo?.androidId;
  288. // }
  289. // // 应用版本号
  290. // params["app_version_name"] = packageInfo.version;
  291. // params["app_version"] = -1 ;// packageInfo.buildNumber;
  292. // // 分辨率
  293. // params["solution"] =
  294. // "${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}";
  295. //
  296. // // 站长ID
  297. // String masterId = setting['master_id'];
  298. // if (null != masterId &&
  299. // masterId != '' &&
  300. // (!params.containsKey('master_id') || params['master_id'] == '')) {
  301. // params['master_id'] = masterId;
  302. // }
  303. //
  304. // // secret_key
  305. // params['secret_key'] = setting['secret_key'];
  306. //
  307. // // token 读取SP缓存中的用户token
  308. // String token = await SharedPreferencesUtil.getStringValue(
  309. // GlobalConfig.SHARED_KEY_TOKEN);
  310. // if (!EmptyUtil.isEmpty(token)) {
  311. // params['token'] = token;
  312. // }
  313. //
  314. // // 当前时间戳:秒
  315. // params["time"] = TimeUtil.getNowTime();
  316. //
  317. // // 过滤空字段,过滤首尾空格
  318. // Map<String, dynamic> filters = Map<String, dynamic>();
  319. // params.forEach((key, value) {
  320. // if (key != '' && value != '') {
  321. // filters[key] = (value is String) ? value.trim() : value;
  322. // }
  323. // });
  324. // params = filters;
  325. //
  326. // List<String> list = List<String>();
  327. // params.forEach((key, value) {
  328. // list.add(key.toString() + value.toString());
  329. // });
  330. // params["sign"] = signWithArray(list);
  331. // return params;
  332. // }
  333. /// 获取必须的请求参数(用于请求头部)
  334. static Future<Map<String, String>> _getMustHeadParams() async {
  335. Map<String, String> params = new HashMap<String, String>();
  336. // 应用信息
  337. PackageInfo packageInfo = await PackageInfo.fromPlatform();
  338. // 原生传的信息
  339. Map setting = await NativeUtil.getSetting();
  340. if (Platform.isIOS) {
  341. IosDeviceInfo iosInfo = await DeviceInfoPlugin().iosInfo;
  342. // 设备
  343. params["platform"] = "ios";
  344. // 设备系统版本
  345. params["os_version"] = iosInfo?.systemVersion?.toString();
  346. // 设备型号 如:iPhone 11pro
  347. params['device_model'] = EncodeUtil.encodeBase64(iosInfo?.name?.toString() ?? '');
  348. // 设备ID
  349. params['device_id'] = iosInfo?.identifierForVendor?.toString();
  350. // idfa
  351. params['idfa'] = iosInfo?.identifierForVendor?.toString();
  352. } else if (Platform.isAndroid) {
  353. AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo;
  354. // 设备
  355. params["platform"] = "android";
  356. // 设备系统版本
  357. params["os_version"] = "Android ${androidInfo?.version?.release}";
  358. // 设备型号 如:iPhone 11pro
  359. params['device_model'] = androidInfo?.model?.toString();
  360. // 设备Id
  361. params['device_id'] = androidInfo?.androidId?.toString();
  362. }
  363. // 应用版本号
  364. params["app_version_name"] = packageInfo.version?.toString();
  365. params["AppVersionName"] = packageInfo.version?.toString();
  366. params["app_version"] = packageInfo.buildNumber?.toString();
  367. // 分辨率
  368. params["solution"] = "${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}";
  369. // 站长ID
  370. String masterId = setting['master_id'];
  371. if (null != masterId && masterId != '' && (!params.containsKey('master_id') || params['master_id'] == '')) {
  372. params['master_id'] = masterId; //!EmptyUtil.isEmpty(masterId) ? masterId : 'template_database';
  373. params['MasterId'] = masterId; //!EmptyUtil.isEmpty(masterId) ? masterId : 'template_database';
  374. }
  375. // token 读取SP缓存中的用户token
  376. String token = await SharedPreferencesUtil.getStringValue(GlobalConfig.SHARED_KEY_TOKEN);
  377. if (EmptyUtil.isEmpty(token) && !bool.fromEnvironment("dart.vm.product")) {
  378. try {
  379. token = setting['token'];
  380. } catch (e, s) {
  381. print(s);
  382. print(e);
  383. }
  384. }
  385. if (!EmptyUtil.isEmpty(token)) {
  386. // params['token'] = token;
  387. params['Authorization'] = 'Bearer ' + token;
  388. }
  389. // secret_key
  390. params['secret_key'] = setting['secret_key'] ?? '';
  391. // 当前时间戳:秒
  392. params["time"] = TimeUtil.getNowTime();
  393. // 过滤空字段,过滤首尾空格
  394. Map<String, String> filters = Map<String, String>();
  395. params.forEach((key, value) {
  396. if (key != '' && value != '') {
  397. filters[key] = (value is String) ? value.trim() : value;
  398. }
  399. });
  400. params = filters;
  401. List<String> list = List<String>();
  402. params.forEach((key, value) {
  403. list.add(key.toString() + '=' + value.toString() + '&');
  404. });
  405. params["sign"] = signWithArray(list);
  406. params.remove('secret_key');
  407. return params;
  408. }
  409. /// 获取Android imei
  410. static Future<String> _getImei() async {
  411. try {
  412. return await ImeiPlugin.getImei(shouldShowRequestPermissionRationale: true);
  413. } catch (e, s) {
  414. Logger.error(e, s);
  415. }
  416. return null;
  417. }
  418. /// 获取请求缓存成功的数据
  419. static Future<void> _onCallBackCacheData(OnCache onCache, String cacheKey) async {
  420. // 读取缓存
  421. Map<String, dynamic> cacheMap = await SharedPreferencesUtil.getNetCacheResult(cacheKey);
  422. if (!EmptyUtil.isEmpty(cacheMap) &&
  423. cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) &&
  424. (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE ||
  425. cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}') &&
  426. !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
  427. onCache(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
  428. return;
  429. }
  430. return;
  431. }
  432. /// 缓存请求成功的数据
  433. static void _setCallBackCacheData(String cacheKey, String value) async {
  434. SharedPreferencesUtil.setNetCacheResult(cacheKey, value);
  435. }
  436. /// 根据请求参数,获取缓存的数据
  437. static Future<dynamic> getRequestCachedData(String url, {Map<String, dynamic> params, Map<String, dynamic> queryParameters}) async {
  438. var paramsData = {'postData': params ?? {}, 'queryParameters': queryParameters ?? {}};
  439. Map<String, dynamic> cacheMap = await SharedPreferencesUtil.getNetCacheResult(getRequestParamsCachedKey(paramsData, url));
  440. if (!EmptyUtil.isEmpty(cacheMap) &&
  441. cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) &&
  442. (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE ||
  443. cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}') &&
  444. !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
  445. return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA];
  446. }
  447. return null;
  448. }
  449. /// 判断后台返回是否成功
  450. static bool isSuccess(Map<String, dynamic> data) {
  451. try {
  452. if (!EmptyUtil.isEmpty(data) &&
  453. (data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE ||
  454. data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}')) {
  455. return true;
  456. }
  457. } catch (e) {
  458. return false;
  459. }
  460. return false;
  461. }
  462. /// 根据请求参数,获取缓存的Key
  463. static String getRequestParamsCachedKey(Map<String, dynamic> map, String path) {
  464. String key;
  465. if (EmptyUtil.isEmpty(map)) {
  466. key = EncodeUtil.generateMd5(path);
  467. } else {
  468. key = EncodeUtil.generateMd5(path + map.toString());
  469. }
  470. return key;
  471. }
  472. // 七牛云文件上传
  473. static Future uploadFile(String url, File file, {String method = 'POST', Map<String, dynamic> params, OnSuccess onSuccess, OnError onError}) async {
  474. if (params == null) {
  475. params = {};
  476. }
  477. Dio dio = Dio(BaseOptions(
  478. method: "post",
  479. connectTimeout: 15000,
  480. receiveTimeout: 15000,
  481. contentType: Headers.jsonContentType,
  482. followRedirects: true,
  483. ));
  484. params['file'] = await MultipartFile.fromFile(file.path);
  485. FormData format = FormData.fromMap(params);
  486. return dio.request(url, data: format, options: Options(method: method));
  487. }
  488. /// 签名
  489. static String signWithArray(List<String> params) {
  490. // 字母升序
  491. params.sort();
  492. String result = "";
  493. params.forEach((param) {
  494. result += param;
  495. });
  496. result = result.substring(0, result.length - 1);
  497. return EncodeUtil.generateMd5(result);
  498. }
  499. /*
  500. * error统一处理
  501. */
  502. static void _formatError(DioError e) {
  503. if (e.type == DioErrorType.CONNECT_TIMEOUT) {
  504. Logger.error('连接超时: ${e.toString()}');
  505. } else if (e.type == DioErrorType.SEND_TIMEOUT) {
  506. Logger.error('请求超时: ${e.toString()}');
  507. } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
  508. Logger.error('响应超时: ${e.toString()}');
  509. } else if (e.type == DioErrorType.RESPONSE) {
  510. Logger.error('出现异常: ${e.toString()}');
  511. } else if (e.type == DioErrorType.CANCEL) {
  512. Logger.error('请求取消: ${e.toString()}');
  513. } else {
  514. Logger.error('未知错误: ${e.toString()}');
  515. }
  516. }
  517. static void getImei() async {
  518. NetUtil.headParam['imei'] = await _getImei();
  519. }
  520. }
  521. /**
  522. * @description: 网络请求拦截器
  523. * @param {type}
  524. * @return:
  525. */
  526. class _NetInterceptors extends InterceptorsWrapper {
  527. @override
  528. Future onRequest(RequestOptions options) {
  529. Logger.net(options?.uri?.toString(), data: options.data.toString());
  530. // TODO 加密?
  531. return super.onRequest(options);
  532. }
  533. @override
  534. Future onResponse(Response response) {
  535. Logger.endNet(response?.request?.uri?.toString(), data: response?.data?.toString() ?? '');
  536. // TODO 解密?
  537. return super.onResponse(response);
  538. }
  539. @override
  540. Future onError(DioError err) {
  541. // Logger.error(err);
  542. return super.onError(err);
  543. }
  544. }