|
- import 'dart:io';
-
- 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/invite/login_invite_page.dart';
- import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
- import 'package:zhiying_comm/util/shared_prefe_util.dart';
- import 'package:zhiying_comm/zhiying_comm.dart';
- import 'bloc/bloc.dart';
- import 'bloc/login_account_repository.dart';
- import 'login_account_sk.dart';
- import 'widget/slide_verify_widget.dart';
- import 'package:zhiying_comm/util/empty_util.dart';
- import 'package:fluttertoast/fluttertoast.dart';
- import 'widget/vcode_widget.dart';
-
- ///
- /// 账号登陆(手机验证码,密码)
- ///
- class LoginAccountPage extends StatelessWidget {
- final Map<String, dynamic> model;
-
- const LoginAccountPage(this.model, {Key key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- resizeToAvoidBottomInset: false,
- backgroundColor: HexColor.fromHex('#FFFFFF'),
- body: BlocProvider<LoginAccountBloc>(
- create: (_) => LoginAccountBloc(repository: LoginAccountRepository())..add(LoginAccountInitEvent()),
- child: LoginAccountPageContianer(),
- ),
- );
- }
- }
-
- /// 啦啦啦
- class LoginAccountPageContianer extends StatefulWidget {
- @override
- _LoginAccountPageContianerState createState() => _LoginAccountPageContianerState();
- }
-
- ///
- /// 主体逻辑
- ///
- class _LoginAccountPageContianerState extends State<LoginAccountPageContianer> implements OnClickListener {
- TextEditingController _phoneEdController;
- TextEditingController _vcodeEdController;
- TextEditingController _passEdController;
- FocusNode _phoneFN;
- FocusNode _passFN;
- FocusNode _vcodeFN;
-
- /// 是否使用验证码登陆 默认使用
- bool _useVcode = true;
-
- /// 是否可以登陆
- bool _canSubmit = false;
-
- /// 是否同意协议
- bool _acceptAgreement = true;
-
- /// 是否显示第三方验证码
- bool _showOtherVcode = false;
-
- /// 是否登录中
- bool _isLogging = false;
-
- /// 设置苹果审核UI
- void _settingIosReviewUI() async{
- String is_ios_review = await SharedPreferencesUtil.getStringValue(GlobalConfig.IS_IOS_REVIEW, defaultVal: '0');
- if(Platform.isIOS && is_ios_review == '1' ){
- _useVcode = false;
- }
- }
-
- /// 跳转到邀请码页面
- void _openInvitePage(String mobile) {
- print('跳转到邀请码页面');
- RouterUtil.hideKeyboard(context);
- Navigator.push(
- context,
- CupertinoPageRoute(
- // builder: (_) => PageFactory.create('login_invite', null)
- builder: (_) => LoginInvitePage({'mobile': mobile})));
- }
-
- /// 登陆成功页面
- void _openLoginSuccessPage() {
- RouterUtil.hideKeyboard(context);
- RouterUtil.goBackHomePage(context);
- // Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) => PageFactory.create('homePage', null)), (Route<dynamic> route) => false,);
- }
-
- /// 登陆
- void _submitOnClick() {
- print('登陆');
- if (_checkParam(true) && !_isLogging) {
- setState(() {
- _isLogging = true;
- });
- if (_useVcode) {
- 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() ?? ''));
- }
- } else {
- Logger.log('参数有误 或者 正在登录中。。。');
- }
- }
-
- /// 切换登陆方式
- void _changeLoginTypeOnClick() {
- print('切换登陆');
-
- _passFN?.unfocus();
- _vcodeFN?.unfocus();
- _phoneFN?.unfocus();
-
- setState(() {
- _useVcode = !_useVcode;
- _canSubmit = false;
- });
- // 清除缓存
- if (_useVcode) {
- _passEdController?.clear();
- } else {
- _vcodeEdController?.clear();
- }
- }
-
- /// 同意协议
- 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) {
- // 验证码
- if (_useVcode) {
- 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;
- }
- } else {
- String phone = _phoneEdController?.text?.toString()?.trim() ?? null;
- String pass = _passEdController?.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(pass)) {
- if (needToast) Fluttertoast.showToast(msg: '验证码不能为空!');
- return false;
- }
- if (pass.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;
- }
-
- @override
- void initState() {
- _phoneEdController = TextEditingController();
- _passEdController = TextEditingController();
- _vcodeEdController = TextEditingController();
- _vcodeFN = FocusNode();
- _passFN = FocusNode();
- _phoneFN = FocusNode();
- // 设置苹果审核UI
- _settingIosReviewUI();
- 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<LoginAccountBloc>(context).add(LoginAccountGetVcodeEvent(mobile: _phoneEdController?.text?.toString()?.trim() ?? ''));
- return true;
- }
- return false;
- }
-
- @override
- Widget build(BuildContext context) {
- return BlocConsumer<LoginAccountBloc, LoginAccountState>(
- listener: (context, state) {
- if (state is LoginAccountLoginSuccessState) {}
- },
- buildWhen: (prev, current) {
- // 登陆失败
- if (current is LoginAccountLoginErrorState) {
- // Fluttertoast.showToast(msg: '登陆失败');
- setState(() {
- _isLogging = false;
- });
-
- return false;
- }
- // 登陆成功
- if (current is LoginAccountLoginSuccessState) {
-
- if (current?.model?.registerInviteCodeEnable != '1') {
- /// 缓存登陆数据
- Provider.of<UserInfoNotifier>(context, listen: false)?.setUserInfo(current.model);
- Fluttertoast.showToast(msg: '登录成功~');
- _isLogging = true;
-
- /// 打开也买
- _openLoginSuccessPage();
- } else {
- /// 打开邀请页面
- _openInvitePage(current?.model?.mobile);
- }
- return false;
- }
- // 获取验证码成功
- if (current is LoginAccountGetVcodeSuccessState) {
- // Fluttertoast.showToast(msg: '验证码下发成功');
- return false;
- }
- // 获取验证码失败
- if (current is LoginAccountGetVcodeErrorState) {
- // Fluttertoast.showToast(msg: '验证码获取失败~');
- return false;
- }
- return true;
- },
- builder: (context, state) {
- print('state = $state');
- if (state is LoginAccountLoadedState) {
- return _getMainWidget(state.model);
- }
- // 返回骨架屏
- return LoginAccountSkeleton();
- },
- );
- }
-
- /// 主页面
- 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: _useVcode, child: Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 15), child: _getVcodeWidget(model))),
-
- /// 密码
- Visibility(visible: !_useVcode, child: Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 15), child: _getPassInputWidget(model))),
-
- /// 第三方验证码
- Visibility(visible: _showOtherVcode, child: Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 15), child: _getOtherVcodeInputWidget(model))),
-
- /// 切换登陆方式tip
- Padding(padding: const EdgeInsets.only(top: 15), child: _getChangeTipWidget(model)),
-
- /// 登录按钮
- Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 30), child: _getSubmiBtnWidget(model)),
-
- /// 协议
- Padding(padding: const EdgeInsets.only(top: 15), child: _getProtoclWidget(model)),
-
- /// 底部提示tip
- Visibility(visible: _useVcode, 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?.appBarTitle ?? '登录',
- 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: () => Navigator.maybePop(context),
- ),
- );
- }
-
- /// title
- Widget _getTitleWidget(LoginStyleModel model) {
- return Align(
- alignment: Alignment.centerLeft,
- child: Text(
- model?.mobile?.title ?? '您好,欢迎登录',
- 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'),
- );
- }
-
- /// 切换登陆方式tip
- Widget _getChangeTipWidget(LoginStyleModel model) {
- return GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () => _changeLoginTypeOnClick(),
- child: Text(
- _useVcode ? model?.mobile?.textUsePassTip ?? '使用密码登录' : model?.mobile?.textUseVcodeTip ?? '使用验证码登陆',
- style: TextStyle(fontSize: 12, color: HexColor.fromHex(_useVcode ? model?.mobile?.textUsePassTipColor ?? '#999999' : model?.mobile?.textUseVcodeTipColor ?? '#999999')),
- ),
- );
- }
-
- /// 登陆按钮
- Widget _getSubmiBtnWidget(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,
- ),
- ),
- ),
- ],
- ),
- );
- }
- }
|