From c5cbeac5049af9fd8a3d0342516e0867105a5bce Mon Sep 17 00:00:00 2001 From: PH2 <1293456824@qq.com> Date: Sat, 28 Nov 2020 15:49:28 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=95=86=E5=93=81=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E7=9A=84=E7=BC=93=E5=AD=98=202=E3=80=81=E6=B7=98=E5=AE=9D?= =?UTF-8?q?=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/user/user_info_model.dart | 7 +- lib/models/user/user_info_model_notifier.dart | 3 + .../bloc/login_account_repository.dart | 9 +- .../account/bloc/login_account_state.dart | 14 +- .../account/login_account_page.dart | 38 +- lib/pages/login_page/bind/bloc/bloc.dart | 4 + .../bind/bloc/login_bind_phone_bloc.dart | 59 ++ .../bind/bloc/login_bind_phone_event.dart | 47 ++ .../bloc/login_bind_phone_repository.dart | 77 +++ .../bind/bloc/login_bind_phone_state.dart | 54 ++ .../bind/login_bind_phone_page.dart | 555 ++++++++++++++++++ .../login_page/bind/login_bind_phone_sk.dart | 61 ++ .../model/login_bind_phone_user_model.dart | 30 + lib/pages/login_page/bloc/login_bloc.dart | 53 +- lib/pages/login_page/bloc/login_event.dart | 30 +- .../login_page/bloc/login_repository.dart | 69 ++- lib/pages/login_page/bloc/login_state.dart | 34 +- .../invite/bloc/login_invite_bloc.dart | 6 +- .../invite/bloc/login_invite_repository.dart | 49 +- .../invite/bloc/login_invite_state.dart | 15 +- .../login_page/invite/login_invite_page.dart | 37 +- lib/pages/login_page/login_page.dart | 128 +++- ...{login_util.dart => login_style_util.dart} | 14 +- ...ogin_model.dart => login_style_model.dart} | 207 +++---- lib/util/global_config.dart | 9 +- lib/util/mob_util/mob_util.dart | 2 +- .../mob_util/secverify/quick_login_util.dart | 2 +- lib/util/net_util.dart | 9 +- 28 files changed, 1387 insertions(+), 235 deletions(-) create mode 100644 lib/pages/login_page/bind/bloc/bloc.dart create mode 100644 lib/pages/login_page/bind/bloc/login_bind_phone_bloc.dart create mode 100644 lib/pages/login_page/bind/bloc/login_bind_phone_event.dart create mode 100644 lib/pages/login_page/bind/bloc/login_bind_phone_repository.dart create mode 100644 lib/pages/login_page/bind/bloc/login_bind_phone_state.dart create mode 100644 lib/pages/login_page/bind/login_bind_phone_page.dart create mode 100644 lib/pages/login_page/bind/login_bind_phone_sk.dart create mode 100644 lib/pages/login_page/bind/model/login_bind_phone_user_model.dart rename lib/pages/login_page/{login_util.dart => login_style_util.dart} (75%) rename lib/pages/login_page/model/{login_model.dart => login_style_model.dart} (86%) diff --git a/lib/models/user/user_info_model.dart b/lib/models/user/user_info_model.dart index 24907bf..95534f2 100644 --- a/lib/models/user/user_info_model.dart +++ b/lib/models/user/user_info_model.dart @@ -10,20 +10,22 @@ class UserInfoModel { String username; List perms; String registerInviteCodeEnable; + String bindPhoneEnable; bool isTBAuth; // 是否淘宝授权 // 获取模糊手机号码 get blurMobile => !EmptyUtil.isEmpty(mobile) ? mobile.length == 11 ? '${mobile.substring(0, 3)}****${mobile.substring(7, mobile.length)}' : mobile : mobile; - UserInfoModel({this.token, this.userId, this.username, this.perms, this.registerInviteCodeEnable, this.isTBAuth = false}); + UserInfoModel({this.token, this.userId, this.username, this.perms, this.registerInviteCodeEnable, this.isTBAuth = false, this.bindPhoneEnable}); UserInfoModel.fromJson(Map json) { token = json['token']; userId = json['user_id']; username = json['username']; mobile = json['mobile']; - perms = json['perms']?.cast(); registerInviteCodeEnable = json['register_invite_code_enable']; + bindPhoneEnable= json['bind_phone_enable']; + perms = json['perms']?.cast(); isTBAuth = json['isTBAuth'] ?? false; } @@ -35,6 +37,7 @@ class UserInfoModel { data['perms'] = this.perms; data['mobile'] = this.mobile; data['register_invite_code_enable'] = this.registerInviteCodeEnable; + data['bind_phone_enable'] = this.bindPhoneEnable; data['isTBAuth'] = this.isTBAuth; return data; } diff --git a/lib/models/user/user_info_model_notifier.dart b/lib/models/user/user_info_model_notifier.dart index fd8b799..51071ce 100644 --- a/lib/models/user/user_info_model_notifier.dart +++ b/lib/models/user/user_info_model_notifier.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:flutter_alibc/flutter_alibc.dart'; import 'package:zhiying_comm/models/user/user_info_model.dart'; import 'package:zhiying_comm/util/global_config.dart'; import 'package:zhiying_comm/util/log/let_log.dart'; @@ -71,6 +72,8 @@ class UserInfoNotifier with ChangeNotifier { GlobalConfig.SHARED_KEY_MOBILE, ''); await SharedPreferencesUtil.setStringValue( GlobalConfig.SHARED_KEY_USER_INFO, ''); + // 退出淘宝登录 + FlutterAlibc.loginOut(); notifyListeners(); } diff --git a/lib/pages/login_page/account/bloc/login_account_repository.dart b/lib/pages/login_page/account/bloc/login_account_repository.dart index 6063446..9ffba58 100644 --- a/lib/pages/login_page/account/bloc/login_account_repository.dart +++ b/lib/pages/login_page/account/bloc/login_account_repository.dart @@ -1,13 +1,12 @@ -import 'dart:math'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'package:zhiying_comm/util/global_config.dart'; import 'package:zhiying_comm/util/mob_util/mob_util.dart'; import 'package:zhiying_comm/util/net_util.dart'; import 'package:zhiying_comm/models/user/user_info_model.dart'; -import '../../login_util.dart'; +import '../../login_style_util.dart'; import 'bloc.dart'; /// @@ -15,8 +14,8 @@ import 'bloc.dart'; /// class LoginAccountRepository { /// 获取数据,如果缓存有,则获取缓存的数据 - Future fetchData() async { - var result = await LoginUtil.getLoginModel(); + Future fetchData() async { + var result = await LoginStyleUtil.getLoginModel(); if (!EmptyUtil.isEmpty(result)) { return result; } diff --git a/lib/pages/login_page/account/bloc/login_account_state.dart b/lib/pages/login_page/account/bloc/login_account_state.dart index 0d85a8b..0d1ccaf 100644 --- a/lib/pages/login_page/account/bloc/login_account_state.dart +++ b/lib/pages/login_page/account/bloc/login_account_state.dart @@ -1,7 +1,7 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/cupertino.dart'; import 'package:zhiying_comm/models/user/user_info_model.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; abstract class LoginAccountState extends Equatable { const LoginAccountState(); @@ -15,7 +15,7 @@ class LoginAccountInitial extends LoginAccountState {} /// 数据加载完毕状态 class LoginAccountLoadedState extends LoginAccountState { - final LoginModel model; + final LoginStyleModel model; const LoginAccountLoadedState({@required this.model}); @@ -55,7 +55,11 @@ class LoginAccountLoginSuccessState extends LoginAccountState { /// 登陆失败 class LoginAccountLoginErrorState extends LoginAccountState { - final String msg; + @override + bool operator ==(Object other) { + return false; + } - const LoginAccountLoginErrorState({this.msg}); -} \ No newline at end of file + @override + int get hashCode => super.hashCode; +} diff --git a/lib/pages/login_page/account/login_account_page.dart b/lib/pages/login_page/account/login_account_page.dart index 70d2461..585715b 100644 --- a/lib/pages/login_page/account/login_account_page.dart +++ b/lib/pages/login_page/account/login_account_page.dart @@ -5,7 +5,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; import 'package:zhiying_comm/pages/login_page/invite/login_invite_page.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; import 'bloc/bloc.dart'; import 'bloc/login_account_repository.dart'; @@ -52,6 +52,7 @@ class _LoginAccountPageContianerState extends State i FocusNode _phoneFN; FocusNode _passFN; FocusNode _vcodeFN; + // 是否登录中 bool _isLogging = false; @@ -88,11 +89,13 @@ class _LoginAccountPageContianerState extends State i _isLogging = true; }); if (_useVcode) { - BlocProvider.of(context).add(LoginAccountTypeVcodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? '', captcha: _vcodeEdController?.text?.toString()?.trim() ?? '')); + BlocProvider.of(context) + .add(LoginAccountTypeVcodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? '', captcha: _vcodeEdController?.text?.toString()?.trim() ?? '')); } else { - BlocProvider.of(context).add(LoginAccountTypePasswordEvent(username: _phoneEdController?.text?.toString()?.trim() ?? '', password: _passEdController?.text?.toString()?.trim() ?? '')); + BlocProvider.of(context) + .add(LoginAccountTypePasswordEvent(username: _phoneEdController?.text?.toString()?.trim() ?? '', password: _passEdController?.text?.toString()?.trim() ?? '')); } - }else{ + } else { Logger.log('参数有误 或者 正在登录中。。。'); } } @@ -277,6 +280,7 @@ class _LoginAccountPageContianerState extends State i Provider.of(context, listen: false)?.setUserInfo(current.model); if (current?.model?.registerInviteCodeEnable != '1') { Fluttertoast.showToast(msg: '登录成功~'); + _isLogging = true; /// 打开也买 _openLoginSuccessPage(); @@ -310,7 +314,7 @@ class _LoginAccountPageContianerState extends State i } /// 主页面 - Widget _getMainWidget(LoginModel model) { + Widget _getMainWidget(LoginStyleModel model) { print(model); return Column( children: [ @@ -348,7 +352,7 @@ class _LoginAccountPageContianerState extends State i } /// appBar - Widget _getAppBarWidget(LoginModel model) { + Widget _getAppBarWidget(LoginStyleModel model) { return AppBar( backgroundColor: HexColor.fromHex('#FFFFFF'), brightness: Brightness.light, @@ -370,7 +374,7 @@ class _LoginAccountPageContianerState extends State i } /// title - Widget _getTitleWidget(LoginModel model) { + Widget _getTitleWidget(LoginStyleModel model) { return Align( alignment: Alignment.centerLeft, child: Text( @@ -380,7 +384,7 @@ class _LoginAccountPageContianerState extends State i } /// 手机输入框 - Widget _getPhoneWidget(LoginModel model) { + Widget _getPhoneWidget(LoginStyleModel model) { return _getCustomInputWidget( hint: model?.mobile?.inputMobileHintText ?? '请输入您的手机号', controller: _phoneEdController, @@ -393,7 +397,7 @@ class _LoginAccountPageContianerState extends State i } /// 验证码输入框 - Widget _getVcodeWidget(LoginModel model) { + Widget _getVcodeWidget(LoginStyleModel model) { return Container( height: 42, child: Stack( @@ -414,7 +418,7 @@ class _LoginAccountPageContianerState extends State i } /// 验证码按钮 - Widget _getVcodeButtonWidget(LoginModel model) { + Widget _getVcodeButtonWidget(LoginStyleModel model) { return VcodeWidget( onCallBack: this, awaitTime: int.parse(model?.mobile?.vcodeTime ?? '60'), @@ -458,11 +462,11 @@ class _LoginAccountPageContianerState extends State i } /// 密码输入框 - Widget _getPassInputWidget(LoginModel model) { + Widget _getPassInputWidget(LoginStyleModel model) { return Container( height: 42, child: _getCustomInputWidget( - obscureText: true, + obscureText: true, keyboardType: TextInputType.text, controller: _passEdController, focusNode: _passFN, @@ -476,7 +480,7 @@ class _LoginAccountPageContianerState extends State i } /// 切换登陆方式tip - Widget _getChangeTipWidget(LoginModel model) { + Widget _getChangeTipWidget(LoginStyleModel model) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => _changeLoginTypeOnClick(), @@ -488,7 +492,7 @@ class _LoginAccountPageContianerState extends State i } /// 登陆按钮 - Widget _getSubmiBtnWidget(LoginModel model) { + Widget _getSubmiBtnWidget(LoginStyleModel model) { return Material( child: Container( height: 52, @@ -512,7 +516,7 @@ class _LoginAccountPageContianerState extends State i } /// 协议 - Widget _getProtoclWidget(LoginModel model) { + Widget _getProtoclWidget(LoginStyleModel model) { // return Text('同意《嗨如意用户协议》 及《营私政策》', style: TextStyle(fontSize: 11, color: HexColor.fromHex('#C0C0C0'))); return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -547,7 +551,7 @@ class _LoginAccountPageContianerState extends State i } /// 底部提示tip - Widget _getBottomTipWidget(LoginModel model) { + Widget _getBottomTipWidget(LoginStyleModel model) { return Padding( padding: const EdgeInsets.only(bottom: 25), child: Text( @@ -596,7 +600,7 @@ class _LoginAccountPageContianerState extends State i expands: false, style: TextStyle(color: HexColor.fromHex(textColor)), maxLines: 1, - keyboardType: keyboardType ?? TextInputType.number, + keyboardType: keyboardType ?? TextInputType.number, decoration: InputDecoration( contentPadding: EdgeInsets.only(top: 30, left: 7.5), hintText: hint, diff --git a/lib/pages/login_page/bind/bloc/bloc.dart b/lib/pages/login_page/bind/bloc/bloc.dart new file mode 100644 index 0000000..af450d7 --- /dev/null +++ b/lib/pages/login_page/bind/bloc/bloc.dart @@ -0,0 +1,4 @@ +export 'login_bind_phone_state.dart'; +export 'login_bind_phone_event.dart'; +export 'login_bind_phone_repository.dart'; +export 'login_bind_phone_bloc.dart'; diff --git a/lib/pages/login_page/bind/bloc/login_bind_phone_bloc.dart b/lib/pages/login_page/bind/bloc/login_bind_phone_bloc.dart new file mode 100644 index 0000000..6ca0e57 --- /dev/null +++ b/lib/pages/login_page/bind/bloc/login_bind_phone_bloc.dart @@ -0,0 +1,59 @@ +import 'dart:async'; +import 'package:bloc/bloc.dart'; +import 'package:flutter/cupertino.dart'; +import './bloc.dart'; +import 'package:zhiying_comm/util/empty_util.dart'; + +class LoginBindPhoneBloc extends Bloc { + LoginBindPhoneRepository repository; + + LoginBindPhoneBloc({@required this.repository}); + + @override + LoginBindPhoneState get initialState => LoginBindPhoneInitial(); + + @override + Stream mapEventToState(LoginBindPhoneEvent event) async* { + /// 获取数据 + if (event is LoginBindPhoneInitEvent) { + yield* _mapInitEventToState(); + } + + /// 获取验证码 + if (event is LoginBindPhoneGetVCodeEvent) { + yield* _mapGetVcodeEventToState(event); + } + + /// 登陆(验证码) + if (event is LoginBindPhoneTypeVCodeEvent) { + yield* _mapLoginTypeVcodeEventToState(event); + } + } + + /// 获取数据 + Stream _mapInitEventToState() async* { + var data = await repository.fetchData(); + if (!EmptyUtil.isEmpty(data)) + yield LoginBindPhoneLoadedState(model: data); + else + yield LoginBindPhoneErrorState(); + } + + /// 获取验证码 + Stream _mapGetVcodeEventToState(LoginBindPhoneGetVCodeEvent event) async* { + bool result = await repository.fetchGetVcode(event); + if (result) + yield LoginBindPhoneGetVCodeSuccessState(); + else + yield LoginBindPhoneGetVCodeErrorState(); + } + + /// 验证码登陆 + Stream _mapLoginTypeVcodeEventToState(LoginBindPhoneTypeVCodeEvent event) async* { + var result = await repository.loginTypeVCode(event); + if (!EmptyUtil.isEmpty(result)) + yield LoginBindPhoneLoginSuccessState(model: result); + else + yield LoginBindPhoneLoginErrorState(); + } +} diff --git a/lib/pages/login_page/bind/bloc/login_bind_phone_event.dart b/lib/pages/login_page/bind/bloc/login_bind_phone_event.dart new file mode 100644 index 0000000..9e84f66 --- /dev/null +++ b/lib/pages/login_page/bind/bloc/login_bind_phone_event.dart @@ -0,0 +1,47 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/cupertino.dart'; + +abstract class LoginBindPhoneEvent extends Equatable { + const LoginBindPhoneEvent(); + + @override + List get props => []; +} + +/// 初始化事件 +class LoginBindPhoneInitEvent extends LoginBindPhoneEvent {} + +/// 获取验证码 +class LoginBindPhoneGetVCodeEvent extends LoginBindPhoneEvent { + final String mobile; + + const LoginBindPhoneGetVCodeEvent({@required this.mobile}); + + @override + List get props => [mobile]; +} + +/// 核对验证码 +class LoginBindPhoneCheckVCodeEvent extends LoginBindPhoneEvent { + /// 手机号码 + final String mobile; + + /// 验证码 + final String captcha; + + const LoginBindPhoneCheckVCodeEvent({@required this.mobile, @required this.captcha}); + + @override + List get props => [this.mobile, this.captcha]; +} + +/// 登陆事件(验证码登陆) +class LoginBindPhoneTypeVCodeEvent extends LoginBindPhoneEvent { + final String mobile; + final String captcha; + + const LoginBindPhoneTypeVCodeEvent({@required this.mobile, @required this.captcha}); + + @override + List get props => [this.mobile, this.captcha]; +} diff --git a/lib/pages/login_page/bind/bloc/login_bind_phone_repository.dart b/lib/pages/login_page/bind/bloc/login_bind_phone_repository.dart new file mode 100644 index 0000000..1c226d7 --- /dev/null +++ b/lib/pages/login_page/bind/bloc/login_bind_phone_repository.dart @@ -0,0 +1,77 @@ +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; +import 'package:zhiying_comm/util/empty_util.dart'; +import 'package:zhiying_comm/util/global_config.dart'; +import 'package:zhiying_comm/util/log/let_log.dart'; +import 'package:zhiying_comm/util/mob_util/mob_util.dart'; +import 'package:zhiying_comm/util/net_util.dart'; +import 'package:zhiying_comm/models/user/user_info_model.dart'; +import '../../login_style_util.dart'; +import 'bloc.dart'; + +/// +/// 账户登陆 +/// +class LoginBindPhoneRepository { + final Map data; + + LoginBindPhoneRepository(this.data); + + /// 获取数据,如果缓存有,则获取缓存的数据 + Future fetchData() async { + var result = await LoginStyleUtil.getLoginModel(); + if (!EmptyUtil.isEmpty(result)) { + return result; + } + return null; + } + + /// 获取验证码 + Future fetchGetVcode(LoginBindPhoneGetVCodeEvent event) async { + print('mobile = ${event.mobile}'); + var result = await MobUtil.getTextCode(event?.mobile, smsCodeType: SMSCodeType.AUTO); + return result; + } + + /// 验证码登陆 + Future loginTypeVCode(LoginBindPhoneTypeVCodeEvent event) async { + try { + String third = data['thirdType']; + if (EmptyUtil.isEmpty(third)) return null; + + /// 请求参数 + Map params = {}; + params['mobile'] = event.mobile; + params['zone'] = '86'; + params['captcha'] = event.captcha; + + /// 淘宝登录 + if (GlobalConfig.LOGIN_THIRD_ALI == third) { + Map taobaoParam = {}; + taobaoParam['nick_name'] = data['nick']; + taobaoParam['avatar_url'] = data['avatarUrl']; + taobaoParam['open_id'] = data['openId']; + taobaoParam['sid'] = data['openSid']; + taobaoParam['access_token'] = data['topAccessToken']; + taobaoParam['auth_code'] = data['topAuthCode']; + params['taobao'] = taobaoParam; + } + + /// 苹果登录 + if(GlobalConfig.LOGIN_THIRD_APPLE == third){ + + } + + var result = await NetUtil.post('/api/v1/sign/fast/in', params: params); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + UserInfoModel loginUser = UserInfoModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + if (null != loginUser) { + loginUser.mobile = event.mobile; + return loginUser; + } + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } +} diff --git a/lib/pages/login_page/bind/bloc/login_bind_phone_state.dart b/lib/pages/login_page/bind/bloc/login_bind_phone_state.dart new file mode 100644 index 0000000..7fb8b91 --- /dev/null +++ b/lib/pages/login_page/bind/bloc/login_bind_phone_state.dart @@ -0,0 +1,54 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:zhiying_comm/models/user/user_info_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; + +abstract class LoginBindPhoneState extends Equatable { + const LoginBindPhoneState(); + + @override + List get props => []; +} + +/// 初始化状态 +class LoginBindPhoneInitial extends LoginBindPhoneState {} + +/// 数据加载完毕状态 +class LoginBindPhoneLoadedState extends LoginBindPhoneState { + final LoginStyleModel model; + + const LoginBindPhoneLoadedState({@required this.model}); + + @override + List get props => [this.model]; +} + +/// 数据加载出错状态 +class LoginBindPhoneErrorState extends LoginBindPhoneState {} + +/// 验证码下发成功的状态 +class LoginBindPhoneGetVCodeSuccessState extends LoginBindPhoneState {} + +/// 验证码下发失败的状态 +class LoginBindPhoneGetVCodeErrorState extends LoginBindPhoneState {} + +/// 登陆成功 +class LoginBindPhoneLoginSuccessState extends LoginBindPhoneState { + final UserInfoModel model; + + const LoginBindPhoneLoginSuccessState({@required this.model}); + + @override + List get props => [this.model]; +} + +/// 登陆失败 +class LoginBindPhoneLoginErrorState extends LoginBindPhoneState { + @override + bool operator ==(Object other) { + return false; + } + + @override + int get hashCode => super.hashCode; +} diff --git a/lib/pages/login_page/bind/login_bind_phone_page.dart b/lib/pages/login_page/bind/login_bind_phone_page.dart new file mode 100644 index 0000000..689cd20 --- /dev/null +++ b/lib/pages/login_page/bind/login_bind_phone_page.dart @@ -0,0 +1,555 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:provider/provider.dart'; +import 'package:zhiying_comm/pages/login_page/account/widget/slide_verify_widget.dart'; +import 'package:zhiying_comm/pages/login_page/account/widget/vcode_widget.dart'; +import 'package:zhiying_comm/pages/login_page/invite/login_invite_page.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +import 'bloc/bloc.dart'; +import 'package:zhiying_comm/util/empty_util.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +import 'login_bind_phone_sk.dart'; + +/// +/// 账号登陆(手机验证码,密码) +/// +class LoginBindPhonePage extends StatelessWidget { + /// + /// 这里面model 需要带上 thirdType key,作为第三方登录的类型。 + /// + final Map model; + + const LoginBindPhonePage(this.model, {Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: HexColor.fromHex('#FFFFFF'), + body: BlocProvider( + create: (_) => LoginBindPhoneBloc(repository: LoginBindPhoneRepository(model))..add(LoginBindPhoneInitEvent()), + child: _LoginBindPhonePageContainer(), + ), + ); + } +} + +/// 啦啦啦 +class _LoginBindPhonePageContainer extends StatefulWidget { + @override + _LoginBindPhonePageContainerState createState() => _LoginBindPhonePageContainerState(); +} + +/// +/// 主体逻辑 +/// +class _LoginBindPhonePageContainerState extends State<_LoginBindPhonePageContainer> implements OnClickListener { + TextEditingController _phoneEdController; + TextEditingController _vcodeEdController; + TextEditingController _passEdController; + FocusNode _phoneFN; + FocusNode _passFN; + FocusNode _vcodeFN; + + // 是否登录中 + bool _isLogging = false; + + /// 跳转到邀请码页面 + void _openInvitePage() { + print('跳转到邀请码页面'); + RouterUtil.hideKeyboard(context); + Navigator.push(context, CupertinoPageRoute(builder: (_) => LoginInvitePage())); + } + + /// 登陆成功页面 + void _openLoginSuccessPage() { + RouterUtil.hideKeyboard(context); + RouterUtil.goBackHomePage(context); + } + + /// 返回上一页 + void _openPop() { + if (Navigator.canPop(context)) { + Navigator.pop(context); + } + } + + /// 登陆 + void _submitOnClick() { + print('登陆'); + if (_checkParam(true) && !_isLogging) { + setState(() { + _isLogging = true; + }); + BlocProvider.of(context) + .add(LoginBindPhoneTypeVCodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? '', captcha: _vcodeEdController?.text?.toString()?.trim() ?? '')); + } else { + Logger.log('参数有误 或者 正在登录中。。。'); + } + } + + /// 同意协议 + void _agreeOnClick() { + print('同意协议'); + setState(() { + _acceptAgreement = !_acceptAgreement; + }); + _checkParam(false); + } + + /// 打开协议 + void _openAgreement(String url) { + if (!EmptyUtil.isEmpty(url)) { + print('打开协议$url'); + RouterUtil.openWebview(url, context); + } + } + + /// 输入框监听 + void _onChange(string) { + print('$string'); + _checkParam(false); + } + + /// 校验登陆参数 + bool _checkParam(bool needToast) { + // 验证码 + String phone = _phoneEdController?.text?.toString()?.trim() ?? null; + String vCode = _vcodeEdController?.text?.toString()?.trim() ?? null; + if (EmptyUtil.isEmpty(phone)) { + if (needToast) Fluttertoast.showToast(msg: '手机号不能为空!'); + return false; + } + if (phone.length != 11) { + if (needToast) Fluttertoast.showToast(msg: '手机号格式有误!'); + return false; + } + if (EmptyUtil.isEmpty(vCode)) { + if (needToast) Fluttertoast.showToast(msg: '验证码不能为空!'); + return false; + } + if (vCode.length < 4) { + if (needToast) Fluttertoast.showToast(msg: '验证码号格式有误!'); + return false; + } + + if (!_acceptAgreement) { + if (needToast) Fluttertoast.showToast(msg: '请同意用户协议与隐私政策'); + return false; + } + + setState(() { + _canSubmit = true; + }); + return true; + } + + /// 检测手机号是否合法 + bool _checkPhoneNumParam(bool needToast) { + String phone = _phoneEdController?.text?.toString()?.trim() ?? null; + if (EmptyUtil.isEmpty(phone)) { + if (needToast) Fluttertoast.showToast(msg: '手机号不能为空!'); + return false; + } + if (phone.length != 11) { + if (needToast) Fluttertoast.showToast(msg: '手机号格式有误!'); + return false; + } + return true; + } + + /// 是否可以登陆 + bool _canSubmit = false; + + /// 是否同意协议 + bool _acceptAgreement = true; + + /// 是否显示第三方验证码 + bool _showOtherVcode = false; + + @override + void initState() { + _phoneEdController = TextEditingController(); + _passEdController = TextEditingController(); + _vcodeEdController = TextEditingController(); + _vcodeFN = FocusNode(); + _passFN = FocusNode(); + _phoneFN = FocusNode(); + super.initState(); + } + + @override + void dispose() { + _phoneEdController?.dispose(); + _passEdController?.dispose(); + _vcodeEdController?.dispose(); + _phoneFN?.unfocus(); + _passFN?.unfocus(); + _vcodeFN?.unfocus(); + _phoneFN?.dispose(); + _passFN?.dispose(); + _vcodeFN?.dispose(); + super.dispose(); + } + + @override + bool onVcodeClick() { + /// 获取验证码 + if (_checkPhoneNumParam(true)) { + BlocProvider.of(context).add(LoginBindPhoneGetVCodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? '')); + return true; + } + return false; + } + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + if (state is LoginBindPhoneLoginSuccessState) {} + }, + buildWhen: (prev, current) { + // 登陆失败 + if (current is LoginBindPhoneLoginErrorState) { + // Fluttertoast.showToast(msg: '登陆失败'); + setState(() { + _isLogging = false; + }); + + return false; + } + // 登陆成功 + if (current is LoginBindPhoneLoginSuccessState) { + /// 缓存登陆数据 + Provider.of(context, listen: false)?.setUserInfo(current.model); + if (current?.model?.registerInviteCodeEnable != '1') { + Fluttertoast.showToast(msg: '登录成功~'); + _isLogging = true; + + /// 打开也买 + _openLoginSuccessPage(); + } else { + /// 打开邀请页面 + _openInvitePage(); + } + return false; + } + // 获取验证码成功 + if (current is LoginBindPhoneGetVCodeSuccessState) { + Fluttertoast.showToast(msg: '验证码下发成功'); + return false; + } + // 获取验证码失败 + if (current is LoginBindPhoneGetVCodeErrorState) { + Fluttertoast.showToast(msg: '验证码获取失败~'); + return false; + } + return true; + }, + builder: (context, state) { + print('state = $state'); + if (state is LoginBindPhoneLoadedState) { + return _getMainWidget(state.model); + } + // 返回骨架屏 + return LoginBindPhoneSkeleton(); + }, + ); + } + + /// 主页面 + Widget _getMainWidget(LoginStyleModel model) { + print(model); + return Column( + children: [ + /// appBar + _getAppBarWidget(model), + + /// title + Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 40), child: _getTitleWidget(model)), + + /// 手机输入框 + Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 30), child: _getPhoneWidget(model)), + + /// 验证码 + Visibility(visible: true, child: Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 15), child: _getVCodeWidget(model))), + + /// 第三方验证码 + Visibility(visible: _showOtherVcode, child: Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 15), child: _getOtherVcodeInputWidget(model))), + + /// 登录按钮 + Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 30), child: _getSubmitBtnWidget(model)), + + /// 协议 + Padding(padding: const EdgeInsets.only(top: 15), child: _getProtoclWidget(model)), + + /// 底部提示tip + Visibility(visible: false, child: Expanded(child: Align(alignment: Alignment.bottomCenter, child: _getBottomTipWidget(model)))) + ], + ); + } + + /// appBar + Widget _getAppBarWidget(LoginStyleModel model) { + return AppBar( + backgroundColor: HexColor.fromHex('#FFFFFF'), + brightness: Brightness.light, + elevation: 0, + title: Text( + model?.mobile?.thirdPartyLoginAppBarTitle ?? '绑定手机号', + style: TextStyle(color: HexColor.fromHex(model?.mobile?.appBarTitleColor ?? '#333333')), + ), + centerTitle: true, + leading: IconButton( + icon: Icon( + Icons.arrow_back_ios, + size: 22, + color: HexColor.fromHex('#333333'), + ), + onPressed: () => _openPop(), + ), + ); + } + + /// title + Widget _getTitleWidget(LoginStyleModel model) { + return Align( + alignment: Alignment.centerLeft, + child: Text( + model?.mobile?.thirdPartyLoginTitle ?? '绑定手机', + style: TextStyle(color: HexColor.fromHex(model?.mobile?.titleColor ?? '#333333'), fontSize: 25), + )); + } + + /// 手机输入框 + Widget _getPhoneWidget(LoginStyleModel model) { + return _getCustomInputWidget( + hint: model?.mobile?.inputMobileHintText ?? '请输入您的手机号', + controller: _phoneEdController, + focusNode: _phoneFN, + onChanged: _onChange, + hintColor: model?.mobile?.inputHintColor ?? '#999999', + bgColor: model?.mobile?.inputBgColor ?? '#F7F7F7', + textColor: model?.mobile?.inputTextColor ?? '#333333', + iconUrl: model?.mobile?.inputMobileIcon ?? ''); + } + + /// 验证码输入框 + Widget _getVCodeWidget(LoginStyleModel model) { + return Container( + height: 42, + child: Stack( + children: [ + _getCustomInputWidget( + controller: _vcodeEdController, + focusNode: _vcodeFN, + onChanged: _onChange, + hintColor: model?.mobile?.inputHintColor ?? '#999999', + hint: model?.mobile?.inputVcodeHintText ?? '请输入您的验证码', + bgColor: model?.mobile?.inputBgColor ?? '#F7F7F7', + textColor: model?.mobile?.inputTextColor ?? '#333333', + iconUrl: model?.mobile?.inputVcodeIcon ?? ''), + Align(alignment: Alignment.centerRight, child: _getVcodeButtonWidget(model)), + ], + ), + ); + } + + /// 验证码按钮 + Widget _getVcodeButtonWidget(LoginStyleModel model) { + return VcodeWidget( + onCallBack: this, + awaitTime: int.parse(model?.mobile?.vcodeTime ?? '60'), + btnAwaitText: '秒', + btnText: '获取验证码', + btnTextColor: model?.mobile?.btnVcodeTextColor ?? '#FFFFFF', + color: model?.mobile?.btnVcodeBgColor ?? '#FF4343', + disabledColor: model?.mobile?.btnVcodeBanBgColor ?? '#DDDDDD', + disabledTextColor: model?.mobile?.btnVcodeBanTextColor ?? '#FFFFFF'); + } + + /// 第三方验证码输入框 + Widget _getOtherVcodeInputWidget(var model) { + return Container( + width: 240, + height: 42, + alignment: Alignment.centerLeft, + child: SlideVerifyWidget( + width: 240, + ), + // child: Row( + // children: [ + // // 输入框 + // Expanded( + // child: _getCustomInputWidget(hint: '请输入右方验证码', hintColor: '#999999', textColor: '#333333', bgColor: '#F7F7F7', iconUrl: null, ) + // ), + // // 第三方验证码 + // Container( + // margin: const EdgeInsets.only(left: 5), + // width: 100, + // height: double.infinity, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(8), + // color: Colors.red + // ), + // ), + // + // ], + // ), + ); + } + + /// 密码输入框 + Widget _getPassInputWidget(LoginStyleModel model) { + return Container( + height: 42, + child: _getCustomInputWidget( + obscureText: true, + keyboardType: TextInputType.text, + controller: _passEdController, + focusNode: _passFN, + onChanged: _onChange, + hint: model?.mobile?.inputPassHintText ?? '请输入您的密码', + iconUrl: model?.mobile?.inputPassIcon ?? '', + hintColor: model?.mobile?.inputHintColor ?? '#999999', + textColor: model?.mobile?.inputTextColor ?? '#333333', + bgColor: model?.mobile?.inputBgColor ?? '#F7F7F7'), + ); + } + + /// 登陆按钮 + Widget _getSubmitBtnWidget(LoginStyleModel model) { + return Material( + child: Container( + height: 52, + width: double.infinity, + color: Colors.white, + child: RaisedButton( + child: Text( + _isLogging ? '登录中...' : model?.mobile?.btnLoginText ?? '立即登录', + style: TextStyle(fontSize: 15), + ), + textColor: HexColor.fromHex(model?.mobile?.btnLoginTextColor ?? '#FFFFFF'), + color: HexColor.fromHex(model?.mobile?.btnLoginBgColor ?? '#FF3939'), + disabledColor: HexColor.fromHex(model?.mobile?.btnLoginBanBgColor ?? '#F5F5F5'), + disabledTextColor: HexColor.fromHex(model?.mobile?.btnLoginBanTextColor ?? '#999999'), + elevation: 5, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(52 / 2)), + onPressed: _canSubmit ? _submitOnClick : null, + ), + ), + ); + } + + /// 协议 + Widget _getProtoclWidget(LoginStyleModel model) { + // return Text('同意《嗨如意用户协议》 及《营私政策》', style: TextStyle(fontSize: 11, color: HexColor.fromHex('#C0C0C0'))); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + /// 图标 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => _agreeOnClick(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: CachedNetworkImage( + imageUrl: _acceptAgreement ? model?.mobile?.protocolSelectIcon ?? '' : model?.mobile?.protocolUnselectIcon ?? '', + width: 12, + ))), + + /// 协议文字 + RichText( + text: TextSpan( + text: '', + children: model.mobile.protocol.map((item) { + return TextSpan( + text: item?.text, + style: TextStyle(color: HexColor.fromHex(item?.textColor), fontSize: 10), + recognizer: TapGestureRecognizer() + ..onTap = () { + _openAgreement(item.url); + }); + }).toList()), + ) + ], + ); + } + + /// 底部提示tip + Widget _getBottomTipWidget(LoginStyleModel model) { + return Padding( + padding: const EdgeInsets.only(bottom: 25), + child: Text( + model?.mobile?.textBottomTip ?? '未注册过的手机将自动注册', + style: TextStyle(fontSize: 11, color: HexColor.fromHex(model?.mobile?.textBottomTipColor ?? '#999999')), + ), + ); + } + + /// 自定义输入框 + Widget _getCustomInputWidget({ + String hint, + String hintColor, + String bgColor, + String textColor, + String iconUrl, + TextEditingController controller, + ValueChanged onChanged, + FocusNode focusNode, + TextInputType keyboardType, + bool obscureText = false, + }) { + var border = OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: HexColor.fromHex(bgColor), width: 0)); + + return Container( + height: 42, + padding: const EdgeInsets.symmetric(horizontal: 15), + decoration: BoxDecoration( + color: HexColor.fromHex(bgColor), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + CachedNetworkImage( + imageUrl: iconUrl ?? '', + width: 10, + ), + Expanded( + child: TextField( + obscureText: obscureText ?? false, + controller: controller, + focusNode: focusNode, + onChanged: onChanged, + expands: false, + style: TextStyle(color: HexColor.fromHex(textColor)), + maxLines: 1, + keyboardType: keyboardType ?? TextInputType.number, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(top: 30, left: 7.5), + hintText: hint, + hintStyle: TextStyle(fontSize: 13, color: HexColor.fromHex(hintColor)), + hintMaxLines: 1, + filled: true, + fillColor: Colors.transparent, + border: border, + focusedBorder: border, + enabledBorder: border, + disabledBorder: border, + errorBorder: border, + focusedErrorBorder: border, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/login_page/bind/login_bind_phone_sk.dart b/lib/pages/login_page/bind/login_bind_phone_sk.dart new file mode 100644 index 0000000..e84e1c3 --- /dev/null +++ b/lib/pages/login_page/bind/login_bind_phone_sk.dart @@ -0,0 +1,61 @@ +import 'package:shimmer/shimmer.dart'; +import 'package:flutter/material.dart'; +import 'package:zhiying_comm/util/extension/color.dart'; + +/// +/// 绑定手机号骨架图 +/// +class LoginBindPhoneSkeleton extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: HexColor.fromHex('#FFFFFF'), + elevation: 0, + title: Text( + '登录', + style: TextStyle(color: HexColor.fromHex('#333333')), + ), + centerTitle: true, + leading: IconButton( + icon: Icon( + Icons.arrow_back_ios, + size: 22, + color: HexColor.fromHex('#333333'), + ), + onPressed: () {}, + ), + ), + body: Container( + padding: const EdgeInsets.symmetric(horizontal: 27.5), + width: double.infinity, + height: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + /// 标题 + Padding(padding: const EdgeInsets.only(top: 40), child: _shimmerWidget(width: 175, height: 20)), + Padding(padding: const EdgeInsets.only(top: 30), child: _shimmerWidget(width: 320, height: 42)), + Padding(padding: const EdgeInsets.only(top: 15), child: _shimmerWidget(width: 320, height: 42)), + Align(alignment: Alignment.center, child: Padding(padding: const EdgeInsets.only(top: 15), child: _shimmerWidget(width: 72, height: 13))), + Padding(padding: const EdgeInsets.only(top: 30), child: _shimmerWidget(width: 320, height: 52.7, radius: 30)), + Align(alignment: Alignment.center, child: Padding(padding: const EdgeInsets.only(top: 12.5), child: _shimmerWidget(width: 220, height: 15))), + Expanded(child: Align(alignment: Alignment.bottomCenter, child: Padding(padding: const EdgeInsets.only(bottom: 25), child: _shimmerWidget(width: 132, height: 15)))) + ], + ), + ), + ); + } + + Widget _shimmerWidget({double width, double height, double radius = 0}) { + return Shimmer.fromColors( + baseColor: Colors.grey[300], + highlightColor: Colors.grey[100], + child: Container( + width: width, + height: height, + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(radius)), + ), + ); + } +} diff --git a/lib/pages/login_page/bind/model/login_bind_phone_user_model.dart b/lib/pages/login_page/bind/model/login_bind_phone_user_model.dart new file mode 100644 index 0000000..22ebffa --- /dev/null +++ b/lib/pages/login_page/bind/model/login_bind_phone_user_model.dart @@ -0,0 +1,30 @@ +class LoginBindPhonUserModel { + String userId; + String nickname; + String appName; + String nickNameColor; + String appNameColor; + String avatar; + + LoginBindPhonUserModel({this.userId, this.nickname, this.appName}); + + LoginBindPhonUserModel.fromJson(Map json) { + userId = json['user_id']?.toString(); + nickname = json['nickname']?.toString(); + appName = json['app_name']?.toString(); + avatar = json['avatar']?.toString(); + appNameColor = json['app_name_color']?.toString(); + nickNameColor = json['nickname_color']?.toString(); + } + + Map toJson() { + final Map data = new Map(); + data['user_id'] = this.userId; + data['nickname'] = this.nickname; + data['app_name'] = this.appName; + data['nickname_color'] = this.nickNameColor; + data['app_name_color'] = this.appNameColor; + data['avatar'] = this.avatar; + return data; + } +} diff --git a/lib/pages/login_page/bloc/login_bloc.dart b/lib/pages/login_page/bloc/login_bloc.dart index c1da81a..0d0c418 100644 --- a/lib/pages/login_page/bloc/login_bloc.dart +++ b/lib/pages/login_page/bloc/login_bloc.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; +import 'package:zhiying_comm/util/global_config.dart'; import './bloc.dart'; import 'login_repository.dart'; import 'package:zhiying_comm/util/empty_util.dart'; @@ -16,23 +17,67 @@ class LoginBloc extends Bloc { Stream mapEventToState( LoginEvent event, ) async* { - // TODO: Add Logic - final currentState = state; - /// 初始化 if (event is LoginInitEvent) { yield* _mapLoginInitEventToState(event); } + + /// 淘宝登录 + if (event is LoginThirdAliEvent) { + yield* _mapLoginAliEventToState(event); + } + + /// 苹果登录 + if (event is LoginThirdAppleEvent) { + yield* _mapLoginAppleEventToState(event); + } + + /// QQ登录 + if (event is LoginThirdQQEvent) { + yield* _mapLoginQQEventToState(event); + } + + /// 微信登录 + if (event is LoginThirdWeChatEvent) { + yield* _mapLoginWeChatEventToState(event); + } } /// 获取页面数据 Stream _mapLoginInitEventToState(LoginInitEvent event) async* { var cache = await repository.fetchCachePageData(); - if (!EmptyUtil.isEmpty(cache)) yield LoginCacheState( model: cache); + if (!EmptyUtil.isEmpty(cache)) yield LoginCacheState(model: cache); var result = await repository.fetchNetPageData(); if (!EmptyUtil.isEmpty(result)) yield LoginLoadedState(model: result); else yield LoginErrorState(); } + + /// 淘宝登录 + Stream _mapLoginAliEventToState(LoginThirdAliEvent event) async* { + var result = await repository.aliLogin( + nick: event.nick, + avatarUrl: event.avatarUrl, + openId: event.openId, + openSid: event.openSid, + topAccessToken: event.topAccessToken, + topAuthCode: event.topAuthCode, + ); + + if(!EmptyUtil.isEmpty(result)){ + yield LoginThirdLoginSuccessState(model: result, thirdType: GlobalConfig.LOGIN_THIRD_ALI); + }else{ + yield LoginThirdLoginErrorState(); + } + } + + /// 微信登录 + Stream _mapLoginWeChatEventToState(LoginThirdWeChatEvent event) async* {} + + /// QQ 登录 + Stream _mapLoginQQEventToState(LoginThirdQQEvent event) async* {} + + /// 苹果登录 + Stream _mapLoginAppleEventToState(LoginThirdAppleEvent event) async* {} } diff --git a/lib/pages/login_page/bloc/login_event.dart b/lib/pages/login_page/bloc/login_event.dart index 7883b15..2a449a8 100644 --- a/lib/pages/login_page/bloc/login_event.dart +++ b/lib/pages/login_page/bloc/login_event.dart @@ -2,9 +2,37 @@ import 'package:equatable/equatable.dart'; abstract class LoginEvent extends Equatable { const LoginEvent(); + @override List get props => []; } /// 初始化 -class LoginInitEvent extends LoginEvent{} +class LoginInitEvent extends LoginEvent {} + +/// 第三方登录: 淘宝登录 +class LoginThirdAliEvent extends LoginEvent { + // 用户昵称 + final String nick; + + // 头像地址 + final String avatarUrl; + final String openId; + final String openSid; + final String topAccessToken; + final String topAuthCode; + + LoginThirdAliEvent({this.nick, this.avatarUrl, this.openId, this.openSid, this.topAccessToken, this.topAuthCode}); + + @override + List get props => [this.nick, this.avatarUrl, this.openId, this.openSid, this.topAccessToken, this.topAuthCode]; +} + +/// 第三方登录:苹果登录 +class LoginThirdAppleEvent extends LoginEvent {} + +/// 第三方登录:微信登录 +class LoginThirdWeChatEvent extends LoginEvent {} + +/// 第三方登录:QQ登录 +class LoginThirdQQEvent extends LoginEvent {} diff --git a/lib/pages/login_page/bloc/login_repository.dart b/lib/pages/login_page/bloc/login_repository.dart index 01ae60a..5fce970 100644 --- a/lib/pages/login_page/bloc/login_repository.dart +++ b/lib/pages/login_page/bloc/login_repository.dart @@ -1,26 +1,59 @@ -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; -import '../login_util.dart'; +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +import '../login_style_util.dart'; class LoginRepository { /// 获取页面数据 - Future fetchNetPageData() async { - // var result = await NetUtil.post('/api/v1/sign/in', method: NetMethod.GET, cache: true); - // if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { - // LoginModel model = LoginModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); - // return model; - // } - // return null; - return await LoginUtil.fetchNetPageData(); + Future fetchNetPageData() async { + return await LoginStyleUtil.fetchNetPageData(); } /// 获取缓存的页面数据 - Future fetchCachePageData() async { - // var result = await NetUtil.getRequestCachedData('/api/v1/sign/in'); - // if (!EmptyUtil.isEmpty(result)) { - // LoginModel model = LoginModel.fromJson(result); - // return model; - // } - // return null; - return await LoginUtil.fetchCachePageData(); + Future fetchCachePageData() async { + return await LoginStyleUtil.fetchCachePageData(); + } + + /// 淘宝登录 + Future aliLogin( + {@required final String nick, @required final String avatarUrl, @required final String openId, final String openSid, final String topAccessToken, final String topAuthCode}) async { + try { + Map params = {}; + params['nick_name'] = nick; + params['avatar_url'] = avatarUrl; + params['open_id'] = openId; + params['access_token'] = topAccessToken; + params['sid'] = openSid; + params['auth_code'] = topAuthCode; + var result = await NetUtil.post( + '/api/v1/sign/fast/in', + queryParameters: {'third_party_login': 'taobao'}, + params: {'taobao': params}, + method: NetMethod.POST, + ); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + return UserInfoModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } + + /// 微信登录 + Future weChatLogin() async { + return null; + } + + /// apple 登录 + Future appleLogin() async { + return null; + } + + /// QQ 登录 + Future qqLogin() async { + return null; } } diff --git a/lib/pages/login_page/bloc/login_state.dart b/lib/pages/login_page/bloc/login_state.dart index 2fd5158..8e59048 100644 --- a/lib/pages/login_page/bloc/login_state.dart +++ b/lib/pages/login_page/bloc/login_state.dart @@ -1,5 +1,7 @@ import 'package:equatable/equatable.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:zhiying_comm/models/user/user_info_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; abstract class LoginState extends Equatable { const LoginState(); @@ -13,19 +15,45 @@ class InitialLoginState extends LoginState {} /// 缓存数据状态 class LoginCacheState extends LoginState { - final LoginModel model; + final LoginStyleModel model; + const LoginCacheState({this.model}); + @override List get props => [this.model]; } /// 数据加载完毕状态 class LoginLoadedState extends LoginState { - final LoginModel model; + final LoginStyleModel model; + const LoginLoadedState({this.model}); + @override List get props => [this.model]; } /// 数据加载出错 class LoginErrorState extends LoginState {} + +/// 第三方登录成功 +class LoginThirdLoginSuccessState extends LoginState { + String thirdType; + UserInfoModel model; + + LoginThirdLoginSuccessState({@required this.model, @required this.thirdType}); + + @override + List get props => [this.model]; +} + +/// 第三方登录失败 +class LoginThirdLoginErrorState extends LoginState { + @override + bool operator ==(Object other) { + return false; + } + + @override + int get hashCode => super.hashCode; +} diff --git a/lib/pages/login_page/invite/bloc/login_invite_bloc.dart b/lib/pages/login_page/invite/bloc/login_invite_bloc.dart index 6a48db1..d3c1dce 100644 --- a/lib/pages/login_page/invite/bloc/login_invite_bloc.dart +++ b/lib/pages/login_page/invite/bloc/login_invite_bloc.dart @@ -53,9 +53,11 @@ class LoginInviteBloc extends Bloc { /// 提交 Stream _mapSubmitEventToState(LoginInviteSubmitEvent event) async* { var data = await repostitory.submitInvite(event); - if (!EmptyUtil.isEmpty(data)) + if (!EmptyUtil.isEmpty(data)) { yield LoginInviteSubmitSuccess(model: data); - else + } else { yield LoginInviteSubmitErrorState(); + yield LoginInviteQuerySuccessState(model: repostitory?.lastInviteUser, pageMdel: repostitory?.pageModel); + } } } diff --git a/lib/pages/login_page/invite/bloc/login_invite_repository.dart b/lib/pages/login_page/invite/bloc/login_invite_repository.dart index 4e70c8a..464da9f 100644 --- a/lib/pages/login_page/invite/bloc/login_invite_repository.dart +++ b/lib/pages/login_page/invite/bloc/login_invite_repository.dart @@ -1,18 +1,20 @@ import 'package:zhiying_comm/pages/login_page/invite/model/login_invite_user.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'package:zhiying_comm/util/net_util.dart'; import 'package:zhiying_comm/util/global_config.dart'; import 'package:zhiying_comm/models/user/user_info_model.dart'; -import '../../login_util.dart'; +import 'package:zhiying_comm/util/log/let_log.dart'; +import '../../login_style_util.dart'; import 'bloc.dart'; class LoginInviteRepository { - LoginModel pageModel; + LoginStyleModel pageModel; + LoginInviteUser lastInviteUser; /// 获取数据,如果缓存有,则获取缓存的数据 - Future fetchData() async { - pageModel = await LoginUtil.getLoginModel(); + Future fetchData() async { + pageModel = await LoginStyleUtil.getLoginModel(); if (!EmptyUtil.isEmpty(pageModel)) { return pageModel; } @@ -21,27 +23,36 @@ class LoginInviteRepository { /// 获取邀请人信息 Future fetchInviteUserInfo(LoginInviteQueryEvent event) async { - var result = await NetUtil.post('/api/v1/user/invite/${event.num}', method: NetMethod.GET); - if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { - LoginInviteUser model = LoginInviteUser.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); - if(null != model) + try { + var result = await NetUtil.post('/api/v1/user/invite/${event.num}', method: NetMethod.GET, showToast: false); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + LoginInviteUser model = LoginInviteUser.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + lastInviteUser = model; return model; - else return null; - } else { - return null; + } + } catch (e, s) { + Logger.error(e, s); } + return null; } /// 提交 Future submitInvite(LoginInviteSubmitEvent event) async { - var result = await NetUtil.post('/api/v1/user/invite/ack', params: {'mobile': event.mobile, 'parent_uid': event.num}); - if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { - UserInfoModel model = UserInfoModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); - if (null != model) { - model.mobile = event.mobile; - return model; + try { + var result = await NetUtil.post('/api/v1/user/invite/ack', params: { + 'mobile': event.mobile, + 'zone': '86', + 'parent_uid': event.num, + }); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + UserInfoModel model = UserInfoModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + if (null != model) { + model.mobile = event.mobile; + return model; + } } - return null; + } catch (e, s) { + Logger.error(e, s); } return null; } diff --git a/lib/pages/login_page/invite/bloc/login_invite_state.dart b/lib/pages/login_page/invite/bloc/login_invite_state.dart index 241f18d..831ae85 100644 --- a/lib/pages/login_page/invite/bloc/login_invite_state.dart +++ b/lib/pages/login_page/invite/bloc/login_invite_state.dart @@ -2,7 +2,7 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/cupertino.dart'; import 'package:zhiying_comm/models/user/user_info_model.dart'; import 'package:zhiying_comm/pages/login_page/invite/model/login_invite_user.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; abstract class LoginInviteState extends Equatable { const LoginInviteState(); @@ -16,7 +16,7 @@ class LoginInviteInitial extends LoginInviteState {} /// 数据加载完毕状态 class LoginInviteLoadedState extends LoginInviteState { - final LoginModel model; + final LoginStyleModel model; const LoginInviteLoadedState({@required this.model}); @@ -46,18 +46,19 @@ class LoginInviteSubmitSuccess extends LoginInviteState { /// 邀请码失败 class LoginInviteSubmitErrorState extends LoginInviteState { - final String msg; - - const LoginInviteSubmitErrorState({this.msg}); + @override + bool operator ==(Object other) { + return false; + } @override - List get props => [this.msg]; + int get hashCode => super.hashCode; } /// 查询邀请人成功 class LoginInviteQuerySuccessState extends LoginInviteState { final LoginInviteUser model; - final LoginModel pageMdel; + final LoginStyleModel pageMdel; const LoginInviteQuerySuccessState({@required this.model, @required this.pageMdel}); diff --git a/lib/pages/login_page/invite/login_invite_page.dart b/lib/pages/login_page/invite/login_invite_page.dart index adbf0f1..ce166cb 100644 --- a/lib/pages/login_page/invite/login_invite_page.dart +++ b/lib/pages/login_page/invite/login_invite_page.dart @@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'package:zhiying_comm/util/mob_util/mob_util.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; @@ -39,7 +39,6 @@ class _LoginInvitePageContainerState extends State { TextEditingController _editingController; FocusNode _focusNode; bool _showInviteInfo = false; - // 是否登录中 bool _isLogging = false; @@ -80,14 +79,19 @@ class _LoginInvitePageContainerState extends State { void _submitOnClick(LoginInviteUser inviteUser) async { _focusNode.unfocus(); - /// 邀请码 - String inviteNum = inviteUser?.userId ?? ''; - - /// 手机号 - UserInfoModel model = await Provider.of(context, listen: false)?.getUserInfoModel(); - String mobile = model?.mobile ?? ''; - if (!EmptyUtil.isEmpty(inviteNum) && !EmptyUtil.isEmpty(mobile)) { - BlocProvider.of(context).add(LoginInviteSubmitEvent(mobile: mobile, num: inviteNum)); + if (!_isLogging) { + /// 邀请码 + String inviteNum = inviteUser?.userId ?? ''; + + /// 手机号 + UserInfoModel model = await Provider.of(context, listen: false)?.getUserInfoModel(); + String mobile = model?.mobile ?? ''; + if (!EmptyUtil.isEmpty(inviteNum) && !EmptyUtil.isEmpty(mobile)) { + setState(() { + _isLogging = true; + }); + BlocProvider.of(context).add(LoginInviteSubmitEvent(mobile: mobile, num: inviteNum)); + } } } @@ -125,6 +129,7 @@ class _LoginInvitePageContainerState extends State { buildWhen: (previous, current) { /// 提交失败 if (current is LoginInviteSubmitErrorState) { + _isLogging = false; return false; } @@ -169,7 +174,7 @@ class _LoginInvitePageContainerState extends State { } /// 主视图 - Widget _getMainWidget(LoginModel model, LoginInviteUser inviteUser) { + Widget _getMainWidget(LoginStyleModel model, LoginInviteUser inviteUser) { return Column( children: [ /// appbar @@ -191,7 +196,7 @@ class _LoginInvitePageContainerState extends State { } /// appBar - Widget _getAppBar(LoginModel model) { + Widget _getAppBar(LoginStyleModel model) { return AppBar( brightness: Brightness.light, backgroundColor: HexColor.fromHex('#FFFFFF'), @@ -213,7 +218,7 @@ class _LoginInvitePageContainerState extends State { } /// title - Widget _getTitleWidget(LoginModel model) { + Widget _getTitleWidget(LoginStyleModel model) { return Align( alignment: Alignment.centerLeft, child: Text( @@ -223,7 +228,7 @@ class _LoginInvitePageContainerState extends State { } /// 邀请码输入框 - Widget _getInviteInputWidget(LoginModel model) { + Widget _getInviteInputWidget(LoginStyleModel model) { return _getCustomInputWidget( hint: model?.invite?.inputInviteText ?? '请输入邀请码', controller: _editingController, @@ -276,7 +281,7 @@ class _LoginInvitePageContainerState extends State { } /// 按钮 - Widget _getSubmiBtnWidget(LoginModel model, LoginInviteUser inviteUser) { + Widget _getSubmiBtnWidget(LoginStyleModel model, LoginInviteUser inviteUser) { return Material( child: Container( height: 52, @@ -284,7 +289,7 @@ class _LoginInvitePageContainerState extends State { color: Colors.white, child: RaisedButton( child: Text( - model?.invite?.btnSubmitText ?? '进入智莺生活', + _isLogging ? '进入...' : model?.invite?.btnSubmitText ?? '进入智莺生活', style: TextStyle(fontSize: 15), ), textColor: HexColor.fromHex(model?.invite?.btnSubmitTextColor ?? '#FFFFFF'), diff --git a/lib/pages/login_page/login_page.dart b/lib/pages/login_page/login_page.dart index cd1c674..c3b2175 100644 --- a/lib/pages/login_page/login_page.dart +++ b/lib/pages/login_page/login_page.dart @@ -2,16 +2,22 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_alibc/alibc_model.dart'; +import 'package:flutter_alibc/flutter_alibc.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:zhiying_comm/pages/login_page/account/login_account_page.dart'; +import 'package:zhiying_comm/pages/login_page/bind/login_bind_phone_page.dart'; +import 'package:zhiying_comm/util/dialog/loading/loading.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'package:zhiying_comm/util/mob_util/mob_util.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; +import 'package:provider/provider.dart'; import 'bloc/bloc.dart'; import 'bloc/login_repository.dart'; import 'login_page_sk.dart'; -import 'model/login_model.dart'; +import 'model/login_style_model.dart'; /// /// 登陆页面 @@ -37,13 +43,15 @@ class LoginPageContainer extends StatefulWidget { } class _LoginPageContainerState extends State { + LoginModel _taoBao; + /// 微信or手机登陆 - void _loginClick(String type, LoginModel model) { + void _loginClick(String type, LoginStyleModel model) { print('登陆$type'); RouterUtil.hideKeyboard(context); if (type == 'mobile') { if (model?.flashLoginEnable == '1') { - // QuickLoginUtil.getInstance().openQuickLogin(context, model?.quick); + // mob 一键登录 MobUtil.openQuickLoginPage(context, model?.quick); } else { Navigator.push(context, CupertinoPageRoute(builder: (_) => LoginAccountPage(null))); @@ -51,16 +59,48 @@ class _LoginPageContainerState extends State { } } - /// 返回上一页 - void _openPop() { - if (Navigator.canPop(context)) { - Navigator.pop(context); - } - } - /// 第三方登陆 - void _otherLoginClick(BottomIcons model) { + void _otherLoginClick(BottomIcons model) async { print('第三方登陆${model.type}'); + if (EmptyUtil.isEmpty(model) || EmptyUtil.isEmpty(model.type)) { + Fluttertoast.showToast(msg: '暂不支持~'); + return; + } + Loading.show(context); + + /// 淘宝登录 + if ('taobao' == model.type) { + _taoBao = await FlutterAlibc.loginTaoBao(); + if (!EmptyUtil.isEmpty(_taoBao) && !EmptyUtil.isEmpty(_taoBao?.errorCode) && _taoBao.errorCode == '0') { + BlocProvider.of(context).add(LoginThirdAliEvent( + nick: _taoBao?.data?.nick, + avatarUrl: _taoBao?.data?.avatarUrl, + openId: _taoBao?.data?.openId, + openSid: _taoBao?.data?.openSid, + topAccessToken: _taoBao?.data?.topAccessToken, + topAuthCode: _taoBao?.data?.topAuthCode)); + // Logger.warn(' tao login = ${taoBao?.errorCode} , msg = ${taoBao?.errorMessage}, nick = ${taoBao?.data?.nick}, ' + // 'avatar = ${taoBao?.data?.avatarUrl}, openId = ${taoBao?.data?.openId}, openSid = ${taoBao?.data?.openSid}, ' + // 'topAccessToken = ${taoBao?.data?.topAccessToken}, topAuthCode = ${taoBao?.data?.topAuthCode}'); + } + } + + /// QQ登录 + if ('qq' == model.type) { + Fluttertoast.showToast(msg: '暂不支持~'); + } + + /// 微信登录 + if ('wechat' == model.type) { + Fluttertoast.showToast(msg: '暂不支持~'); + } + + /// 苹果登录 + if ('apple' == model.type) { + Fluttertoast.showToast(msg: '暂不支持~'); + } + + Loading.dismiss(); } /// 跳到用户协议 @@ -71,8 +111,32 @@ class _LoginPageContainerState extends State { } } + /// 跳到绑定手机号 + void _jumpBindPhonePage(String thirdType) { + /// 如果是淘宝登录 + if (GlobalConfig.LOGIN_THIRD_ALI == thirdType) { + Navigator.push( + context, + CupertinoPageRoute( + builder: (_) => LoginBindPhonePage({ + 'thirdType': thirdType, + 'nick': _taoBao?.data?.nick, + 'avatarUrl': _taoBao?.data?.avatarUrl, + 'openId': _taoBao?.data?.openId, + 'openSid': _taoBao?.data?.openSid, + 'topAccessToken': _taoBao?.data?.topAccessToken, + 'topAuthCode': _taoBao?.data?.topAuthCode, + }))); + } + } + + /// 跳到首页 + void _jumpHomePage() { + RouterUtil.goBackHomePage(context); + } + /// 展开关闭其它登陆 - void _showOrColoseOtherLogin() { + void _showOrCloseOtherLogin() { setState(() { _showOther = !_showOther; }); @@ -94,6 +158,28 @@ class _LoginPageContainerState extends State { if (current is LoginErrorState) { return false; } + + /// 登录失败 + if (current is LoginThirdLoginErrorState) { + return false; + } + + /// 登录成功 + if (current is LoginThirdLoginSuccessState) { + // 需要绑定手机号 + if (current.model.bindPhoneEnable == '1') { + // 打开绑定手机号页面 + _jumpBindPhonePage(current.thirdType); + } else { + // 更新登录数据 + Provider.of(context, listen: false)?.setUserInfo(current.model); + // 直接打开首页 + _jumpHomePage(); + Fluttertoast.showToast(msg: '登录成功~'); + } + return false; + } + return true; }, builder: (context, state) { @@ -109,7 +195,7 @@ class _LoginPageContainerState extends State { } /// 主视图 - Widget _getMainWidget(LoginModel model) { + Widget _getMainWidget(LoginStyleModel model) { return Column( children: [ /// 头部 @@ -130,7 +216,7 @@ class _LoginPageContainerState extends State { } /// 头部Widget - Widget _headWidget(LoginModel model) { + Widget _headWidget(LoginStyleModel model) { return Container( height: 228 + MediaQuery.of(context).padding.top, width: double.infinity, @@ -152,7 +238,7 @@ class _LoginPageContainerState extends State { size: 22, color: HexColor.fromHex('#333333'), ), - onPressed: () => _openPop(), + onPressed: () => Navigator.maybePop(context), ), ), Column( @@ -187,7 +273,7 @@ class _LoginPageContainerState extends State { } /// 按钮 - Widget _buttonsWidget(LoginModel model) { + Widget _buttonsWidget(LoginStyleModel model) { return Container( padding: const EdgeInsets.symmetric(horizontal: 27.5), child: Column( @@ -209,7 +295,7 @@ class _LoginPageContainerState extends State { } /// 协议 - Widget _protocolWidget(LoginModel model) { + Widget _protocolWidget(LoginStyleModel model) { return RichText( text: TextSpan( text: '', @@ -226,7 +312,7 @@ class _LoginPageContainerState extends State { } /// 其它登陆方式 - Widget _otherLoginWidget(LoginModel model) { + Widget _otherLoginWidget(LoginStyleModel model) { return Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.end, @@ -241,10 +327,10 @@ class _LoginPageContainerState extends State { } /// 其它登陆方式的title - Widget _getOtherLoginTitle(LoginModel model) { + Widget _getOtherLoginTitle(LoginStyleModel model) { return GestureDetector( behavior: HitTestBehavior.opaque, - onTap: () => _showOrColoseOtherLogin(), + onTap: () => _showOrCloseOtherLogin(), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -261,7 +347,7 @@ class _LoginPageContainerState extends State { } /// 其它登陆方式的按钮 - Widget _getOtherLoginIcons(LoginModel model) { + Widget _getOtherLoginIcons(LoginStyleModel model) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: model.main.bottomIcons.map((item) { diff --git a/lib/pages/login_page/login_util.dart b/lib/pages/login_page/login_style_util.dart similarity index 75% rename from lib/pages/login_page/login_util.dart rename to lib/pages/login_page/login_style_util.dart index 6418fb2..bb7c3fc 100644 --- a/lib/pages/login_page/login_util.dart +++ b/lib/pages/login_page/login_style_util.dart @@ -3,10 +3,10 @@ import 'package:zhiying_comm/util/shared_prefe_util.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'package:zhiying_comm/util/global_config.dart'; -import 'model/login_model.dart'; +import 'model/login_style_model.dart'; /// 登陆数据管理工具类 -class LoginUtil { +class LoginStyleUtil { static final String _URL = '/api/v1/sign/in'; static void init() async { @@ -17,7 +17,7 @@ class LoginUtil { } /// 获取数据 - static Future getLoginModel() async { + static Future getLoginModel() async { var cache = await fetchCachePageData(); if (!EmptyUtil.isEmpty(cache)) return cache; var result = await fetchNetPageData(); @@ -32,20 +32,20 @@ class LoginUtil { } /// 获取缓存的页面数据 - static Future fetchCachePageData() async { + static Future fetchCachePageData() async { var result = await NetUtil.getRequestCachedData(_URL); if (!EmptyUtil.isEmpty(result)) { - LoginModel model = LoginModel.fromJson(result); + LoginStyleModel model = LoginStyleModel.fromJson(result); return model; } return null; } /// 获取页面数据 - static Future fetchNetPageData() async { + static Future fetchNetPageData() async { var result = await NetUtil.post(_URL, method: NetMethod.GET, cache: true); if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { - LoginModel model = LoginModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + LoginStyleModel model = LoginStyleModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); return model; } return null; diff --git a/lib/pages/login_page/model/login_model.dart b/lib/pages/login_page/model/login_style_model.dart similarity index 86% rename from lib/pages/login_page/model/login_model.dart rename to lib/pages/login_page/model/login_style_model.dart index 600520d..4926ec0 100644 --- a/lib/pages/login_page/model/login_model.dart +++ b/lib/pages/login_page/model/login_style_model.dart @@ -5,32 +5,36 @@ /// invite : {"app_bar_title":"登陆","app_bar_title_color":"#333333","app_bar_bg_color":"#FFFFFF","title":"输入邀请码","title_color":"#333333","input_hint_color":"#999999","input_bg_color":"#F7F7F7","btn_ban_bg_color":"#F5F5F5","btn_ban_text_color":"#999999","input_invite_icon":"http://xxxx","input_invite_text":"请输入邀请码","input_invite_text_color":"#999999","btn_submit_text":"进入智莺生活","btn_submit_text_color":"#FFFFFF","btn_submit_bg_color":"#FF3939","btn_submit_shadow_color":"#FF0000"} /// quick : {"app_bar_title":"","app_bar_bg_color":"","app_bar_title_color":"#FFFFFF","account_color":"#333333","text_tip":"切换账号","text_tip_color":"#FF3939","btn_submit_text":"立即登录","btn_submit_text_color":"#FFFFFF","btn_submit_bg_color":"#FF3939","btn_submit_shadow_color":"#FF0000","protocol_select_icon":"http://xxxx","protocol_unselect_icon":"http://xxxxx","text_bottom_tip":"中国电信提供认证服务","text_bottom_tip_color":"#C0C0C0","protocol":[{"text":"同意","text_color":"#C0C0C0","url":""},{"text":"《智莺生活用户协议》","text_color":"#FF3939","url":"http://www.hairuyi.com/?mod=appapi&act=privacy&ctrl=index&type=protocol"},{"text":"及","text_color":"#C0C0C0","url":""},{"text":"《隐私政策》","text_color":"#FF3939","url":"http://www.hairuyi.com/?mod=appapi&act=privacy&ctrl=index&type=privacyPolicy"}]} /// flash_login_enable : "1" -class LoginModel { +class LoginStyleModel { + // 返回图标 String backImg; + + // logo String logoImg; + + // 登录首页的UI Main main; + + // 手机绑定 Mobile mobile; + + // 邀请好友页面 Invite invite; + + // 一键登录 Quick quick; + + // 是否需要填写邀请码 String flashLoginEnable; - LoginModel( - {this.backImg, - this.logoImg, - this.main, - this.mobile, - this.invite, - this.quick, - this.flashLoginEnable}); + LoginStyleModel({this.backImg, this.logoImg, this.main, this.mobile, this.invite, this.quick, this.flashLoginEnable}); - LoginModel.fromJson(Map json) { + LoginStyleModel.fromJson(Map json) { backImg = json['back_img']; logoImg = json['logo_img']; main = json['main'] != null ? new Main.fromJson(json['main']) : null; - mobile = - json['mobile'] != null ? new Mobile.fromJson(json['mobile']) : null; - invite = - json['invite'] != null ? new Invite.fromJson(json['invite']) : null; + mobile = json['mobile'] != null ? new Mobile.fromJson(json['mobile']) : null; + invite = json['invite'] != null ? new Invite.fromJson(json['invite']) : null; quick = json['quick'] != null ? new Quick.fromJson(json['quick']) : null; flashLoginEnable = json['flash_login_enable']; } @@ -71,16 +75,16 @@ class Main { Main( {this.appBarTitle, - this.appBarTitleColor, - this.appBarBgColor, - this.appNameImg, - this.backgroundImg, - this.agreements, - this.importanceLogin, - this.otherIconsTitle, - this.otherIconsTitleColor, - this.otherExpansionIcon, - this.bottomIcons}); + this.appBarTitleColor, + this.appBarBgColor, + this.appNameImg, + this.backgroundImg, + this.agreements, + this.importanceLogin, + this.otherIconsTitle, + this.otherIconsTitleColor, + this.otherExpansionIcon, + this.bottomIcons}); Main.fromJson(Map json) { appBarTitle = json['app_bar_title']; @@ -122,8 +126,7 @@ class Main { data['agreements'] = this.agreements.map((v) => v.toJson()).toList(); } if (this.importanceLogin != null) { - data['importance_login'] = - this.importanceLogin.map((v) => v.toJson()).toList(); + data['importance_login'] = this.importanceLogin.map((v) => v.toJson()).toList(); } data['other_icons_title'] = this.otherIconsTitle; data['other_icons_title_color'] = this.otherIconsTitleColor; @@ -165,13 +168,7 @@ class ImportanceLogin { String btnBgColor; String btnMobileIcon; - ImportanceLogin( - {this.type, - this.btnText, - this.btnTextColor, - this.btnBorderColor, - this.btnBgColor, - this.btnMobileIcon}); + ImportanceLogin({this.type, this.btnText, this.btnTextColor, this.btnBorderColor, this.btnBgColor, this.btnMobileIcon}); ImportanceLogin.fromJson(Map json) { type = json['type']; @@ -252,44 +249,50 @@ class Mobile { String protocolUnselectIcon; List protocol; - Mobile( - {this.vcodeTime, - this.appBarTitle, - this.appBarTitleColor, - this.appBarBgColor, - this.title, - this.titleColor, - this.inputHintColor, - this.inputTextColor, - this.inputBgColor, - this.inputMobileIcon, - this.inputMobileHintText, - this.inputVcodeIcon, - this.inputVcodeHintText, - this.inputOtherCodeIcon, - this.inputOtherCodeIconText, - this.inputPassIcon, - this.inputPassHintText, - this.btnLoginText, - this.btnLoginTextColor, - this.btnLoginBgColor, - this.btnLoginShadowColor, - this.btnLoginBanBgColor, - this.btnLoginBanTextColor, - this.btnVcodeText, - this.btnVcodeTextColor, - this.btnVcodeBgColor, - this.btnVcodeBanTextColor, - this.btnVcodeBanBgColor, - this.textUsePassTip, - this.textUseVcodeTip, - this.textUsePassTipColor, - this.textUseVcodeTipColor, - this.textBottomTip, - this.textBottomTipColor, - this.protocolSelectIcon, - this.protocolUnselectIcon, - this.protocol}); + String thirdPartyLoginTitle; + String thirdPartyLoginAppBarTitle; + + Mobile({ + this.vcodeTime, + this.appBarTitle, + this.appBarTitleColor, + this.appBarBgColor, + this.title, + this.titleColor, + this.inputHintColor, + this.inputTextColor, + this.inputBgColor, + this.inputMobileIcon, + this.inputMobileHintText, + this.inputVcodeIcon, + this.inputVcodeHintText, + this.inputOtherCodeIcon, + this.inputOtherCodeIconText, + this.inputPassIcon, + this.inputPassHintText, + this.btnLoginText, + this.btnLoginTextColor, + this.btnLoginBgColor, + this.btnLoginShadowColor, + this.btnLoginBanBgColor, + this.btnLoginBanTextColor, + this.btnVcodeText, + this.btnVcodeTextColor, + this.btnVcodeBgColor, + this.btnVcodeBanTextColor, + this.btnVcodeBanBgColor, + this.textUsePassTip, + this.textUseVcodeTip, + this.textUsePassTipColor, + this.textUseVcodeTipColor, + this.textBottomTip, + this.textBottomTipColor, + this.protocolSelectIcon, + this.protocolUnselectIcon, + this.protocol, + this.thirdPartyLoginAppBarTitle, + this.thirdPartyLoginTitle, + }); Mobile.fromJson(Map json) { vcodeTime = json['vcode_time']; @@ -328,6 +331,8 @@ class Mobile { textBottomTipColor = json['text_bottom_tip_color']; protocolSelectIcon = json['protocol_select_icon']; protocolUnselectIcon = json['protocol_unselect_icon']; + thirdPartyLoginAppBarTitle = json['third_party_login_app_bar_title']; + thirdPartyLoginTitle = json['third_party_login_title']; if (json['protocol'] != null) { protocol = new List(); json['protocol'].forEach((v) { @@ -339,6 +344,8 @@ class Mobile { Map toJson() { final Map data = new Map(); data['vcode_time'] = this.vcodeTime; + data['third_party_login_app_bar_title'] = this.thirdPartyLoginAppBarTitle; + data['third_party_login_title'] = this.thirdPartyLoginTitle; data['app_bar_title'] = this.appBarTitle; data['app_bar_title_color'] = this.appBarTitleColor; data['app_bar_bg_color'] = this.appBarBgColor; @@ -401,21 +408,21 @@ class Invite { Invite( {this.appBarTitle, - this.appBarTitleColor, - this.appBarBgColor, - this.title, - this.titleColor, - this.inputHintColor, - this.inputBgColor, - this.btnBanBgColor, - this.btnBanTextColor, - this.inputInviteIcon, - this.inputInviteText, - this.inputInviteTextColor, - this.btnSubmitText, - this.btnSubmitTextColor, - this.btnSubmitBgColor, - this.btnSubmitShadowColor}); + this.appBarTitleColor, + this.appBarBgColor, + this.title, + this.titleColor, + this.inputHintColor, + this.inputBgColor, + this.btnBanBgColor, + this.btnBanTextColor, + this.inputInviteIcon, + this.inputInviteText, + this.inputInviteTextColor, + this.btnSubmitText, + this.btnSubmitTextColor, + this.btnSubmitBgColor, + this.btnSubmitShadowColor}); Invite.fromJson(Map json) { appBarTitle = json['app_bar_title']; @@ -477,20 +484,20 @@ class Quick { Quick( {this.appBarTitle, - this.appBarBgColor, - this.appBarTitleColor, - this.accountColor, - this.textTip, - this.textTipColor, - this.btnSubmitText, - this.btnSubmitTextColor, - this.btnSubmitBgColor, - this.btnSubmitShadowColor, - this.protocolSelectIcon, - this.protocolUnselectIcon, - this.textBottomTip, - this.textBottomTipColor, - this.protocol}); + this.appBarBgColor, + this.appBarTitleColor, + this.accountColor, + this.textTip, + this.textTipColor, + this.btnSubmitText, + this.btnSubmitTextColor, + this.btnSubmitBgColor, + this.btnSubmitShadowColor, + this.protocolSelectIcon, + this.protocolUnselectIcon, + this.textBottomTip, + this.textBottomTipColor, + this.protocol}); Quick.fromJson(Map json) { appBarTitle = json['app_bar_title']; diff --git a/lib/util/global_config.dart b/lib/util/global_config.dart index acb3aae..73089eb 100644 --- a/lib/util/global_config.dart +++ b/lib/util/global_config.dart @@ -10,6 +10,12 @@ class GlobalConfig { /// 通用标志key static final String SKIP_IDENTIFIER = 'skip_identifier'; + /// ====================== 第三方登录key ====================== /// + static const String LOGIN_THIRD_ALI = 'taobao'; // 淘宝登录 + static const String LOGIN_THIRD_WECHAT = 'wechat'; // 微信 + static const String LOGIN_THIRD_QQ = 'qq'; // QQ + static const String LOGIN_THIRD_APPLE = 'apple'; // 苹果登录 + /// ====================== 各个渠道的key ====================== /// static const String PROVIDER_TB = 'taobao'; // 淘宝 static const String PROVIDER_TM = 'tianmao'; // 天猫 @@ -35,7 +41,4 @@ class GlobalConfig { /// 货币类型 static final String MONEY_TYPE = "¥ "; -// /// 天猫 淘宝类型 -// static final String PROVIDER_TM = 'tianmao'; -// static final String PROVIDER_TB = 'taobao'; } diff --git a/lib/util/mob_util/mob_util.dart b/lib/util/mob_util/mob_util.dart index 114146c..a8a2792 100644 --- a/lib/util/mob_util/mob_util.dart +++ b/lib/util/mob_util/mob_util.dart @@ -1,6 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:mobsms/mobsms.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'package:zhiying_comm/util/enum_util.dart'; import 'package:zhiying_comm/util/global_config.dart'; diff --git a/lib/util/mob_util/secverify/quick_login_util.dart b/lib/util/mob_util/secverify/quick_login_util.dart index bd5db20..750bf12 100644 --- a/lib/util/mob_util/secverify/quick_login_util.dart +++ b/lib/util/mob_util/secverify/quick_login_util.dart @@ -7,7 +7,7 @@ import 'package:zhiying_comm/models/user/user_info_model.dart'; import 'package:zhiying_comm/models/user/user_info_model_notifier.dart'; import 'package:zhiying_comm/pages/login_page/account/login_account_page.dart'; import 'package:zhiying_comm/pages/login_page/invite/login_invite_page.dart'; -import 'package:zhiying_comm/pages/login_page/model/login_model.dart'; +import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'package:zhiying_comm/util/global_config.dart'; import 'package:zhiying_comm/util/log/let_log.dart'; diff --git a/lib/util/net_util.dart b/lib/util/net_util.dart index cfd40ca..82c3f6a 100644 --- a/lib/util/net_util.dart +++ b/lib/util/net_util.dart @@ -145,7 +145,10 @@ class NetUtil { } } - // 退出登陆 + /// + /// 401003 用户被逼下线 + /// 退出登陆(清理token等用户信息) + /// if (result[GlobalConfig.HTTP_RESPONSE_KEY_CODE]?.toString() == '401003') { try { Future.delayed(Duration(seconds: 0)).then((onValue) { @@ -178,7 +181,7 @@ class NetUtil { } try { - Map result = await NetUtil.post(path, method: method, params: params, queryParameters: queryParameters, showToast: showToast); + Map result = await NetUtil.post(path, method: method, params: params, queryParameters: queryParameters, showToast: showToast, cache: onCache != null); // TODO 解密? if (isSuccess(result)) { if (onSuccess != null) { @@ -323,7 +326,7 @@ class NetUtil { // 站长ID String masterId = setting['master_id']; if (null != masterId && masterId != '' && (!params.containsKey('master_id') || params['master_id'] == '')) { - params['master_id'] = masterId ?? 'template_database'; + params['master_id'] = masterId; //!EmptyUtil.isEmpty(masterId) ? masterId : 'template_database'; } // token 读取SP缓存中的用户token