diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b2c169e..2418c89 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -9,6 +9,8 @@ PODS: - Toast - permission_handler_apple (9.0.4): - Flutter + - shared_preferences_ios (0.0.1): + - Flutter - Toast (4.0.0) DEPENDENCIES: @@ -16,6 +18,7 @@ DEPENDENCIES: - Flutter (from `Flutter`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) SPEC REPOS: trunk: @@ -31,6 +34,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/fluttertoast/ios" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" + shared_preferences_ios: + :path: ".symlinks/plugins/shared_preferences_ios/ios" SPEC CHECKSUMS: agora_rtc_engine: ffc530eff766a38272568ebaead9341d73f58856 @@ -38,6 +43,7 @@ SPEC CHECKSUMS: Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037 permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce + shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 PODFILE CHECKSUM: bd5ecd90bb4d3dada07dd6c6725bb70ab42e9619 diff --git a/lib/utils/auth.dart b/lib/utils/auth.dart new file mode 100644 index 0000000..dcb3422 --- /dev/null +++ b/lib/utils/auth.dart @@ -0,0 +1,59 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +class Storage { + // 储存数据 + static Future set(String key, value) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + if (value is String) { + return prefs.setString(key, value); + } else if (value is int) { + return prefs.setInt(key, value); + } else if (value is double) { + return prefs.setDouble(key, value); + } else if (value is bool) { + return prefs.setBool(key, value); + } else if (value is List) { + return prefs.setStringList(key, value.cast()); + } + } + + // 取出 + static Future get(key) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.get(key); + } + + // 删除 + static Future remove(key) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.remove(key); + } +} + +// const TokenKey = 'token'; + +// getToken() async { +// SharedPreferences prefs = await SharedPreferences.getInstance(); +// return prefs.getString(TokenKey); +// } + +// setToken(token) async { +// SharedPreferences prefs = await SharedPreferences.getInstance(); +// prefs.setString(TokenKey, token.toString()); +// // if (token is String) { +// // prefs.setString(TokenKey, token); +// // } else if (token is num) { +// // prefs.setInt(TokenKey, token as int); +// // } else if (token is double) { +// // prefs.setDouble(TokenKey, token); +// // } else if (token is bool) { +// // prefs.setBool(TokenKey, token); +// // } else if (token is List) { +// // prefs.setStringList(TokenKey, token.cast()); +// // } +// } + +// removeToken() async { +// SharedPreferences prefs = await SharedPreferences.getInstance(); +// prefs.remove(TokenKey); +// } diff --git a/lib/utils/dioHttp.dart b/lib/utils/dioHttp.dart index e515515..812bd37 100644 --- a/lib/utils/dioHttp.dart +++ b/lib/utils/dioHttp.dart @@ -1,7 +1,7 @@ -import 'package:dio/dio.dart'; +import 'dart:convert'; -var token = - 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJ0ZXN0MSJ9.GV21nLXeLwZI7lB5Mp2lk9kEBJl4kJOPtw7YXwXINrE'; +import 'package:dio/dio.dart'; +import '../utils/auth.dart'; // Dio dio = new Dio(); // dio.options = BaseOptions( @@ -25,10 +25,27 @@ class dioHttp { baseUrl: 'http://101.35.117.69:9093/', connectTimeout: 5000, receiveTimeout: 5000, - headers: {"Authorization": 'Bearer ${token}'}, + contentType: "application/json", + // headers: {"Authorization": 'Bearer ${getToken()}'}, ); - - Dio dio = new Dio(options); + Dio dio = new Dio(options) + ..interceptors.add( + InterceptorsWrapper( + onRequest: (options, handler) { + // print('请求REQUEST[${options.method}] => PATH: ${options.path}'); + return handler.next(options); + }, + onResponse: (response, handler) { + // var resMap = jsonDecode(response.toString()); + // print('响应RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}'); + return handler.next(response); + }, + onError: (err, handler) { + // print('ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}'); + return handler.next(err); + }, + ), + ); } // Dio dio = new Dio( diff --git a/lib/utils/http_util.dart b/lib/utils/http_util.dart new file mode 100644 index 0000000..9a7372f --- /dev/null +++ b/lib/utils/http_util.dart @@ -0,0 +1,98 @@ +import 'package:dio/dio.dart' as dioplugn; +import 'package:pretty_dio_logger/pretty_dio_logger.dart'; +import './response_model.dart'; +import './auth.dart'; + +class MyHttpUtil { + late dioplugn.Dio dio; + late dioplugn.BaseOptions options; + + MyHttpUtil({Map? header}) { + Map defaultHeader = { + "Accept": "application/json", + "Content-Type": "application/json;charset=UTF-8", + // "Authorization": getToken() ? 'Bearer $getToken()' : null + }; + options = dioplugn.BaseOptions( + connectTimeout: 15000, + receiveTimeout: 3000, + baseUrl: 'http://101.35.117.69:9093', + headers: header ?? defaultHeader, + ); + dio = dioplugn.Dio(options); + dio.interceptors.add(PrettyDioLogger( + requestHeader: true, + requestBody: true, + responseBody: true, + responseHeader: false, + error: true, + compact: true, + maxWidth: 90)); + } + + Future get(url, + {data, cancelToken, bool analyze = true}) async { + try { + // dio.options.headers['Authorization'] = 'Bearer $getToken()'; + var token = await Storage.get('token'); + if (token != null) { + dio.options.headers['Authorization'] = 'Bearer ${token}'; + } + dioplugn.Response response = + await dio.get(url, queryParameters: data, cancelToken: cancelToken); + + int code = -1; + String msg = "数据请求失败"; + dynamic resData; + + ///如果返回的data 是String 类型失败处理 + if (response.statusCode == 200 && + response.data.runtimeType.toString() != "String") { + return ResponseModel.fromJson(response.data); + } else { + return ResponseModel(code: code, message: msg, data: resData); + } + } on dioplugn.DioError catch (e) { + // ToastUtil.closeLoading(); + return ResponseModel(code: -1, message: "网络加载失败", data: {}); + // throw e.error; + } + } + + Future post(url, + {data, + options, + cancelToken, + Function(int, int)? onSendProgress, + bool analyze = true}) async { + try { + // dio.options.headers['Authorization'] = 'Bearer $getToken()'; + var token = await Storage.get('token'); + if (token != null) { + dio.options.headers['Authorization'] = 'Bearer ${token}'; + } + dioplugn.Response response = await dio.post( + url, + data: data, + cancelToken: cancelToken, + onSendProgress: onSendProgress, + ); + int code = -1; + String msg = "msg"; + dynamic resData; + + ///如果返回的data 是String 类型失败处理 + if (response.statusCode == 200 && + response.data.runtimeType.toString() != "String") { + return ResponseModel.fromJson(response.data); + } else { + return ResponseModel(code: code, message: msg, data: resData); + } + } on dioplugn.DioError catch (e) { + // printLog(e); + // ToastUtil.closeLoading(); + return ResponseModel(code: -1, message: "网络加载失败", data: {}); + // throw e.error; + } + } +} diff --git a/lib/utils/response_model.dart b/lib/utils/response_model.dart new file mode 100644 index 0000000..c82a6cb --- /dev/null +++ b/lib/utils/response_model.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +import 'dart:developer'; + +class FFConvert { + FFConvert._(); + // ignore: prefer_function_declarations_over_variables + static T? Function(dynamic value) convert = (dynamic value) { + if (value == null) { + return null; + } + return json.decode(value.toString()) as T?; + }; +} + +T? asT(dynamic value, [T? defaultValue]) { + if (value is T) { + return value; + } + try { + if (value != null) { + final String valueS = value.toString(); + if ('' is T) { + return valueS as T; + } else if (0 is T) { + return int.parse(valueS) as T; + } else if (0.0 is T) { + return double.parse(valueS) as T; + } else if (false is T) { + if (valueS == '0' || valueS == '1') { + return (valueS == '1') as T; + } + return (valueS == 'true') as T; + } else { + return FFConvert.convert(value); + } + } + } catch (e, stackTrace) { + log('asT<$T>', error: e, stackTrace: stackTrace); + return defaultValue; + } + + return defaultValue; +} + +class ResponseModel { + ResponseModel({ + this.code, + this.message, + this.data, + }); + + factory ResponseModel.fromJson(Map jsonRes) => ResponseModel( + code: asT(jsonRes['code']), + message: asT(jsonRes['message']), + data: asT(jsonRes['data']), + ); + + int? code; + String? message; + dynamic data; + + @override + String toString() { + return jsonEncode(this); + } + + Map toJson() => { + 'code': code, + 'message': message, + 'data': data, + }; +} \ No newline at end of file diff --git a/lib/utils/showToast.dart b/lib/utils/showToast.dart index d41a492..2edd8ad 100644 --- a/lib/utils/showToast.dart +++ b/lib/utils/showToast.dart @@ -3,6 +3,7 @@ import 'package:fluttertoast/fluttertoast.dart'; // 普通气泡弹框 // 使用:showToast("xxxxxxx"); +// 取消:Fluttertoast.cancel() void showToast( String text, { gravity: ToastGravity.CENTER, diff --git a/lib/views/createRoom/CreateRoom.dart b/lib/views/createRoom/CreateRoom.dart index d1ae988..8e89603 100644 --- a/lib/views/createRoom/CreateRoom.dart +++ b/lib/views/createRoom/CreateRoom.dart @@ -1,5 +1,11 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:will_play/utils/auth.dart'; +import 'package:will_play/views/palRoom/PalRoom.dart'; + +import '../../utils/http_util.dart'; class CreateRoomPage extends StatefulWidget { CreateRoomPage({Key? key}) : super(key: key); @@ -51,6 +57,84 @@ class _CreateRoomPageState extends State { ), ]; + var Timer; + + void _create(roomName) { + MyHttpUtil().post( + "/chat/api/room/create", + data: {"name": roomName}, + ).then((res) { + var roomId = res.data; + // print(roomId); + + Timer = Timer.periodic(Duration(seconds: 1), (timer) async { + _lodingCreate(roomId); + }); + + // Timer = Timer.periodic(Duration(seconds: 1), (timer) async { + // var resp = await MyHttpUtil().get( + // "/chat/api/room/create/$roomId", + // ); + // String userName = await Storage.get('userName'); + // print(userName); + // print(resp.data); + // if (resp.data == true) { + // // onJoin(userName, roomName, ClientRole.Broadcaster); // 参数1:用户名; 参数2:频道名; 参数3:身份; + // Timer?.cancel(); + // Timer = null; + // } + // }); + }); + } + + void _lodingCreate(roomId) async { + var resp = await MyHttpUtil().get( + "/chat/api/room/create/$roomId", + ); + String userName = await Storage.get('userName'); + print(userName); + print(resp.data); + if (resp.data == true) { + // onJoin(userName, roomName, ClientRole.Broadcaster); // 参数1:用户名; 参数2:频道名; 参数3:身份; + Timer?.cancel(); + Timer = null; + } + } + + @override + void dispose() { + super.dispose(); + Timer?.cancel(); + Timer = null; + } + + // 页面跳转方法:参数1:用户名; 参数2:频道名; 参数3:身份; + Future onJoin(userName, channelName, role) async { + await _handleCameraAndMic(Permission.camera); + await _handleCameraAndMic(Permission.microphone); + + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PalRoomPage( + userName: userName, + channelName: channelName, + role: role, + ), + ), + ); + } + + // 判断是否开启权限方法 + Future _handleCameraAndMic(Permission permission) async { + PermissionStatus status = await permission.request(); + print('权限状态$status'); + if (!status.isGranted) { + openAppSettings(); + } + } + + @override Widget _buttonstyle(theme, parameter) { return Container( child: Stack( @@ -290,6 +374,7 @@ class _CreateRoomPageState extends State { ), onPressed: () { if (_formKey.currentState!.validate()) { + _create(_roomName.text); print('表单验证通过!'); } }, diff --git a/lib/views/login/Login.dart b/lib/views/login/Login.dart index 913e0ed..ff27c1d 100644 --- a/lib/views/login/Login.dart +++ b/lib/views/login/Login.dart @@ -1,6 +1,12 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; +import 'package:will_play/utils/auth.dart'; + +// import '../../utils/dioHttp.dart'; +import '../../utils/http_util.dart'; +import '../../utils/auth.dart'; import '../../utils/showToast.dart'; -import '../../utils/dioHttp.dart'; class LoginPage extends StatefulWidget { LoginPage({Key? key}) : super(key: key); @@ -15,6 +21,26 @@ class _LoginPageState extends State { final _password = TextEditingController(); bool checked = true; + _login() async { + var removeToken = await Storage.remove('token'); + var removeID = await Storage.remove('id'); + var removeUserName = await Storage.remove('userName'); + + var res = await MyHttpUtil().post( + "http://101.35.117.69:9093/chat/api/auth/login", + data: { + "username": _userName.text, + "password": _password.text, + }, + ); + + var setToken = await Storage.set('token', '${res.data["token"]}'); + var setId = await Storage.set('id', '${res.data["id"]}'); + var setUserName = await Storage.set('userName', '${res.data["userName"]}'); + + Navigator.of(context).pushReplacementNamed('/'); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -138,18 +164,32 @@ class _LoginPageState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30)), ), - onPressed: () { + onPressed: () async { if (_formKey.currentState!.validate()) { print('表单验证通过!'); if (!checked) { print('请勾选服务协议和隐私政策'); } else { - dioHttp().dio.post('chat/api/auth/login', data: { - "username": _userName.text, - "password": _password.text, - }).then((res) { - print(res); - }); + _login(); + + // var token; + // getToken().then((value) { + // print('~~~~~~~~~~~~~~$value'); + // token = value; + // }); + + // print('~~~~~~~~~~~~~~$getToken()'); + // print('~~~~~~~~~~~~~~$token'); + + // var res = await dioHttp() + // .dio + // .post('chat/api/auth/login', data: { + // "username": _userName.text, + // "password": _password.text, + // }); + + // var resMap = jsonDecode(res.toString()); + // print(resMap['data']); // print('请求登录接口业务逻辑'); diff --git a/lib/views/party/Party.dart b/lib/views/party/Party.dart index a016e68..f512581 100644 --- a/lib/views/party/Party.dart +++ b/lib/views/party/Party.dart @@ -5,6 +5,8 @@ import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:will_play/views/palRoom/PalRoom.dart'; +import '../../utils/http_util.dart'; + class PartyPage extends StatefulWidget { PartyPage({Key? key}) : super(key: key); @@ -180,7 +182,7 @@ class Lists extends StatefulWidget { } class _ListsState extends State { - final List _list = [ + List _list = [ { "photo": "images/party/photo1.png", "name": "小明", @@ -219,6 +221,20 @@ class _ListsState extends State { }, ]; + @override + void initState() { + super.initState(); + _getList(); + } + + _getList() async { + var res = await MyHttpUtil().get( + "http://101.35.117.69:9093/chat/api/room/page", + ); + print(res); + // _list = res.data['content']; + } + // 判断是否开启权限方法 Future _handleCameraAndMic(Permission permission) async { PermissionStatus status = await permission.request(); @@ -229,7 +245,7 @@ class _ListsState extends State { } // 页面跳转方法 - Future onJoin(name, role) async { + Future onJoin(userName, role) async { await _handleCameraAndMic(Permission.camera); await _handleCameraAndMic(Permission.microphone); @@ -237,7 +253,7 @@ class _ListsState extends State { context, MaterialPageRoute( builder: (context) => PalRoomPage( - userName: name, + userName: userName, channelName: 'call', role: role, ), diff --git a/pubspec.lock b/pubspec.lock index fe70e9d..a221f26 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -71,6 +71,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.1" + file: + dependency: transitive + description: + name: file + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.1.2" flutter: dependency: "direct main" description: flutter @@ -156,6 +170,27 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.8.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.7" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" permission_handler: dependency: "direct main" description: @@ -191,6 +226,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.1.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.0" plugin_platform_interface: dependency: transitive description: @@ -198,6 +240,76 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" + pretty_dio_logger: + dependency: "direct main" + description: + name: pretty_dio_logger + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0-beta-1" + process: + dependency: transitive + description: + name: process + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.2.4" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.15" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.12" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.4" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.4" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" sky_engine: dependency: transitive description: flutter @@ -266,6 +378,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.7.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.0+1" sdks: dart: ">=2.17.0 <3.0.0" - flutter: ">=2.8.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 329fcfa..5f5ff42 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,8 @@ dependencies: validators: ^3.0.0 dio: ^4.0.6 fluttertoast: ^8.0.6 + shared_preferences: ^2.0.7 + pretty_dio_logger: ^1.1.1 dev_dependencies: flutter_test: