Commit 94342c3fb8dfce3d01d4d4a6ac8c82693e2084d6

Authored by Key
1 parent 05f9b20a

feat: user util

lib/app/splash_page.dart
1 1 import 'dart:async';
2 2  
3 3 import 'package:flutter/material.dart';
  4 +import 'package:flutter_bloc/flutter_bloc.dart';
  5 +import 'package:wow_english/common/core/user_util.dart';
4 6 import 'package:wow_english/common/extension/string_extension.dart';
5   -import 'package:wow_english/network/basic_configuration.dart.txt';
  7 +import 'package:wow_english/models/user_entity.dart';
6 8 import 'package:wow_english/route/route.dart';
  9 +import 'package:wow_english/utils/sp_util.dart';
7 10  
  11 +import '../common/blocs/cachebloc/cache_bloc.dart';
8 12  
9 13 class SplashPage extends StatelessWidget {
10 14 const SplashPage({super.key});
... ... @@ -25,13 +29,15 @@ class TransitionView extends StatefulWidget {
25 29 }
26 30  
27 31 class _TransitionViewState extends State<TransitionView> {
28   -
29 32 Future startTime() async {
30   - Timer(const Duration(seconds: 2),() {
31   - if(BasicConfigurationManager().sessionId!.isNotEmpty) {
  33 + // 判断是否登录
  34 + UserEntity? userEntity = UserUtil.getUser();
  35 + Timer(const Duration(seconds: 2), () {
  36 + if (userEntity != null && userEntity.token.isNotEmpty) {
  37 + context.read<CacheBloc>().add(UserInfoChangeEvent(userEntity));
32 38 Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.home, (route) => false);
33 39 } else {
34   - Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.login,(route) => false);
  40 + Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.login, (route) => false);
35 41 }
36 42 });
37 43 }
... ... @@ -39,6 +45,7 @@ class _TransitionViewState extends State&lt;TransitionView&gt; {
39 45 @override
40 46 void initState() {
41 47 super.initState();
  48 + SpUtil.preInit();
42 49 startTime();
43 50 }
44 51  
... ... @@ -52,9 +59,7 @@ class _TransitionViewState extends State&lt;TransitionView&gt; {
52 59 image: AssetImage(
53 60 'splash'.assetGif,
54 61 ),
55   - fit: BoxFit.fill
56   - )
57   - ),
  62 + fit: BoxFit.fill)),
58 63 ),
59 64 ),
60 65 );
... ...
lib/common/core/const.dart 0 → 100644
  1 +class SpConst {
  2 + static const String prefsKeyUserInfo = "key_user_info";
  3 +}
... ...
lib/common/core/user_util.dart 0 → 100644
  1 +import 'dart:convert';
  2 +
  3 +import 'package:flutter/material.dart';
  4 +import 'package:wow_english/common/core/const.dart';
  5 +import 'package:wow_english/models/user_entity.dart';
  6 +import 'package:wow_english/route/route.dart';
  7 +import 'package:wow_english/utils/sp_util.dart';
  8 +
  9 +class UserUtil {
  10 + static String token = '';
  11 +
  12 + static saveUser(UserEntity user) {
  13 + token = user.token;
  14 + SpUtil.getInstance().setData(SpConst.prefsKeyUserInfo, user.toString());
  15 + }
  16 +
  17 + static UserEntity? getUser() {
  18 + String? userJson = getUserJson();
  19 + if (userJson != null && userJson.isNotEmpty) {
  20 + var userEntity = UserEntity.fromJson(json.decode(userJson));
  21 + // todo 并且在有效期,计算一下, "expireTime": 2592000 倒计时需要手动转换,后面再优化
  22 + if (userEntity.token.isNotEmpty) {
  23 + token = userEntity.token;
  24 + return userEntity;
  25 + } else {
  26 + // token为空或失效的,清除sp
  27 + clearUserSp();
  28 + }
  29 + }
  30 + return null;
  31 + }
  32 +
  33 + static saveUserJson(String userJson) {
  34 + SpUtil.getInstance().setData(SpConst.prefsKeyUserInfo, userJson);
  35 + }
  36 +
  37 + static String? getUserJson() {
  38 + return SpUtil.getInstance().get<String>(SpConst.prefsKeyUserInfo);
  39 + }
  40 +
  41 + static clearUserSp() {
  42 + token = '';
  43 + SpUtil.getInstance().remove(SpConst.prefsKeyUserInfo);
  44 + }
  45 +
  46 + static logout() {
  47 + clearUserSp();
  48 + Navigator.of(AppRouter.context).push(AppRouteName.login as Route<Object?>);
  49 + }
  50 +}
