From 94342c3fb8dfce3d01d4d4a6ac8c82693e2084d6 Mon Sep 17 00:00:00 2001 From: Key Date: Wed, 21 Jun 2023 17:11:18 +0800 Subject: [PATCH] feat: user util --- lib/app/splash_page.dart | 21 +++++++++++++-------- lib/common/core/const.dart | 3 +++ lib/common/core/user_util.dart | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/common/request/config.dart | 1 - lib/common/request/dao/user_dao.dart | 8 ++++++-- lib/common/request/exception_handler.dart | 5 +++-- lib/common/request/token_interceptor.dart | 6 +++--- lib/pages/login/loginpage/bloc/login_bloc.dart | 5 +---- lib/route/route.dart | 51 ++++++++++++++++++++++++++------------------------- lib/utils/sp_util.dart | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 161 insertions(+), 45 deletions(-) create mode 100644 lib/common/core/const.dart create mode 100644 lib/common/core/user_util.dart create mode 100644 lib/utils/sp_util.dart diff --git a/lib/app/splash_page.dart b/lib/app/splash_page.dart index 5d8ef98..89d9c23 100644 --- a/lib/app/splash_page.dart +++ b/lib/app/splash_page.dart @@ -1,10 +1,14 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wow_english/common/core/user_util.dart'; import 'package:wow_english/common/extension/string_extension.dart'; -import 'package:wow_english/network/basic_configuration.dart.txt'; +import 'package:wow_english/models/user_entity.dart'; import 'package:wow_english/route/route.dart'; +import 'package:wow_english/utils/sp_util.dart'; +import '../common/blocs/cachebloc/cache_bloc.dart'; class SplashPage extends StatelessWidget { const SplashPage({super.key}); @@ -25,13 +29,15 @@ class TransitionView extends StatefulWidget { } class _TransitionViewState extends State { - Future startTime() async { - Timer(const Duration(seconds: 2),() { - if(BasicConfigurationManager().sessionId!.isNotEmpty) { + // 判断是否登录 + UserEntity? userEntity = UserUtil.getUser(); + Timer(const Duration(seconds: 2), () { + if (userEntity != null && userEntity.token.isNotEmpty) { + context.read().add(UserInfoChangeEvent(userEntity)); Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.home, (route) => false); } else { - Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.login,(route) => false); + Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.login, (route) => false); } }); } @@ -39,6 +45,7 @@ class _TransitionViewState extends State { @override void initState() { super.initState(); + SpUtil.preInit(); startTime(); } @@ -52,9 +59,7 @@ class _TransitionViewState extends State { image: AssetImage( 'splash'.assetGif, ), - fit: BoxFit.fill - ) - ), + fit: BoxFit.fill)), ), ), ); diff --git a/lib/common/core/const.dart b/lib/common/core/const.dart new file mode 100644 index 0000000..608f51f --- /dev/null +++ b/lib/common/core/const.dart @@ -0,0 +1,3 @@ +class SpConst { + static const String prefsKeyUserInfo = "key_user_info"; +} diff --git a/lib/common/core/user_util.dart b/lib/common/core/user_util.dart new file mode 100644 index 0000000..43fa426 --- /dev/null +++ b/lib/common/core/user_util.dart @@ -0,0 +1,50 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:wow_english/common/core/const.dart'; +import 'package:wow_english/models/user_entity.dart'; +import 'package:wow_english/route/route.dart'; +import 'package:wow_english/utils/sp_util.dart'; + +class UserUtil { + static String token = ''; + + static saveUser(UserEntity user) { + token = user.token; + SpUtil.getInstance().setData(SpConst.prefsKeyUserInfo, user.toString()); + } + + static UserEntity? getUser() { + String? userJson = getUserJson(); + if (userJson != null && userJson.isNotEmpty) { + var userEntity = UserEntity.fromJson(json.decode(userJson)); + // todo 并且在有效期,计算一下, "expireTime": 2592000 倒计时需要手动转换,后面再优化 + if (userEntity.token.isNotEmpty) { + token = userEntity.token; + return userEntity; + } else { + // token为空或失效的,清除sp + clearUserSp(); + } + } + return null; + } + + static saveUserJson(String userJson) { + SpUtil.getInstance().setData(SpConst.prefsKeyUserInfo, userJson); + } + + static String? getUserJson() { + return SpUtil.getInstance().get(SpConst.prefsKeyUserInfo); + } + + static clearUserSp() { + token = ''; + SpUtil.getInstance().remove(SpConst.prefsKeyUserInfo); + } + + static logout() { + clearUserSp(); + Navigator.of(AppRouter.context).push(AppRouteName.login as Route); + } +} diff --git a/lib/common/request/config.dart b/lib/common/request/config.dart index 963a214..aa3bba0 100644 --- a/lib/common/request/config.dart +++ b/lib/common/request/config.dart @@ -1,7 +1,6 @@ ///request config class RequestConfig { static String baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/'; - static String token = ''; static const connectTimeout = Duration(seconds: 15); static const successCode = 200; } diff --git a/lib/common/request/dao/user_dao.dart b/lib/common/request/dao/user_dao.dart index 870f1b4..085ff1b 100644 --- a/lib/common/request/dao/user_dao.dart +++ b/lib/common/request/dao/user_dao.dart @@ -1,15 +1,19 @@ +import 'package:wow_english/common/core/user_util.dart'; import 'package:wow_english/models/user_entity.dart'; import '../apis.dart'; import '../request_client.dart'; class UserDao { - static Future login(phoneNumber, type, checkKey, checkNumber) { + static Future login(phoneNumber, type, checkKey, checkNumber) async { var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber}; - var data = requestClient.post( + var data = await requestClient.post( Apis.login, data: params, ); + if (data != null && data.token.isNotEmpty) { + UserUtil.saveUser(data); + } return data; } } diff --git a/lib/common/request/exception_handler.dart b/lib/common/request/exception_handler.dart index 348bc60..e8a1890 100644 --- a/lib/common/request/exception_handler.dart +++ b/lib/common/request/exception_handler.dart @@ -1,4 +1,5 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:wow_english/common/core/user_util.dart'; import 'exception.dart'; @@ -7,8 +8,8 @@ bool handleException(ApiException exception, {bool Function(ApiException)? onErr return true; } - if (exception.code == 401) { - ///todo to login + if (exception.code == 405) { + UserUtil.logout(); return true; } EasyLoading.showError(exception.message ?? ApiException.unknownException); diff --git a/lib/common/request/token_interceptor.dart b/lib/common/request/token_interceptor.dart index 319b207..95f24fa 100644 --- a/lib/common/request/token_interceptor.dart +++ b/lib/common/request/token_interceptor.dart @@ -1,12 +1,12 @@ import 'package:dio/dio.dart'; -import 'package:wow_english/common/request/config.dart'; +import 'package:wow_english/common/core/user_util.dart'; class TokenInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { // 判断token不为空插入, todo token的取法应该跟user在一起,这里取不到user - if (RequestConfig.token.isNotEmpty) { - options.headers["Auth-token"] = RequestConfig.token; + if (UserUtil.token.isNotEmpty) { + options.headers["Auth-token"] = UserUtil.token; } options.headers["version"] = '1.0.0'; super.onRequest(options, handler); diff --git a/lib/pages/login/loginpage/bloc/login_bloc.dart b/lib/pages/login/loginpage/bloc/login_bloc.dart index dfe9f71..a6be6dd 100644 --- a/lib/pages/login/loginpage/bloc/login_bloc.dart +++ b/lib/pages/login/loginpage/bloc/login_bloc.dart @@ -1,7 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:wow_english/common/request/config.dart'; import 'package:wow_english/common/request/dao/user_dao.dart'; import 'package:wow_english/models/user_entity.dart'; import 'package:wow_english/utils/loading.dart'; @@ -72,10 +71,8 @@ class LoginBloc extends Bloc { try { await loading(() async { var user = await UserDao.login(phoneNumber, type, checkKey, checkNumber); - print('login已执行'); print('user=$user'); - RequestConfig.token = user!.token; - emitter.call(LoginResultChangeState(user)); + emitter.call(LoginResultChangeState(user!)); }); } catch (e) { print(e); diff --git a/lib/route/route.dart b/lib/route/route.dart index 7033394..0d665c6 100644 --- a/lib/route/route.dart +++ b/lib/route/route.dart @@ -21,8 +21,6 @@ import 'package:wow_english/pages/user/user_page.dart'; import 'package:wow_english/pages/video/lookvideo/look_video_page.dart'; import 'package:wow_english/pages/voiceanswer/voice_answer_page.dart'; - - class AppRouteName { static const String splash = 'splash'; static const String login = 'login'; @@ -48,6 +46,7 @@ class AppRouteName { class AppRouter { static final navigatorKey = GlobalKey(); + // App 根节点Context static BuildContext get context => navigatorKey.currentContext!; @@ -56,60 +55,62 @@ class AppRouter { case AppRouteName.splash: return PageRouteBuilder( opaque: false, - pageBuilder: (_,__,___) => const SplashPage(), + pageBuilder: (_, __, ___) => const SplashPage(), transitionDuration: Duration.zero, transitionsBuilder: (_, __, ___, child) => child); case AppRouteName.login: - return CupertinoPageRoute(builder: (_) => const LoginPage()); + return CupertinoPageRoute(builder: (_) => const LoginPage()); case AppRouteName.home: - return CupertinoPageRoute(builder: (_) => const HomePage()); + return CupertinoPageRoute(builder: (_) => const HomePage()); case AppRouteName.fogPwd: - return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage()); + return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage()); case AppRouteName.lesson: - return CupertinoPageRoute(builder: (_) => const LessonPage()); + return CupertinoPageRoute(builder: (_) => const LessonPage()); case AppRouteName.listen: - return CupertinoPageRoute(builder: (_) => const ListenPage()); + return CupertinoPageRoute(builder: (_) => const ListenPage()); case AppRouteName.shop: - return CupertinoPageRoute(builder: (_) => const ShopHomePage()); + return CupertinoPageRoute(builder: (_) => const ShopHomePage()); case AppRouteName.exLesson: - return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage()); + return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage()); case AppRouteName.exList: - return CupertinoPageRoute(builder: (_) => const ExchangeLessonListPage()); + return CupertinoPageRoute(builder: (_) => const ExchangeLessonListPage()); case AppRouteName.reAfter: - return CupertinoPageRoute(builder: (_) => const RepeatAfterPage()); + return CupertinoPageRoute(builder: (_) => const RepeatAfterPage()); case AppRouteName.user: - return CupertinoPageRoute(builder: (_) => const UserPage()); + return CupertinoPageRoute(builder: (_) => const UserPage()); case AppRouteName.topicPic: - return CupertinoPageRoute(builder: (_) => const TopicPicturePage()); + return CupertinoPageRoute(builder: (_) => const TopicPicturePage()); case AppRouteName.topicWord: - return CupertinoPageRoute(builder: (_) => const TopicWordPage()); + return CupertinoPageRoute(builder: (_) => const TopicWordPage()); case AppRouteName.voicePic: - return CupertinoPageRoute(builder: (_) => const VoicePicPage()); + return CupertinoPageRoute(builder: (_) => const VoicePicPage()); case AppRouteName.voiceWord: - return CupertinoPageRoute(builder: (_) => const VoiceWordPage()); + return CupertinoPageRoute(builder: (_) => const VoiceWordPage()); case AppRouteName.voiceAnswer: - return CupertinoPageRoute(builder: (_) => const VoiceAnswerPage()); + return CupertinoPageRoute(builder: (_) => const VoiceAnswerPage()); case AppRouteName.lookVideo: - return CupertinoPageRoute(builder: (_) => const LookVideoPage()); + return CupertinoPageRoute(builder: (_) => const LookVideoPage()); case AppRouteName.setPwd: final phoneNum = (settings.arguments as Map)['phoneNumber'] as String; - return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum)); + return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum)); case AppRouteName.webView: final urlStr = (settings.arguments as Map)['urlStr'] as String; final webViewTitle = (settings.arguments as Map)['webViewTitle'] as String; - return CupertinoPageRoute(builder: (_) => WowWebViewPage(urlStr: urlStr,webViewTitle: webViewTitle,)); + return CupertinoPageRoute( + builder: (_) => WowWebViewPage( + urlStr: urlStr, + webViewTitle: webViewTitle, + )); case AppRouteName.tab: return PageRouteBuilder( opaque: false, settings: const RouteSettings(name: AppRouteName.tab), transitionDuration: Duration.zero, - pageBuilder: (_,__,___) => const TabPage(), + pageBuilder: (_, __, ___) => const TabPage(), transitionsBuilder: (_, __, ___, child) => child); default: return CupertinoPageRoute( - builder: (_) => Scaffold( - body: Center( - child: Text('No route defined for ${settings.name}')))); + builder: (_) => Scaffold(body: Center(child: Text('No route defined for ${settings.name}')))); } } } diff --git a/lib/utils/sp_util.dart b/lib/utils/sp_util.dart new file mode 100644 index 0000000..855fa3c --- /dev/null +++ b/lib/utils/sp_util.dart @@ -0,0 +1,56 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +class SpUtil { + SharedPreferences? _prefs; + static SpUtil? _instance; + + SpUtil.of() { + init(); + } + SpUtil._pre(SharedPreferences prefs) { + _prefs = prefs; + } + + static SpUtil getInstance() { + _instance ??= SpUtil.of(); + return _instance!; + } + + void init() async { + _prefs ??= await SharedPreferences.getInstance(); + } + + static Future preInit() async { + if (_instance == null) { + var prefs = await SharedPreferences.getInstance(); + _instance = SpUtil._pre(prefs); + } + return _instance!; + } + + void setData(String key, T data) { + if (data is String) { + _prefs?.setString(key, data); + } else if (data is double) { + _prefs?.setDouble(key, data); + } else if (data is int) { + _prefs?.setInt(key, data); + } else if (data is bool) { + _prefs?.setBool(key, data); + } else if (data is List) { + _prefs?.setStringList(key, data); + } + } + + void remove(String key) { + _prefs?.remove(key); + } + + T? get(String key) { + var value = _prefs?.get(key); + if (value != null) { + return value as T; + } + return null; + } +} -- libgit2 0.22.2