@@ -10,20 +10,22 @@ class UserInfoModel { | |||
String username; | |||
List<String> 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<String, dynamic> json) { | |||
token = json['token']; | |||
userId = json['user_id']; | |||
username = json['username']; | |||
mobile = json['mobile']; | |||
perms = json['perms']?.cast<String>(); | |||
registerInviteCodeEnable = json['register_invite_code_enable']; | |||
bindPhoneEnable= json['bind_phone_enable']; | |||
perms = json['perms']?.cast<String>(); | |||
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; | |||
} | |||
@@ -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(); | |||
} | |||
@@ -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<LoginModel> fetchData() async { | |||
var result = await LoginUtil.getLoginModel(); | |||
Future<LoginStyleModel> fetchData() async { | |||
var result = await LoginStyleUtil.getLoginModel(); | |||
if (!EmptyUtil.isEmpty(result)) { | |||
return result; | |||
} | |||
@@ -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}); | |||
} | |||
@override | |||
int get hashCode => super.hashCode; | |||
} |
@@ -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<LoginAccountPageContianer> i | |||
FocusNode _phoneFN; | |||
FocusNode _passFN; | |||
FocusNode _vcodeFN; | |||
// 是否登录中 | |||
bool _isLogging = false; | |||
@@ -88,11 +89,13 @@ class _LoginAccountPageContianerState extends State<LoginAccountPageContianer> i | |||
_isLogging = true; | |||
}); | |||
if (_useVcode) { | |||
BlocProvider.of<LoginAccountBloc>(context).add(LoginAccountTypeVcodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? '', captcha: _vcodeEdController?.text?.toString()?.trim() ?? '')); | |||
BlocProvider.of<LoginAccountBloc>(context) | |||
.add(LoginAccountTypeVcodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? '', captcha: _vcodeEdController?.text?.toString()?.trim() ?? '')); | |||
} else { | |||
BlocProvider.of<LoginAccountBloc>(context).add(LoginAccountTypePasswordEvent(username: _phoneEdController?.text?.toString()?.trim() ?? '', password: _passEdController?.text?.toString()?.trim() ?? '')); | |||
BlocProvider.of<LoginAccountBloc>(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<LoginAccountPageContianer> i | |||
Provider.of<UserInfoNotifier>(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<LoginAccountPageContianer> i | |||
} | |||
/// 主页面 | |||
Widget _getMainWidget(LoginModel model) { | |||
Widget _getMainWidget(LoginStyleModel model) { | |||
print(model); | |||
return Column( | |||
children: <Widget>[ | |||
@@ -348,7 +352,7 @@ class _LoginAccountPageContianerState extends State<LoginAccountPageContianer> 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<LoginAccountPageContianer> 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<LoginAccountPageContianer> 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<LoginAccountPageContianer> i | |||
} | |||
/// 验证码输入框 | |||
Widget _getVcodeWidget(LoginModel model) { | |||
Widget _getVcodeWidget(LoginStyleModel model) { | |||
return Container( | |||
height: 42, | |||
child: Stack( | |||
@@ -414,7 +418,7 @@ class _LoginAccountPageContianerState extends State<LoginAccountPageContianer> 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<LoginAccountPageContianer> 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<LoginAccountPageContianer> 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<LoginAccountPageContianer> i | |||
} | |||
/// 登陆按钮 | |||
Widget _getSubmiBtnWidget(LoginModel model) { | |||
Widget _getSubmiBtnWidget(LoginStyleModel model) { | |||
return Material( | |||
child: Container( | |||
height: 52, | |||
@@ -512,7 +516,7 @@ class _LoginAccountPageContianerState extends State<LoginAccountPageContianer> 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<LoginAccountPageContianer> 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<LoginAccountPageContianer> 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, | |||
@@ -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'; |
@@ -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<LoginBindPhoneEvent, LoginBindPhoneState> { | |||
LoginBindPhoneRepository repository; | |||
LoginBindPhoneBloc({@required this.repository}); | |||
@override | |||
LoginBindPhoneState get initialState => LoginBindPhoneInitial(); | |||
@override | |||
Stream<LoginBindPhoneState> 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<LoginBindPhoneState> _mapInitEventToState() async* { | |||
var data = await repository.fetchData(); | |||
if (!EmptyUtil.isEmpty(data)) | |||
yield LoginBindPhoneLoadedState(model: data); | |||
else | |||
yield LoginBindPhoneErrorState(); | |||
} | |||
/// 获取验证码 | |||
Stream<LoginBindPhoneState> _mapGetVcodeEventToState(LoginBindPhoneGetVCodeEvent event) async* { | |||
bool result = await repository.fetchGetVcode(event); | |||
if (result) | |||
yield LoginBindPhoneGetVCodeSuccessState(); | |||
else | |||
yield LoginBindPhoneGetVCodeErrorState(); | |||
} | |||
/// 验证码登陆 | |||
Stream<LoginBindPhoneState> _mapLoginTypeVcodeEventToState(LoginBindPhoneTypeVCodeEvent event) async* { | |||
var result = await repository.loginTypeVCode(event); | |||
if (!EmptyUtil.isEmpty(result)) | |||
yield LoginBindPhoneLoginSuccessState(model: result); | |||
else | |||
yield LoginBindPhoneLoginErrorState(); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
import 'package:equatable/equatable.dart'; | |||
import 'package:flutter/cupertino.dart'; | |||
abstract class LoginBindPhoneEvent extends Equatable { | |||
const LoginBindPhoneEvent(); | |||
@override | |||
List<Object> get props => []; | |||
} | |||
/// 初始化事件 | |||
class LoginBindPhoneInitEvent extends LoginBindPhoneEvent {} | |||
/// 获取验证码 | |||
class LoginBindPhoneGetVCodeEvent extends LoginBindPhoneEvent { | |||
final String mobile; | |||
const LoginBindPhoneGetVCodeEvent({@required this.mobile}); | |||
@override | |||
List<Object> get props => [mobile]; | |||
} | |||
/// 核对验证码 | |||
class LoginBindPhoneCheckVCodeEvent extends LoginBindPhoneEvent { | |||
/// 手机号码 | |||
final String mobile; | |||
/// 验证码 | |||
final String captcha; | |||
const LoginBindPhoneCheckVCodeEvent({@required this.mobile, @required this.captcha}); | |||
@override | |||
List<Object> 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<Object> get props => [this.mobile, this.captcha]; | |||
} |
@@ -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<String, dynamic> data; | |||
LoginBindPhoneRepository(this.data); | |||
/// 获取数据,如果缓存有,则获取缓存的数据 | |||
Future<LoginStyleModel> fetchData() async { | |||
var result = await LoginStyleUtil.getLoginModel(); | |||
if (!EmptyUtil.isEmpty(result)) { | |||
return result; | |||
} | |||
return null; | |||
} | |||
/// 获取验证码 | |||
Future<bool> fetchGetVcode(LoginBindPhoneGetVCodeEvent event) async { | |||
print('mobile = ${event.mobile}'); | |||
var result = await MobUtil.getTextCode(event?.mobile, smsCodeType: SMSCodeType.AUTO); | |||
return result; | |||
} | |||
/// 验证码登陆 | |||
Future<UserInfoModel> loginTypeVCode(LoginBindPhoneTypeVCodeEvent event) async { | |||
try { | |||
String third = data['thirdType']; | |||
if (EmptyUtil.isEmpty(third)) return null; | |||
/// 请求参数 | |||
Map<String, dynamic> params = {}; | |||
params['mobile'] = event.mobile; | |||
params['zone'] = '86'; | |||
params['captcha'] = event.captcha; | |||
/// 淘宝登录 | |||
if (GlobalConfig.LOGIN_THIRD_ALI == third) { | |||
Map<String, String> 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; | |||
} | |||
} |
@@ -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<Object> get props => []; | |||
} | |||
/// 初始化状态 | |||
class LoginBindPhoneInitial extends LoginBindPhoneState {} | |||
/// 数据加载完毕状态 | |||
class LoginBindPhoneLoadedState extends LoginBindPhoneState { | |||
final LoginStyleModel model; | |||
const LoginBindPhoneLoadedState({@required this.model}); | |||
@override | |||
List<Object> 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<Object> get props => [this.model]; | |||
} | |||
/// 登陆失败 | |||
class LoginBindPhoneLoginErrorState extends LoginBindPhoneState { | |||
@override | |||
bool operator ==(Object other) { | |||
return false; | |||
} | |||
@override | |||
int get hashCode => super.hashCode; | |||
} |
@@ -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<String, dynamic> 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<LoginBindPhoneBloc>( | |||
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<LoginBindPhoneBloc>(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<LoginBindPhoneBloc>(context).add(LoginBindPhoneGetVCodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? '')); | |||
return true; | |||
} | |||
return false; | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return BlocConsumer<LoginBindPhoneBloc, LoginBindPhoneState>( | |||
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<UserInfoNotifier>(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: <Widget>[ | |||
/// 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: <Widget>[ | |||
_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: <Widget>[ | |||
// // 输入框 | |||
// 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: <Widget>[ | |||
/// 图标 | |||
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<String> 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: <Widget>[ | |||
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, | |||
), | |||
), | |||
), | |||
], | |||
), | |||
); | |||
} | |||
} |
@@ -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: <Widget>[ | |||
/// 标题 | |||
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)), | |||
), | |||
); | |||
} | |||
} |
@@ -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<String, dynamic> 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<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
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; | |||
} | |||
} |
@@ -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<LoginEvent, LoginState> { | |||
Stream<LoginState> 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<LoginState> _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<LoginState> _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<LoginState> _mapLoginWeChatEventToState(LoginThirdWeChatEvent event) async* {} | |||
/// QQ 登录 | |||
Stream<LoginState> _mapLoginQQEventToState(LoginThirdQQEvent event) async* {} | |||
/// 苹果登录 | |||
Stream<LoginState> _mapLoginAppleEventToState(LoginThirdAppleEvent event) async* {} | |||
} |
@@ -2,9 +2,37 @@ import 'package:equatable/equatable.dart'; | |||
abstract class LoginEvent extends Equatable { | |||
const LoginEvent(); | |||
@override | |||
List<Object> 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<Object> 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 {} |
@@ -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<LoginModel> 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<LoginStyleModel> fetchNetPageData() async { | |||
return await LoginStyleUtil.fetchNetPageData(); | |||
} | |||
/// 获取缓存的页面数据 | |||
Future<LoginModel> 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<LoginStyleModel> fetchCachePageData() async { | |||
return await LoginStyleUtil.fetchCachePageData(); | |||
} | |||
/// 淘宝登录 | |||
Future<UserInfoModel> 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<String, String> 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<UserInfoModel> weChatLogin() async { | |||
return null; | |||
} | |||
/// apple 登录 | |||
Future<UserInfoModel> appleLogin() async { | |||
return null; | |||
} | |||
/// QQ 登录 | |||
Future<UserInfoModel> qqLogin() async { | |||
return null; | |||
} | |||
} |
@@ -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<Object> get props => [this.model]; | |||
} | |||
/// 数据加载完毕状态 | |||
class LoginLoadedState extends LoginState { | |||
final LoginModel model; | |||
final LoginStyleModel model; | |||
const LoginLoadedState({this.model}); | |||
@override | |||
List<Object> 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<Object> get props => [this.model]; | |||
} | |||
/// 第三方登录失败 | |||
class LoginThirdLoginErrorState extends LoginState { | |||
@override | |||
bool operator ==(Object other) { | |||
return false; | |||
} | |||
@override | |||
int get hashCode => super.hashCode; | |||
} |
@@ -53,9 +53,11 @@ class LoginInviteBloc extends Bloc<LoginInviteEvent, LoginInviteState> { | |||
/// 提交 | |||
Stream<LoginInviteState> _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); | |||
} | |||
} | |||
} |
@@ -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<LoginModel> fetchData() async { | |||
pageModel = await LoginUtil.getLoginModel(); | |||
Future<LoginStyleModel> fetchData() async { | |||
pageModel = await LoginStyleUtil.getLoginModel(); | |||
if (!EmptyUtil.isEmpty(pageModel)) { | |||
return pageModel; | |||
} | |||
@@ -21,27 +23,36 @@ class LoginInviteRepository { | |||
/// 获取邀请人信息 | |||
Future<LoginInviteUser> 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<UserInfoModel> 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; | |||
} | |||
@@ -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<Object> 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}); | |||
@@ -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<LoginInvitePageContainer> { | |||
TextEditingController _editingController; | |||
FocusNode _focusNode; | |||
bool _showInviteInfo = false; | |||
// 是否登录中 | |||
bool _isLogging = false; | |||
@@ -80,14 +79,19 @@ class _LoginInvitePageContainerState extends State<LoginInvitePageContainer> { | |||
void _submitOnClick(LoginInviteUser inviteUser) async { | |||
_focusNode.unfocus(); | |||
/// 邀请码 | |||
String inviteNum = inviteUser?.userId ?? ''; | |||
/// 手机号 | |||
UserInfoModel model = await Provider.of<UserInfoNotifier>(context, listen: false)?.getUserInfoModel(); | |||
String mobile = model?.mobile ?? ''; | |||
if (!EmptyUtil.isEmpty(inviteNum) && !EmptyUtil.isEmpty(mobile)) { | |||
BlocProvider.of<LoginInviteBloc>(context).add(LoginInviteSubmitEvent(mobile: mobile, num: inviteNum)); | |||
if (!_isLogging) { | |||
/// 邀请码 | |||
String inviteNum = inviteUser?.userId ?? ''; | |||
/// 手机号 | |||
UserInfoModel model = await Provider.of<UserInfoNotifier>(context, listen: false)?.getUserInfoModel(); | |||
String mobile = model?.mobile ?? ''; | |||
if (!EmptyUtil.isEmpty(inviteNum) && !EmptyUtil.isEmpty(mobile)) { | |||
setState(() { | |||
_isLogging = true; | |||
}); | |||
BlocProvider.of<LoginInviteBloc>(context).add(LoginInviteSubmitEvent(mobile: mobile, num: inviteNum)); | |||
} | |||
} | |||
} | |||
@@ -125,6 +129,7 @@ class _LoginInvitePageContainerState extends State<LoginInvitePageContainer> { | |||
buildWhen: (previous, current) { | |||
/// 提交失败 | |||
if (current is LoginInviteSubmitErrorState) { | |||
_isLogging = false; | |||
return false; | |||
} | |||
@@ -169,7 +174,7 @@ class _LoginInvitePageContainerState extends State<LoginInvitePageContainer> { | |||
} | |||
/// 主视图 | |||
Widget _getMainWidget(LoginModel model, LoginInviteUser inviteUser) { | |||
Widget _getMainWidget(LoginStyleModel model, LoginInviteUser inviteUser) { | |||
return Column( | |||
children: <Widget>[ | |||
/// appbar | |||
@@ -191,7 +196,7 @@ class _LoginInvitePageContainerState extends State<LoginInvitePageContainer> { | |||
} | |||
/// 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<LoginInvitePageContainer> { | |||
} | |||
/// title | |||
Widget _getTitleWidget(LoginModel model) { | |||
Widget _getTitleWidget(LoginStyleModel model) { | |||
return Align( | |||
alignment: Alignment.centerLeft, | |||
child: Text( | |||
@@ -223,7 +228,7 @@ class _LoginInvitePageContainerState extends State<LoginInvitePageContainer> { | |||
} | |||
/// 邀请码输入框 | |||
Widget _getInviteInputWidget(LoginModel model) { | |||
Widget _getInviteInputWidget(LoginStyleModel model) { | |||
return _getCustomInputWidget( | |||
hint: model?.invite?.inputInviteText ?? '请输入邀请码', | |||
controller: _editingController, | |||
@@ -276,7 +281,7 @@ class _LoginInvitePageContainerState extends State<LoginInvitePageContainer> { | |||
} | |||
/// 按钮 | |||
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<LoginInvitePageContainer> { | |||
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'), | |||
@@ -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<LoginPageContainer> { | |||
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<LoginPageContainer> { | |||
} | |||
} | |||
/// 返回上一页 | |||
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<LoginBloc>(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<LoginPageContainer> { | |||
} | |||
} | |||
/// 跳到绑定手机号 | |||
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<LoginPageContainer> { | |||
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<UserInfoNotifier>(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<LoginPageContainer> { | |||
} | |||
/// 主视图 | |||
Widget _getMainWidget(LoginModel model) { | |||
Widget _getMainWidget(LoginStyleModel model) { | |||
return Column( | |||
children: <Widget>[ | |||
/// 头部 | |||
@@ -130,7 +216,7 @@ class _LoginPageContainerState extends State<LoginPageContainer> { | |||
} | |||
/// 头部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<LoginPageContainer> { | |||
size: 22, | |||
color: HexColor.fromHex('#333333'), | |||
), | |||
onPressed: () => _openPop(), | |||
onPressed: () => Navigator.maybePop(context), | |||
), | |||
), | |||
Column( | |||
@@ -187,7 +273,7 @@ class _LoginPageContainerState extends State<LoginPageContainer> { | |||
} | |||
/// 按钮 | |||
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<LoginPageContainer> { | |||
} | |||
/// 协议 | |||
Widget _protocolWidget(LoginModel model) { | |||
Widget _protocolWidget(LoginStyleModel model) { | |||
return RichText( | |||
text: TextSpan( | |||
text: '', | |||
@@ -226,7 +312,7 @@ class _LoginPageContainerState extends State<LoginPageContainer> { | |||
} | |||
/// 其它登陆方式 | |||
Widget _otherLoginWidget(LoginModel model) { | |||
Widget _otherLoginWidget(LoginStyleModel model) { | |||
return Expanded( | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.end, | |||
@@ -241,10 +327,10 @@ class _LoginPageContainerState extends State<LoginPageContainer> { | |||
} | |||
/// 其它登陆方式的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<LoginPageContainer> { | |||
} | |||
/// 其它登陆方式的按钮 | |||
Widget _getOtherLoginIcons(LoginModel model) { | |||
Widget _getOtherLoginIcons(LoginStyleModel model) { | |||
return Row( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: model.main.bottomIcons.map((item) { | |||
@@ -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<LoginModel> getLoginModel() async { | |||
static Future<LoginStyleModel> getLoginModel() async { | |||
var cache = await fetchCachePageData(); | |||
if (!EmptyUtil.isEmpty(cache)) return cache; | |||
var result = await fetchNetPageData(); | |||
@@ -32,20 +32,20 @@ class LoginUtil { | |||
} | |||
/// 获取缓存的页面数据 | |||
static Future<LoginModel> fetchCachePageData() async { | |||
static Future<LoginStyleModel> 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<LoginModel> fetchNetPageData() async { | |||
static Future<LoginStyleModel> 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; |
@@ -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<String, dynamic> json) { | |||
LoginStyleModel.fromJson(Map<String, dynamic> 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<String, dynamic> 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<String, dynamic> json) { | |||
type = json['type']; | |||
@@ -252,44 +249,50 @@ class Mobile { | |||
String protocolUnselectIcon; | |||
List<Protocol> 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<String, dynamic> 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<Protocol>(); | |||
json['protocol'].forEach((v) { | |||
@@ -339,6 +344,8 @@ class Mobile { | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
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<String, dynamic> 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<String, dynamic> json) { | |||
appBarTitle = json['app_bar_title']; |
@@ -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'; | |||
} |
@@ -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'; | |||
@@ -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'; | |||
@@ -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 | |||