YSNetWorking.dart 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. import 'dart:convert';
  2. import 'dart:isolate';
  3. import 'dart:typed_data';
  4. import 'package:dio/dio.dart';
  5. import 'package:encrypt/encrypt.dart';
  6. import 'package:flutter/cupertino.dart';
  7. import 'package:flutter/foundation.dart';
  8. import 'package:flutter/material.dart';
  9. import 'package:ysairplane2/code/YSBind.dart';
  10. import 'package:ysairplane2/code/YSLogin.dart';
  11. import 'package:fluttertoast/fluttertoast.dart';
  12. import 'package:shared_preferences/shared_preferences.dart';
  13. import 'YSTools.dart';
  14. //http://aviation.ytby0402.top
  15. //http://192.168.1.3:8082
  16. //https://api.s-fly.cn
  17. String base = 'http://aviation.ytby0402.top';
  18. int outTime = 20000;
  19. enum requestType{
  20. put,
  21. delete,
  22. get,
  23. post
  24. }
  25. typedef widgetCallback = Widget Function(dynamic value);
  26. ysRequestHttp(BuildContext context,{requestType type,String api,var parameter,bool isLoading,VoidCallback refresh,bool isToken}) async {
  27. FocusScope.of(context).unfocus();
  28. if(isLoading==true)showDialog(
  29. context: context,
  30. barrierDismissible: false,
  31. builder: (BuildContext context) {
  32. return LoadingDialog();
  33. }
  34. );
  35. try {
  36. SharedPreferences prefs = await SharedPreferences.getInstance();
  37. String token = prefs.getString('token');
  38. Map<String, dynamic> httpHeaders = {
  39. 'Accept': 'application/json,*/*',
  40. 'Content-Type': 'application/json',
  41. if(isToken==true)'Authentication': token??''
  42. };
  43. String url = base+api;
  44. print('请求网址:$url');
  45. if(isToken==true)print('token:$token');
  46. print('请求参数:$parameter');
  47. Response response;
  48. if(type==requestType.put){
  49. response = await Dio().put(url,data: parameter,options: Options(receiveTimeout: outTime,headers: httpHeaders));
  50. }else if(type==requestType.post){
  51. response = await Dio().post(url,data: parameter,options: Options(receiveTimeout: outTime,headers: httpHeaders));
  52. }else if(type==requestType.delete){
  53. response = await Dio().delete(url,data: parameter,options: Options(receiveTimeout: outTime,headers: httpHeaders));
  54. }else{
  55. response = await Dio().get(url,queryParameters: Map<String, dynamic>.from(parameter),options: Options(receiveTimeout: outTime,headers: httpHeaders));
  56. }
  57. LogUtil.d('请求结果:${response.data}');
  58. Map dict = response.data;
  59. if(isLoading==true)Navigator.of(context,rootNavigator: true).pop();
  60. if(dict['code']==200){
  61. //ysFlutterToast(context,'操作成功');
  62. return dict;
  63. }else if(dict['code']==500){
  64. ysFlutterToast(context,'网络错误');
  65. }else if(dict['code']==404){
  66. ysFlutterToast(context,'接口请求错误');
  67. }else if(dict['code']==402){
  68. ysFlutterToast(context,'${dict['msg']}');
  69. }else if(dict['code']==401){
  70. ysFlutterToast(context,'登陆已过期');
  71. Navigator.of(context,rootNavigator: true).push(
  72. CupertinoPageRoute(
  73. fullscreenDialog: true,
  74. builder: (context){
  75. Future<SharedPreferences> _prefer = SharedPreferences.getInstance();
  76. _prefer.then((value){
  77. value.remove('token');
  78. });
  79. return YSLogin();
  80. }
  81. )
  82. ).then((value){
  83. if(refresh!=null&&value!=null){
  84. refresh();
  85. }
  86. });
  87. }else if(dict['code']==400){
  88. ysFlutterToast(context,'没有检测到手机号');
  89. }else if(dict['code']==403){
  90. ysFlutterToast(context,'没有相关权限');
  91. }else if(dict['code']==405){
  92. ysFlutterToast(context,'没有注册,请注册');
  93. if(isToken==true)Navigator.of(context).push(
  94. CupertinoPageRoute(
  95. fullscreenDialog: true,
  96. builder: (context){
  97. Future<SharedPreferences> _prefer = SharedPreferences.getInstance();
  98. _prefer.then((value){
  99. value.remove('token');
  100. });
  101. return YSLogin();
  102. }
  103. )
  104. ).then((value){
  105. if(refresh!=null&&value!=null){
  106. refresh();
  107. }
  108. });
  109. }else if(dict['code']==406){
  110. ysFlutterToast(context,'密码错误');
  111. }else if(dict['code']==407){
  112. ysFlutterToast(context,'注册成功,需要新建账号');
  113. if(api=='/app/applets/verificationCode'){
  114. SharedPreferences prefer = await SharedPreferences.getInstance();
  115. prefer.setString('token', dict['token']);
  116. prefer.setString('name', dict['nickname']);
  117. prefer.setString('phone', dict['phoneNumber']);
  118. }
  119. Navigator.of(context).push(
  120. CupertinoPageRoute(
  121. builder: (context){
  122. return YSBind();
  123. }
  124. )
  125. );
  126. }else if(dict['code']==408){
  127. ysFlutterToast(context,'用户名重复');
  128. }else if(dict['code']==804){
  129. return {'code':804};
  130. }else if(dict['code']==801){
  131. return {'code':801};
  132. }
  133. } catch (error) {
  134. if(isLoading==true)Navigator.of(context,rootNavigator: true).pop();
  135. print('网络错误:$error');
  136. ysFlutterToast(context,'网络错误');
  137. }
  138. }
  139. ysRequestHttpEncrypt(BuildContext context,{requestType type,String api,var parameter,bool isLoading,bool isToken}) async {
  140. FocusScope.of(context).unfocus();
  141. if(isLoading==true)showDialog(
  142. context: context,
  143. barrierDismissible: false,
  144. builder: (BuildContext context) {
  145. return LoadingDialog();
  146. }
  147. );
  148. try {
  149. SharedPreferences prefs = await SharedPreferences.getInstance();
  150. String token = prefs.getString('token');
  151. Map<String, dynamic> httpHeaders = {
  152. 'Accept': 'application/json,*/*',
  153. 'Content-Type': 'application/json',
  154. if(isToken==true)'Authentication': token??''
  155. };
  156. String url = base+api;
  157. print('请求网址:$url');
  158. if(isToken==true)print('token:$token');
  159. print('请求参数:$parameter');
  160. var requestStr = await rsaEncryption(json.encode(parameter));
  161. print('加密参数:${{'parmar':requestStr}}');
  162. Response response;
  163. if(type==requestType.put){
  164. response = await Dio().put(url,data: {'parmar':requestStr},options: Options(receiveTimeout: outTime,headers: httpHeaders));
  165. }else if(type==requestType.post){
  166. response = await Dio().post(url,data: {'parmar':requestStr},options: Options(receiveTimeout: outTime,headers: httpHeaders));
  167. }else if(type==requestType.delete){
  168. response = await Dio().delete(url,data: {'parmar':requestStr},options: Options(receiveTimeout: outTime,headers: httpHeaders));
  169. }else{
  170. response = await Dio().get(url,queryParameters: Map<String, dynamic>.from({'parmar':requestStr}),
  171. options: Options(receiveTimeout: outTime,headers: httpHeaders));
  172. }
  173. if(isLoading==true)Navigator.of(context,rootNavigator: true).pop();
  174. print('请求结果:${response.data}');
  175. Map dict = response.data;
  176. if(dict['code']==200){
  177. // ysFlutterToast(context,'操作成功');
  178. if(response.data['data']!=null){
  179. String encrypt = response.data['data'];
  180. String dictStr = await rsaPrivateDecrypt(encrypt);
  181. LogUtil.d('解密后:$dictStr');
  182. return json.decode(dictStr);
  183. }else{
  184. return '';
  185. }
  186. }else if(dict['code']==500){
  187. ysFlutterToast(context,'网络错误');
  188. }else if(dict['code']==404){
  189. ysFlutterToast(context,'接口请求错误');
  190. }else if(dict['code']==401){
  191. ysFlutterToast(context,'登陆已过期');
  192. if(isToken==true)Navigator.of(context).push(
  193. CupertinoPageRoute(
  194. builder: (context){
  195. Future<SharedPreferences> _prefer = SharedPreferences.getInstance();
  196. _prefer.then((value){
  197. value.remove('token');
  198. });
  199. return YSLogin();
  200. }
  201. )
  202. );
  203. }else if(dict['code']==400){
  204. ysFlutterToast(context,'没有检测到手机号');
  205. }else if(dict['code']==403){
  206. ysFlutterToast(context,'没有相关权限');
  207. }else if(dict['code']==405){
  208. ysFlutterToast(context,'没有注册,请注册');
  209. if(isToken==true)Navigator.of(context).push(
  210. CupertinoPageRoute(
  211. builder: (context){
  212. Future<SharedPreferences> _prefer = SharedPreferences.getInstance();
  213. _prefer.then((value){
  214. value.remove('token');
  215. });
  216. return YSLogin();
  217. }
  218. )
  219. ).then((value){
  220. });
  221. }else if(dict['code']==406){
  222. ysFlutterToast(context,'密码错误');
  223. }else if(dict['code']==407){
  224. ysFlutterToast(context,'注册成功,需要新建账号');
  225. String encrypt = response.data['data'];
  226. var dictStr = await rsaPrivateDecrypt(encrypt);
  227. print('解密后:$dictStr');
  228. if(api=='/app/applets/verificationCode'||api=='/app/applets/verificationCodeRegistered'){
  229. Map loginMap = json.decode(dictStr);
  230. SharedPreferences prefer = await SharedPreferences.getInstance();
  231. prefer.setString('token', loginMap['token']);
  232. prefer.setString('name', loginMap['nickname']);
  233. prefer.setString('phone', loginMap['phoneNumber']);
  234. }
  235. Navigator.of(context).push(
  236. CupertinoPageRoute(
  237. builder: (context){
  238. return YSBind();
  239. }
  240. )
  241. );
  242. }else if(dict['code']==408){
  243. ysFlutterToast(context,'用户名重复');
  244. }else if(dict['code']==804){
  245. return {'code':804};
  246. }else if(dict['code']==801){
  247. return {'code':801};
  248. }else{
  249. ysFlutterToast(context,'${dict['msg']}');
  250. }
  251. } catch (error) {
  252. if(isLoading==true)Navigator.of(context,rootNavigator: false).pop();
  253. print('网络错误:$error');
  254. ysFlutterToast(context,'网络错误');
  255. }
  256. }
  257. class LoadingDialog extends Dialog {
  258. @override
  259. Widget build(BuildContext context) {
  260. return Material(
  261. type: MaterialType.transparency,
  262. child: Center(
  263. child: SizedBox(
  264. width: 120.0,
  265. height: 120.0,
  266. child: Container(
  267. decoration: ShapeDecoration(
  268. color: Colors.black87,
  269. shape: RoundedRectangleBorder(
  270. borderRadius: BorderRadius.all(
  271. Radius.circular(8.0),
  272. ),
  273. ),
  274. ),
  275. child: Column(
  276. mainAxisAlignment: MainAxisAlignment.center,
  277. crossAxisAlignment: CrossAxisAlignment.center,
  278. children: <Widget>[
  279. CircularProgressIndicator(valueColor: AlwaysStoppedAnimation<Color>(Colors.white),),
  280. Padding(
  281. padding: EdgeInsets.only(top: 20.0,),
  282. child: Text('正在请求',style: TextStyle(color: Colors.white),),
  283. ),
  284. ],
  285. ),
  286. ),
  287. ),
  288. ),
  289. );
  290. }
  291. }
  292. void ysFlutterToast(BuildContext context,String msg){
  293. Fluttertoast.showToast(
  294. msg: msg,
  295. gravity: ToastGravity.BOTTOM,
  296. textColor: Colors.white,
  297. backgroundColor: Colors.black87,
  298. timeInSecForIosWeb: 2
  299. );
  300. }
  301. //加密
  302. Future<String> rsaEncryption(String data) async {
  303. // 原始json转成字节数组
  304. List<int> sourceBytes = utf8.encode(data);
  305. final parser = RSAKeyParser();
  306. String key = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCit9lK3Y4jrSBAWbbH4OYN4UzMLx7Q+zy0qKzyzMszeEitI8xLP9E4HanriT'
  307. 'X6iKFrdKJLb55DWga79trUozlzeI7XXu67S5VRr+YRLOXHbbTGrJVV63RnolgGd9jkzDd74wjVJIn8gylqlN+WG5/4daMHeEVQ8bGSq03aotzxrwIDAQAB';
  308. final publicKey = parser.parse(key);
  309. final encrypter = Encrypter(RSA(publicKey: publicKey));
  310. // 数据长度
  311. int inputLen = sourceBytes.length;
  312. // 加密最大长度
  313. int maxLen = 117;
  314. // 存放加密后的字节数组
  315. List<int> totalBytes = List();
  316. // 分段加密 步长为117
  317. for (var i = 0; i < inputLen; i += maxLen) {
  318. // 还剩多少字节长度
  319. int endLen = inputLen - i;
  320. List<int> item;
  321. if (endLen > maxLen) {
  322. item = sourceBytes.sublist(i, i + maxLen);
  323. }else{
  324. item = sourceBytes.sublist(i, i + endLen);
  325. }
  326. // 加密后的对象转换成字节数组再存放到容器
  327. totalBytes.addAll(encrypter.encryptBytes(item).bytes);
  328. }
  329. return base64.encode(totalBytes);
  330. }
  331. //解密
  332. Future<String> rsaPrivateDecrypt(String data) async {
  333. Uint8List sourceBytes = base64.decode(data);
  334. final parser = RSAKeyParser();
  335. String key = '-----BEGIN PRIVATE KEY-----\nMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKK32UrdjiOtIEBZtsfg5g3hTMwvHtD7PLSorPLMyzN4SK0jzEs/0TgdqeuJNfqIoWt0oktvnkNaBrv22tSjOXN4jtde7rtLlVGv5hEs5c'
  336. 'dttMaslVXrdGeiWAZ32OTMN3vjCNUkifyDKWqU35Ybn/h1owd4RVDxsZKrTdqi3PGvAgMBAAECgYBQ/OanD40Ojr3NqZmC9JoscGXT/uP8qf91/7pNAsdkr8qkenvVPEc7AfCv7dQzBUwqepvIph6EcUuGxH/4c+FEn5X'
  337. 'QS/dNhdDHZtZ6E+DQzXHvrz7wVfDSecyYEKHRKw0WZmoCy6bfeDEf5zShmMJtmtakGq/+ES6U0DtLN4SWkQJBANCadJQm2ZSnHc0lCHkdkcSXsS+nhtRZ5EyKg3Xr81BClQXPtswYhPcNq9QSC/CBiaVNeC0TOOZEfaVEH'
  338. 'wc+bAkCQQDHsHPzMbnyZtPdv3MG1xukTgIuFsmg/LPM+hkuSNDUNR63PBNeVv59DwnFd+bgQTyZWQ97wm6Nx4ZQSfN3BE33AkB4RbWVfdjRZpE+KG38NtpGuRdF3JdWdAW3Q92L7eC5k8oMMbi5cCGpt84sVcNgha9xCXuSs'
  339. 'ZSK3056LQ6exJTRAkBSPmqDD0f2fkNkYSWO+6l20mozcU857tpe4eLdHUBlJjuwXB3eDRZji34KxodgdX3v6q5l2n6OBk9bYhnUOwGhAkB7+gFxeARigkNJl8CCVtpJ9oAped5NT8ebDS8KCAU2qu6Y9mz04bk2NbHAf6TmIm'
  340. 'oLCa/ORgP0Tn4HefEOfBKl';//根据存放位置更改
  341. final privateKey = parser.parse(key);
  342. final encrypter = Encrypter(RSA(privateKey: privateKey));
  343. // 数据长度
  344. int inputLen = sourceBytes.length;
  345. // 解密最大长度
  346. int maxLen = 128;
  347. // 存放加密后的字节数组
  348. List<int> totalBytes = List();
  349. // 分段解密 步长为128
  350. for (var i = 0; i < inputLen; i += maxLen) {
  351. // 还剩多少字节长度
  352. int endLen = inputLen - i;
  353. Uint8List item;
  354. if (endLen > maxLen) {
  355. item = sourceBytes.sublist(i, i + maxLen);
  356. }else{
  357. item = sourceBytes.sublist(i, i + endLen);
  358. }
  359. // 解密后的对象转换成字节数组再存放到容器
  360. totalBytes.addAll(encrypter.decryptBytes(Encrypted(item)));
  361. }
  362. return utf8.decode(totalBytes);
  363. }
  364. ysFutureWidge({widgetCallback data,var net}){
  365. return FutureBuilder(
  366. future: net,
  367. builder: (context, snapshot) {
  368. var widget;
  369. if (snapshot.connectionState == ConnectionState.done) {
  370. if (snapshot.hasError) {
  371. widget = Icon(
  372. Icons.error,
  373. color: Colors.red,
  374. size: 20,
  375. );
  376. }else if(snapshot.data==null||snapshot.data.isEmpty||snapshot.data==[]){
  377. widget = Container();
  378. } else {
  379. widget = data(snapshot);
  380. }
  381. } else {
  382. widget = Icon(
  383. Icons.image,
  384. color: Colors.grey.withOpacity(0.5),
  385. size: 20,
  386. );
  387. }
  388. return Center(
  389. child: Container(
  390. child: widget,
  391. ),
  392. );
  393. },
  394. );
  395. }
  396. ysImageLoad({String imageUrl,BoxFit fit,double height,double width,double aspectRatio}) {
  397. return aspectRatio==null?Image(
  398. image: NetworkImage(imageUrl),
  399. fit: fit,
  400. //placeholder: placeholder,
  401. height: height,
  402. width: width,
  403. ):AspectRatio(
  404. child: Container(
  405. decoration: BoxDecoration(
  406. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)),
  407. ),
  408. child: ClipRRect(
  409. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)),
  410. child: Image(
  411. image: NetworkImage(imageUrl),
  412. fit: fit,
  413. //placeholder: placeholder,
  414. ),
  415. ),
  416. ),
  417. aspectRatio: aspectRatio
  418. );
  419. // Future<String> _future = Future.value(imageUrl);
  420. // return ysFutureWidge(
  421. // net: _future,
  422. // data: (value){
  423. // return aspectRatio==null?Image(
  424. // image: NetworkImage('${value.data}'),
  425. // fit: fit,
  426. // //placeholder: placeholder,
  427. // height: height,
  428. // width: width,
  429. // ):AspectRatio(
  430. // child: Container(
  431. // decoration: BoxDecoration(
  432. // borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)),
  433. // ),
  434. // child: ClipRRect(
  435. // borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)),
  436. // child: Image(
  437. // image: NetworkImage('${value.data}'),
  438. // fit: fit,
  439. // //placeholder: placeholder,
  440. // ),
  441. // ),
  442. // ),
  443. // aspectRatio: aspectRatio
  444. // );
  445. // }
  446. // );
  447. }
  448. ysIsolateImage({String imageUrl,BoxFit fit,double height,double width,double aspectRatio}) async{
  449. return await isolateCountEven(ImageModel(imageUrl, fit, height, width, aspectRatio));
  450. }
  451. isolateCountEven(ImageModel model) async {
  452. final response = ReceivePort();
  453. await Isolate.spawn(countEvent2, response.sendPort);
  454. final sendPort = await response.first;
  455. final answer = ReceivePort();
  456. sendPort.send([answer.sendPort, model]);
  457. return answer.first;
  458. }
  459. countEvent2(SendPort port) {
  460. final rPort = ReceivePort();
  461. port.send(rPort.sendPort);
  462. rPort.listen((message) {
  463. final send = message[0] as SendPort;
  464. final model = message[1];
  465. send.send(countEven(model));
  466. });
  467. }
  468. countEven(ImageModel model){
  469. Future<String> _future = Future.value(model.imageUrl);
  470. return ysFutureWidge(
  471. net: _future,
  472. data: (value){
  473. return model.aspectRatio==null?ysImageLoad(
  474. imageUrl: '${value.data}',
  475. fit: model.fit,
  476. height: model.height,
  477. width: model.width,
  478. ):AspectRatio(
  479. child: Container(
  480. decoration: BoxDecoration(
  481. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)),
  482. ),
  483. child: ClipRRect(
  484. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)),
  485. child: ysImageLoad(
  486. imageUrl: '${value.data}',
  487. fit: model.fit,
  488. ),
  489. ),
  490. ),
  491. aspectRatio: model.aspectRatio
  492. );
  493. }
  494. );
  495. }
  496. class ImageModel{
  497. final String imageUrl;
  498. final BoxFit fit;
  499. final double height;
  500. final double width;
  501. final double aspectRatio;
  502. ImageModel(this.imageUrl, this.fit, this.height, this.width, this.aspectRatio);
  503. }