... ...
lib/common/request/config.dart
1 1 ///request config
2 2 class RequestConfig {
3 3 static String baseUrl = 'http://wow-app.dev.kouyuxingqiu.com/';
4   - static String token = '';
5 4 static const connectTimeout = Duration(seconds: 15);
6 5 static const successCode = 200;
7 6 }
... ...
lib/common/request/dao/user_dao.dart
  1 +import 'package:wow_english/common/core/user_util.dart';
1 2 import 'package:wow_english/models/user_entity.dart';
2 3  
3 4 import '../apis.dart';
4 5 import '../request_client.dart';
5 6  
6 7 class UserDao {
7   - static Future<UserEntity?> login(phoneNumber, type, checkKey, checkNumber) {
  8 + static Future<UserEntity?> login(phoneNumber, type, checkKey, checkNumber) async {
8 9 var params = {'phoneNum': phoneNumber, 'type': type, checkKey: checkNumber};
9   - var data = requestClient.post<UserEntity>(
  10 + var data = await requestClient.post<UserEntity>(
10 11 Apis.login,
11 12 data: params,
12 13 );
  14 + if (data != null && data.token.isNotEmpty) {
  15 + UserUtil.saveUser(data);
  16 + }
13 17 return data;
14 18 }
15 19 }
... ...
lib/common/request/exception_handler.dart
1 1 import 'package:flutter_easyloading/flutter_easyloading.dart';
  2 +import 'package:wow_english/common/core/user_util.dart';
2 3  
3 4 import 'exception.dart';
4 5  
... ... @@ -7,8 +8,8 @@ bool handleException(ApiException exception, {bool Function(ApiException)? onErr
7 8 return true;
8 9 }
9 10  
10   - if (exception.code == 401) {
11   - ///todo to login
  11 + if (exception.code == 405) {
  12 + UserUtil.logout();
12 13 return true;
13 14 }
14 15 EasyLoading.showError(exception.message ?? ApiException.unknownException);
... ...
lib/common/request/token_interceptor.dart
1 1 import 'package:dio/dio.dart';
2   -import 'package:wow_english/common/request/config.dart';
  2 +import 'package:wow_english/common/core/user_util.dart';
3 3  
4 4 class TokenInterceptor extends Interceptor {
5 5 @override
6 6 void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
7 7 // 判断token不为空插入, todo token的取法应该跟user在一起,这里取不到user
8   - if (RequestConfig.token.isNotEmpty) {
9   - options.headers["Auth-token"] = RequestConfig.token;
  8 + if (UserUtil.token.isNotEmpty) {
  9 + options.headers["Auth-token"] = UserUtil.token;
10 10 }
11 11 options.headers["version"] = '1.0.0';
12 12 super.onRequest(options, handler);
... ...
lib/pages/login/loginpage/bloc/login_bloc.dart
1 1 import 'package:flutter/cupertino.dart';
2 2 import 'package:flutter_bloc/flutter_bloc.dart';
3 3 import 'package:flutter_easyloading/flutter_easyloading.dart';
4   -import 'package:wow_english/common/request/config.dart';
5 4 import 'package:wow_english/common/request/dao/user_dao.dart';
6 5 import 'package:wow_english/models/user_entity.dart';
7 6 import 'package:wow_english/utils/loading.dart';
... ... @@ -72,10 +71,8 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
72 71 try {
73 72 await loading(() async {
74 73 var user = await UserDao.login(phoneNumber, type, checkKey, checkNumber);
75   - print('login已执行');
76 74 print('user=$user');
77   - RequestConfig.token = user!.token;
78   - emitter.call(LoginResultChangeState(user));
  75 + emitter.call(LoginResultChangeState(user!));
79 76 });
80 77 } catch (e) {
81 78 print(e);
... ...
lib/route/route.dart
... ... @@ -21,8 +21,6 @@ import &#39;package:wow_english/pages/user/user_page.dart&#39;;
21 21 import 'package:wow_english/pages/video/lookvideo/look_video_page.dart';
22 22 import 'package:wow_english/pages/voiceanswer/voice_answer_page.dart';
23 23  
24   -
25   -
26 24 class AppRouteName {
27 25 static const String splash = 'splash';
28 26 static const String login = 'login';
... ... @@ -48,6 +46,7 @@ class AppRouteName {
48 46  
49 47 class AppRouter {
50 48 static final navigatorKey = GlobalKey<NavigatorState>();
  49 +
51 50 // App 根节点Context
52 51 static BuildContext get context => navigatorKey.currentContext!;
53 52  
... ... @@ -56,60 +55,62 @@ class AppRouter {
56 55 case AppRouteName.splash:
57 56 return PageRouteBuilder(
58 57 opaque: false,
59   - pageBuilder: (_,__,___) => const SplashPage(),
  58 + pageBuilder: (_, __, ___) => const SplashPage(),
60 59 transitionDuration: Duration.zero,
61 60 transitionsBuilder: (_, __, ___, child) => child);
62 61 case AppRouteName.login:
63   - return CupertinoPageRoute(builder: (_) => const LoginPage());
  62 + return CupertinoPageRoute(builder: (_) => const LoginPage());
64 63 case AppRouteName.home:
65   - return CupertinoPageRoute(builder: (_) => const HomePage());
  64 + return CupertinoPageRoute(builder: (_) => const HomePage());
66 65 case AppRouteName.fogPwd:
67   - return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage());
  66 + return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage());
68 67 case AppRouteName.lesson:
69   - return CupertinoPageRoute(builder: (_) => const LessonPage());
  68 + return CupertinoPageRoute(builder: (_) => const LessonPage());
70 69 case AppRouteName.listen:
71   - return CupertinoPageRoute(builder: (_) => const ListenPage());
  70 + return CupertinoPageRoute(builder: (_) => const ListenPage());
72 71 case AppRouteName.shop:
73   - return CupertinoPageRoute(builder: (_) => const ShopHomePage());
  72 + return CupertinoPageRoute(builder: (_) => const ShopHomePage());
74 73 case AppRouteName.exLesson:
75   - return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage());
  74 + return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage());
76 75 case AppRouteName.exList:
77   - return CupertinoPageRoute(builder: (_) => const ExchangeLessonListPage());
  76 + return CupertinoPageRoute(builder: (_) => const ExchangeLessonListPage());
78 77 case AppRouteName.reAfter:
79   - return CupertinoPageRoute(builder: (_) => const RepeatAfterPage());
  78 + return CupertinoPageRoute(builder: (_) => const RepeatAfterPage());
80 79 case AppRouteName.user:
81   - return CupertinoPageRoute(builder: (_) => const UserPage());
  80 + return CupertinoPageRoute(builder: (_) => const UserPage());
82 81 case AppRouteName.topicPic:
83   - return CupertinoPageRoute(builder: (_) => const TopicPicturePage());
  82 + return CupertinoPageRoute(builder: (_) => const TopicPicturePage());
84 83 case AppRouteName.topicWord:
85   - return CupertinoPageRoute(builder: (_) => const TopicWordPage());
  84 + return CupertinoPageRoute(builder: (_) => const TopicWordPage());
86 85 case AppRouteName.voicePic:
87   - return CupertinoPageRoute(builder: (_) => const VoicePicPage());
  86 + return CupertinoPageRoute(builder: (_) => const VoicePicPage());
88 87 case AppRouteName.voiceWord:
89   - return CupertinoPageRoute(builder: (_) => const VoiceWordPage());
  88 + return CupertinoPageRoute(builder: (_) => const VoiceWordPage());
90 89 case AppRouteName.voiceAnswer:
91   - return CupertinoPageRoute(builder: (_) => const VoiceAnswerPage());
  90 + return CupertinoPageRoute(builder: (_) => const VoiceAnswerPage());
92 91 case AppRouteName.lookVideo:
93   - return CupertinoPageRoute(builder: (_) => const LookVideoPage());
  92 + return CupertinoPageRoute(builder: (_) => const LookVideoPage());
94 93 case AppRouteName.setPwd:
95 94 final phoneNum = (settings.arguments as Map)['phoneNumber'] as String;
96   - return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum));
  95 + return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum));
97 96 case AppRouteName.webView:
98 97 final urlStr = (settings.arguments as Map)['urlStr'] as String;
99 98 final webViewTitle = (settings.arguments as Map)['webViewTitle'] as String;
100   - return CupertinoPageRoute(builder: (_) => WowWebViewPage(urlStr: urlStr,webViewTitle: webViewTitle,));
  99 + return CupertinoPageRoute(
  100 + builder: (_) => WowWebViewPage(
  101 + urlStr: urlStr,
  102 + webViewTitle: webViewTitle,
  103 + ));
101 104 case AppRouteName.tab:
102 105 return PageRouteBuilder(
103 106 opaque: false,
104 107 settings: const RouteSettings(name: AppRouteName.tab),
105 108 transitionDuration: Duration.zero,
106   - pageBuilder: (_,__,___) => const TabPage(),
  109 + pageBuilder: (_, __, ___) => const TabPage(),
107 110 transitionsBuilder: (_, __, ___, child) => child);
108 111 default:
109 112 return CupertinoPageRoute(
110   - builder: (_) => Scaffold(
111   - body: Center(
112   - child: Text('No route defined for ${settings.name}'))));
  113 + builder: (_) => Scaffold(body: Center(child: Text('No route defined for ${settings.name}'))));
113 114 }
114 115 }
115 116 }
... ...
lib/utils/sp_util.dart 0 → 100644
  1 +import 'package:shared_preferences/shared_preferences.dart';
  2 +
  3 +class SpUtil {
  4 + SharedPreferences? _prefs;
  5 + static SpUtil? _instance;
  6 +
  7 + SpUtil.of() {
  8 + init();
  9 + }
  10 + SpUtil._pre(SharedPreferences prefs) {
  11 + _prefs = prefs;
  12 + }
  13 +
  14 + static SpUtil getInstance() {
  15 + _instance ??= SpUtil.of();
  16 + return _instance!;
  17 + }
  18 +
  19 + void init() async {
  20 + _prefs ??= await SharedPreferences.getInstance();
  21 + }
  22 +
  23 + static Future<SpUtil> preInit() async {
  24 + if (_instance == null) {
  25 + var prefs = await SharedPreferences.getInstance();
  26 + _instance = SpUtil._pre(prefs);
  27 + }
  28 + return _instance!;
  29 + }
  30 +
  31 + void setData<T>(String key, T data) {
  32 + if (data is String) {
  33 + _prefs?.setString(key, data);
  34 + } else if (data is double) {
  35 + _prefs?.setDouble(key, data);
  36 + } else if (data is int) {
  37 + _prefs?.setInt(key, data);
  38 + } else if (data is bool) {
  39 + _prefs?.setBool(key, data);
  40 + } else if (data is List<String>) {
  41 + _prefs?.setStringList(key, data);
  42 + }
  43 + }
  44 +
  45 + void remove(String key) {
  46 + _prefs?.remove(key);
  47 + }
  48 +
  49 + T? get<T>(String key) {
  50 + var value = _prefs?.get(key);
  51 + if (value != null) {
  52 + return value as T;
  53 + }
  54 + return null;
  55 + }
  56 +}
... ...