import 'dart:convert'; import 'dart:isolate'; import 'dart:typed_data'; import 'package:dio/dio.dart'; import 'package:encrypt/encrypt.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:ysairplane2/code/YSBind.dart'; import 'package:ysairplane2/code/YSLogin.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'YSTools.dart'; //http://aviation.ytby0402.top //http://192.168.1.3:8082 //https://api.s-fly.cn String base = 'https://api.s-fly.cn'; int outTime = 20000; enum requestType{ put, delete, get, post } typedef widgetCallback = Widget Function(dynamic value); ysRequestHttp(BuildContext context,{requestType type,String api,var parameter,bool isLoading,VoidCallback refresh,bool isToken,bool unfocus = true}) async { if(unfocus)FocusScope.of(context).unfocus(); if(isLoading==true)showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return LoadingDialog(); } ); try { SharedPreferences prefs = await SharedPreferences.getInstance(); String token = prefs.getString('token'); Map httpHeaders = { 'Accept': 'application/json,*/*', 'Content-Type': 'application/json', if(isToken==true)'Authentication': token??'' }; String url = base+api; print('请求网址:$url'); if(isToken==true)print('token:$token'); print('请求参数:$parameter'); Response response; if(type==requestType.put){ response = await Dio().put(url,data: parameter,options: Options(receiveTimeout: outTime,headers: httpHeaders)); }else if(type==requestType.post){ response = await Dio().post(url,data: parameter,options: Options(receiveTimeout: outTime,headers: httpHeaders)); }else if(type==requestType.delete){ response = await Dio().delete(url,data: parameter,options: Options(receiveTimeout: outTime,headers: httpHeaders)); }else{ response = await Dio().get(url,queryParameters: Map.from(parameter),options: Options(receiveTimeout: outTime,headers: httpHeaders)); } LogUtil.d('请求结果:$url ${response.data}'); Map dict = response.data; if(isLoading==true)Navigator.of(context,rootNavigator: true).pop(); if(dict['code']==200){ //ysFlutterToast(context,'操作成功'); return dict; }else if(dict['code']==500){ ysFlutterToast(context,'网络错误'); }else if(dict['code']==404){ ysFlutterToast(context,'接口请求错误'); }else if(dict['code']==402){ ysFlutterToast(context,'${dict['msg']}'); }else if(dict['code']==401){ ysFlutterToast(context,'登陆已过期'); Navigator.of(context,rootNavigator: true).push( CupertinoPageRoute( fullscreenDialog: true, builder: (context){ Future _prefer = SharedPreferences.getInstance(); _prefer.then((value){ value.remove('token'); }); return YSLogin(); } ) ).then((value){ if(refresh!=null&&value!=null){ refresh(); } }); }else if(dict['code']==400){ ysFlutterToast(context,'没有检测到手机号'); }else if(dict['code']==403){ ysFlutterToast(context,'没有相关权限'); }else if(dict['code']==405){ ysFlutterToast(context,'没有注册,请注册'); if(isToken==true)Navigator.of(context).push( CupertinoPageRoute( fullscreenDialog: true, builder: (context){ Future _prefer = SharedPreferences.getInstance(); _prefer.then((value){ value.remove('token'); }); return YSLogin(); } ) ).then((value){ if(refresh!=null&&value!=null){ refresh(); } }); }else if(dict['code']==406){ ysFlutterToast(context,'密码错误'); }else if(dict['code']==407){ ysFlutterToast(context,'注册成功,需要新建账号'); if(api=='/app/applets/verificationCode'){ SharedPreferences prefer = await SharedPreferences.getInstance(); prefer.setString('token', dict['token']); prefer.setString('name', dict['nickname']); prefer.setString('phone', dict['phoneNumber']); } Navigator.of(context).push( CupertinoPageRoute( builder: (context){ return YSBind(); } ) ); }else if(dict['code']==408){ ysFlutterToast(context,'用户名重复'); }else if(dict['code']==804){ return {'code':804}; }else if(dict['code']==801){ return {'code':801}; } } catch (error) { if(isLoading==true)Navigator.of(context,rootNavigator: true).pop(); print('网络错误:$error'); ysFlutterToast(context,'网络错误'); } } ysRequestHttpEncrypt(BuildContext context,{requestType type,String api,var parameter,bool isLoading,bool isToken}) async { FocusScope.of(context).unfocus(); if(isLoading==true)showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return LoadingDialog(); } ); try { SharedPreferences prefs = await SharedPreferences.getInstance(); String token = prefs.getString('token'); Map httpHeaders = { 'Accept': 'application/json,*/*', 'Content-Type': 'application/json', if(isToken==true)'Authentication': token??'' }; String url = base+api; print('请求网址:$url'); if(isToken==true)print('token:$token'); print('请求参数:$parameter'); var requestStr = await rsaEncryption(json.encode(parameter)); print('加密参数:${{'parmar':requestStr}}'); Response response; if(type==requestType.put){ response = await Dio().put(url,data: {'parmar':requestStr},options: Options(receiveTimeout: outTime,headers: httpHeaders)); }else if(type==requestType.post){ response = await Dio().post(url,data: {'parmar':requestStr},options: Options(receiveTimeout: outTime,headers: httpHeaders)); }else if(type==requestType.delete){ response = await Dio().delete(url,data: {'parmar':requestStr},options: Options(receiveTimeout: outTime,headers: httpHeaders)); }else{ response = await Dio().get(url,queryParameters: Map.from({'parmar':requestStr}), options: Options(receiveTimeout: outTime,headers: httpHeaders)); } if(isLoading==true)Navigator.of(context,rootNavigator: true).pop(); print('请求结果:${response.data}'); Map dict = response.data; if(dict['code']==200){ // ysFlutterToast(context,'操作成功'); if(response.data['data']!=null){ String encrypt = response.data['data']; String dictStr = await rsaPrivateDecrypt(encrypt); LogUtil.d('解密后:$dictStr'); return json.decode(dictStr); }else{ return ''; } }else if(dict['code']==500){ ysFlutterToast(context,'网络错误'); }else if(dict['code']==404){ ysFlutterToast(context,'接口请求错误'); }else if(dict['code']==401){ ysFlutterToast(context,'登陆已过期'); if(isToken==true)Navigator.of(context).push( CupertinoPageRoute( builder: (context){ Future _prefer = SharedPreferences.getInstance(); _prefer.then((value){ value.remove('token'); }); return YSLogin(); } ) ); }else if(dict['code']==400){ ysFlutterToast(context,'没有检测到手机号'); }else if(dict['code']==403){ ysFlutterToast(context,'没有相关权限'); }else if(dict['code']==405){ ysFlutterToast(context,'没有注册,请注册'); if(isToken==true)Navigator.of(context).push( CupertinoPageRoute( builder: (context){ Future _prefer = SharedPreferences.getInstance(); _prefer.then((value){ value.remove('token'); }); return YSLogin(); } ) ).then((value){ }); }else if(dict['code']==406){ ysFlutterToast(context,'密码错误'); }else if(dict['code']==407){ ysFlutterToast(context,'注册成功,需要新建账号'); String encrypt = response.data['data']; var dictStr = await rsaPrivateDecrypt(encrypt); print('解密后:$dictStr'); if(api=='/app/applets/verificationCode'||api=='/app/applets/verificationCodeRegistered'){ Map loginMap = json.decode(dictStr); SharedPreferences prefer = await SharedPreferences.getInstance(); prefer.setString('token', loginMap['token']); prefer.setString('name', loginMap['nickname']); prefer.setString('phone', loginMap['phoneNumber']); } Navigator.of(context).push( CupertinoPageRoute( builder: (context){ return YSBind(); } ) ); }else if(dict['code']==408){ ysFlutterToast(context,'用户名重复'); }else if(dict['code']==804){ return {'code':804}; }else if(dict['code']==801){ return {'code':801}; }else{ ysFlutterToast(context,'${dict['msg']}'); } } catch (error) { if(isLoading==true)Navigator.of(context,rootNavigator: false).pop(); print('网络错误:$error'); ysFlutterToast(context,'网络错误'); } } class LoadingDialog extends Dialog { @override Widget build(BuildContext context) { return Material( type: MaterialType.transparency, child: Center( child: SizedBox( width: 120.0, height: 120.0, child: Container( decoration: ShapeDecoration( color: Colors.black87, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(8.0), ), ), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.white),), Padding( padding: EdgeInsets.only(top: 20.0,), child: Text('正在请求',style: TextStyle(color: Colors.white),), ), ], ), ), ), ), ); } } void ysFlutterToast(BuildContext context,String msg){ Fluttertoast.showToast( msg: msg, gravity: ToastGravity.BOTTOM, textColor: Colors.white, backgroundColor: Colors.black87, timeInSecForIosWeb: 2 ); } //加密 Future rsaEncryption(String data) async { // 原始json转成字节数组 List sourceBytes = utf8.encode(data); final parser = RSAKeyParser(); String key = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCit9lK3Y4jrSBAWbbH4OYN4UzMLx7Q+zy0qKzyzMszeEitI8xLP9E4HanriT' 'X6iKFrdKJLb55DWga79trUozlzeI7XXu67S5VRr+YRLOXHbbTGrJVV63RnolgGd9jkzDd74wjVJIn8gylqlN+WG5/4daMHeEVQ8bGSq03aotzxrwIDAQAB'; final publicKey = parser.parse(key); final encrypter = Encrypter(RSA(publicKey: publicKey)); // 数据长度 int inputLen = sourceBytes.length; // 加密最大长度 int maxLen = 117; // 存放加密后的字节数组 List totalBytes = List(); // 分段加密 步长为117 for (var i = 0; i < inputLen; i += maxLen) { // 还剩多少字节长度 int endLen = inputLen - i; List item; if (endLen > maxLen) { item = sourceBytes.sublist(i, i + maxLen); }else{ item = sourceBytes.sublist(i, i + endLen); } // 加密后的对象转换成字节数组再存放到容器 totalBytes.addAll(encrypter.encryptBytes(item).bytes); } return base64.encode(totalBytes); } //解密 Future rsaPrivateDecrypt(String data) async { Uint8List sourceBytes = base64.decode(data); final parser = RSAKeyParser(); String key = '-----BEGIN PRIVATE KEY-----\nMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKK32UrdjiOtIEBZtsfg5g3hTMwvHtD7PLSorPLMyzN4SK0jzEs/0TgdqeuJNfqIoWt0oktvnkNaBrv22tSjOXN4jtde7rtLlVGv5hEs5c' 'dttMaslVXrdGeiWAZ32OTMN3vjCNUkifyDKWqU35Ybn/h1owd4RVDxsZKrTdqi3PGvAgMBAAECgYBQ/OanD40Ojr3NqZmC9JoscGXT/uP8qf91/7pNAsdkr8qkenvVPEc7AfCv7dQzBUwqepvIph6EcUuGxH/4c+FEn5X' 'QS/dNhdDHZtZ6E+DQzXHvrz7wVfDSecyYEKHRKw0WZmoCy6bfeDEf5zShmMJtmtakGq/+ES6U0DtLN4SWkQJBANCadJQm2ZSnHc0lCHkdkcSXsS+nhtRZ5EyKg3Xr81BClQXPtswYhPcNq9QSC/CBiaVNeC0TOOZEfaVEH' 'wc+bAkCQQDHsHPzMbnyZtPdv3MG1xukTgIuFsmg/LPM+hkuSNDUNR63PBNeVv59DwnFd+bgQTyZWQ97wm6Nx4ZQSfN3BE33AkB4RbWVfdjRZpE+KG38NtpGuRdF3JdWdAW3Q92L7eC5k8oMMbi5cCGpt84sVcNgha9xCXuSs' 'ZSK3056LQ6exJTRAkBSPmqDD0f2fkNkYSWO+6l20mozcU857tpe4eLdHUBlJjuwXB3eDRZji34KxodgdX3v6q5l2n6OBk9bYhnUOwGhAkB7+gFxeARigkNJl8CCVtpJ9oAped5NT8ebDS8KCAU2qu6Y9mz04bk2NbHAf6TmIm' 'oLCa/ORgP0Tn4HefEOfBKl';//根据存放位置更改 final privateKey = parser.parse(key); final encrypter = Encrypter(RSA(privateKey: privateKey)); // 数据长度 int inputLen = sourceBytes.length; // 解密最大长度 int maxLen = 128; // 存放加密后的字节数组 List totalBytes = List(); // 分段解密 步长为128 for (var i = 0; i < inputLen; i += maxLen) { // 还剩多少字节长度 int endLen = inputLen - i; Uint8List item; if (endLen > maxLen) { item = sourceBytes.sublist(i, i + maxLen); }else{ item = sourceBytes.sublist(i, i + endLen); } // 解密后的对象转换成字节数组再存放到容器 totalBytes.addAll(encrypter.decryptBytes(Encrypted(item))); } return utf8.decode(totalBytes); } ysFutureWidge({widgetCallback data,var net}){ return FutureBuilder( future: net, builder: (context, snapshot) { var widget; if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasError) { widget = Icon( Icons.error, color: Colors.red, size: 20, ); }else if(snapshot.data==null||snapshot.data.isEmpty||snapshot.data==[]){ widget = Container(); } else { widget = data(snapshot); } } else { widget = Icon( Icons.image, color: Colors.grey.withOpacity(0.5), size: 20, ); } return Center( child: Container( child: widget, ), ); }, ); } ysImageLoad({String imageUrl,BoxFit fit,double height,double width,double aspectRatio}) { return aspectRatio==null?Image( image: NetworkImage(imageUrl), fit: fit, //placeholder: placeholder, height: height, width: width, ):AspectRatio( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)), ), child: ClipRRect( borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)), child: Image( image: NetworkImage(imageUrl), fit: fit, //placeholder: placeholder, ), ), ), aspectRatio: aspectRatio ); // Future _future = Future.value(imageUrl); // return ysFutureWidge( // net: _future, // data: (value){ // return aspectRatio==null?Image( // image: NetworkImage('${value.data}'), // fit: fit, // //placeholder: placeholder, // height: height, // width: width, // ):AspectRatio( // child: Container( // decoration: BoxDecoration( // borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)), // ), // child: ClipRRect( // borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)), // child: Image( // image: NetworkImage('${value.data}'), // fit: fit, // //placeholder: placeholder, // ), // ), // ), // aspectRatio: aspectRatio // ); // } // ); } ysIsolateImage({String imageUrl,BoxFit fit,double height,double width,double aspectRatio}) async{ return await isolateCountEven(ImageModel(imageUrl, fit, height, width, aspectRatio)); } isolateCountEven(ImageModel model) async { final response = ReceivePort(); await Isolate.spawn(countEvent2, response.sendPort); final sendPort = await response.first; final answer = ReceivePort(); sendPort.send([answer.sendPort, model]); return answer.first; } countEvent2(SendPort port) { final rPort = ReceivePort(); port.send(rPort.sendPort); rPort.listen((message) { final send = message[0] as SendPort; final model = message[1]; send.send(countEven(model)); }); } countEven(ImageModel model){ Future _future = Future.value(model.imageUrl); return ysFutureWidge( net: _future, data: (value){ return model.aspectRatio==null?ysImageLoad( imageUrl: '${value.data}', fit: model.fit, height: model.height, width: model.width, ):AspectRatio( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)), ), child: ClipRRect( borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)), child: ysImageLoad( imageUrl: '${value.data}', fit: model.fit, ), ), ), aspectRatio: model.aspectRatio ); } ); } class ImageModel{ final String imageUrl; final BoxFit fit; final double height; final double width; final double aspectRatio; ImageModel(this.imageUrl, this.fit, this.height, this.width, this.aspectRatio); }