Переглянути джерело

1、商品列表的缓存

2、淘宝登录
tags/0.0.2+11
PH2 4 роки тому
джерело
коміт
c5cbeac504
28 змінених файлів з 1387 додано та 235 видалено
  1. +5
    -2
      lib/models/user/user_info_model.dart
  2. +3
    -0
      lib/models/user/user_info_model_notifier.dart
  3. +4
    -5
      lib/pages/login_page/account/bloc/login_account_repository.dart
  4. +9
    -5
      lib/pages/login_page/account/bloc/login_account_state.dart
  5. +21
    -17
      lib/pages/login_page/account/login_account_page.dart
  6. +4
    -0
      lib/pages/login_page/bind/bloc/bloc.dart
  7. +59
    -0
      lib/pages/login_page/bind/bloc/login_bind_phone_bloc.dart
  8. +47
    -0
      lib/pages/login_page/bind/bloc/login_bind_phone_event.dart
  9. +77
    -0
      lib/pages/login_page/bind/bloc/login_bind_phone_repository.dart
  10. +54
    -0
      lib/pages/login_page/bind/bloc/login_bind_phone_state.dart
  11. +555
    -0
      lib/pages/login_page/bind/login_bind_phone_page.dart
  12. +61
    -0
      lib/pages/login_page/bind/login_bind_phone_sk.dart
  13. +30
    -0
      lib/pages/login_page/bind/model/login_bind_phone_user_model.dart
  14. +49
    -4
      lib/pages/login_page/bloc/login_bloc.dart
  15. +29
    -1
      lib/pages/login_page/bloc/login_event.dart
  16. +51
    -18
      lib/pages/login_page/bloc/login_repository.dart
  17. +31
    -3
      lib/pages/login_page/bloc/login_state.dart
  18. +4
    -2
      lib/pages/login_page/invite/bloc/login_invite_bloc.dart
  19. +30
    -19
      lib/pages/login_page/invite/bloc/login_invite_repository.dart
  20. +8
    -7
      lib/pages/login_page/invite/bloc/login_invite_state.dart
  21. +21
    -16
      lib/pages/login_page/invite/login_invite_page.dart
  22. +107
    -21
      lib/pages/login_page/login_page.dart
  23. +7
    -7
      lib/pages/login_page/login_style_util.dart
  24. +107
    -100
      lib/pages/login_page/model/login_style_model.dart
  25. +6
    -3
      lib/util/global_config.dart
  26. +1
    -1
      lib/util/mob_util/mob_util.dart
  27. +1
    -1
      lib/util/mob_util/secverify/quick_login_util.dart
  28. +6
    -3
      lib/util/net_util.dart

+ 5
- 2
lib/models/user/user_info_model.dart Переглянути файл

@@ -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;
}


+ 3
- 0
lib/models/user/user_info_model_notifier.dart Переглянути файл

@@ -1,6 +1,7 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_alibc/flutter_alibc.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';
import 'package:zhiying_comm/util/global_config.dart';
import 'package:zhiying_comm/util/log/let_log.dart';
@@ -71,6 +72,8 @@ class UserInfoNotifier with ChangeNotifier {
GlobalConfig.SHARED_KEY_MOBILE, '');
await SharedPreferencesUtil.setStringValue(
GlobalConfig.SHARED_KEY_USER_INFO, '');
// 退出淘宝登录
FlutterAlibc.loginOut();
notifyListeners();
}



+ 4
- 5
lib/pages/login_page/account/bloc/login_account_repository.dart Переглянути файл

@@ -1,13 +1,12 @@
import 'dart:math';

import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/global_config.dart';
import 'package:zhiying_comm/util/mob_util/mob_util.dart';
import 'package:zhiying_comm/util/net_util.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';

import '../../login_util.dart';
import '../../login_style_util.dart';
import 'bloc.dart';

///
@@ -15,8 +14,8 @@ import 'bloc.dart';
///
class LoginAccountRepository {
/// 获取数据,如果缓存有,则获取缓存的数据
Future<LoginModel> fetchData() async {
var result = await LoginUtil.getLoginModel();
Future<LoginStyleModel> fetchData() async {
var result = await LoginStyleUtil.getLoginModel();
if (!EmptyUtil.isEmpty(result)) {
return result;
}


+ 9
- 5
lib/pages/login_page/account/bloc/login_account_state.dart Переглянути файл

@@ -1,7 +1,7 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';

abstract class LoginAccountState extends Equatable {
const LoginAccountState();
@@ -15,7 +15,7 @@ class LoginAccountInitial extends LoginAccountState {}

/// 数据加载完毕状态
class LoginAccountLoadedState extends LoginAccountState {
final LoginModel model;
final LoginStyleModel model;

const LoginAccountLoadedState({@required this.model});

@@ -55,7 +55,11 @@ class LoginAccountLoginSuccessState extends LoginAccountState {

/// 登陆失败
class LoginAccountLoginErrorState extends LoginAccountState {
final String msg;
@override
bool operator ==(Object other) {
return false;
}

const LoginAccountLoginErrorState({this.msg});
}
@override
int get hashCode => super.hashCode;
}

+ 21
- 17
lib/pages/login_page/account/login_account_page.dart Переглянути файл

@@ -5,7 +5,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
import 'package:zhiying_comm/pages/login_page/invite/login_invite_page.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'bloc/bloc.dart';
import 'bloc/login_account_repository.dart';
@@ -52,6 +52,7 @@ class _LoginAccountPageContianerState extends State<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,


+ 4
- 0
lib/pages/login_page/bind/bloc/bloc.dart Переглянути файл

@@ -0,0 +1,4 @@
export 'login_bind_phone_state.dart';
export 'login_bind_phone_event.dart';
export 'login_bind_phone_repository.dart';
export 'login_bind_phone_bloc.dart';

+ 59
- 0
lib/pages/login_page/bind/bloc/login_bind_phone_bloc.dart Переглянути файл

@@ -0,0 +1,59 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import './bloc.dart';
import 'package:zhiying_comm/util/empty_util.dart';

class LoginBindPhoneBloc extends Bloc<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();
}
}

+ 47
- 0
lib/pages/login_page/bind/bloc/login_bind_phone_event.dart Переглянути файл

@@ -0,0 +1,47 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';

abstract class LoginBindPhoneEvent extends Equatable {
const LoginBindPhoneEvent();

@override
List<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];
}

+ 77
- 0
lib/pages/login_page/bind/bloc/login_bind_phone_repository.dart Переглянути файл

@@ -0,0 +1,77 @@
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/global_config.dart';
import 'package:zhiying_comm/util/log/let_log.dart';
import 'package:zhiying_comm/util/mob_util/mob_util.dart';
import 'package:zhiying_comm/util/net_util.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';
import '../../login_style_util.dart';
import 'bloc.dart';

///
/// 账户登陆
///
class LoginBindPhoneRepository {
final Map<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;
}
}

+ 54
- 0
lib/pages/login_page/bind/bloc/login_bind_phone_state.dart Переглянути файл

@@ -0,0 +1,54 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';

abstract class LoginBindPhoneState extends Equatable {
const LoginBindPhoneState();

@override
List<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;
}

+ 555
- 0
lib/pages/login_page/bind/login_bind_phone_page.dart Переглянути файл

@@ -0,0 +1,555 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
import 'package:zhiying_comm/pages/login_page/account/widget/slide_verify_widget.dart';
import 'package:zhiying_comm/pages/login_page/account/widget/vcode_widget.dart';
import 'package:zhiying_comm/pages/login_page/invite/login_invite_page.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'bloc/bloc.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:fluttertoast/fluttertoast.dart';

import 'login_bind_phone_sk.dart';

///
/// 账号登陆(手机验证码,密码)
///
class LoginBindPhonePage extends StatelessWidget {
///
/// 这里面model 需要带上 thirdType key,作为第三方登录的类型。
///
final Map<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,
),
),
),
],
),
);
}
}

+ 61
- 0
lib/pages/login_page/bind/login_bind_phone_sk.dart Переглянути файл

@@ -0,0 +1,61 @@
import 'package:shimmer/shimmer.dart';
import 'package:flutter/material.dart';
import 'package:zhiying_comm/util/extension/color.dart';

///
/// 绑定手机号骨架图
///
class LoginBindPhoneSkeleton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: HexColor.fromHex('#FFFFFF'),
elevation: 0,
title: Text(
'登录',
style: TextStyle(color: HexColor.fromHex('#333333')),
),
centerTitle: true,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
size: 22,
color: HexColor.fromHex('#333333'),
),
onPressed: () {},
),
),
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 27.5),
width: double.infinity,
height: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <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)),
),
);
}
}

+ 30
- 0
lib/pages/login_page/bind/model/login_bind_phone_user_model.dart Переглянути файл

@@ -0,0 +1,30 @@
class LoginBindPhonUserModel {
String userId;
String nickname;
String appName;
String nickNameColor;
String appNameColor;
String avatar;

LoginBindPhonUserModel({this.userId, this.nickname, this.appName});

LoginBindPhonUserModel.fromJson(Map<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;
}
}

+ 49
- 4
lib/pages/login_page/bloc/login_bloc.dart Переглянути файл

@@ -1,5 +1,6 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:zhiying_comm/util/global_config.dart';
import './bloc.dart';
import 'login_repository.dart';
import 'package:zhiying_comm/util/empty_util.dart';
@@ -16,23 +17,67 @@ class LoginBloc extends Bloc<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* {}
}

+ 29
- 1
lib/pages/login_page/bloc/login_event.dart Переглянути файл

@@ -2,9 +2,37 @@ import 'package:equatable/equatable.dart';

abstract class LoginEvent extends Equatable {
const LoginEvent();

@override
List<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 {}

+ 51
- 18
lib/pages/login_page/bloc/login_repository.dart Переглянути файл

@@ -1,26 +1,59 @@
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import '../login_util.dart';
import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import '../login_style_util.dart';

class LoginRepository {
/// 获取页面数据
Future<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;
}
}

+ 31
- 3
lib/pages/login_page/bloc/login_state.dart Переглянути файл

@@ -1,5 +1,7 @@
import 'package:equatable/equatable.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';

abstract class LoginState extends Equatable {
const LoginState();
@@ -13,19 +15,45 @@ class InitialLoginState extends LoginState {}

/// 缓存数据状态
class LoginCacheState extends LoginState {
final LoginModel model;
final LoginStyleModel model;

const LoginCacheState({this.model});

@override
List<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;
}

+ 4
- 2
lib/pages/login_page/invite/bloc/login_invite_bloc.dart Переглянути файл

@@ -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);
}
}
}

+ 30
- 19
lib/pages/login_page/invite/bloc/login_invite_repository.dart Переглянути файл

@@ -1,18 +1,20 @@
import 'package:zhiying_comm/pages/login_page/invite/model/login_invite_user.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/net_util.dart';
import 'package:zhiying_comm/util/global_config.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';
import '../../login_util.dart';
import 'package:zhiying_comm/util/log/let_log.dart';
import '../../login_style_util.dart';
import 'bloc.dart';

class LoginInviteRepository {
LoginModel pageModel;
LoginStyleModel pageModel;
LoginInviteUser lastInviteUser;

/// 获取数据,如果缓存有,则获取缓存的数据
Future<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;
}


+ 8
- 7
lib/pages/login_page/invite/bloc/login_invite_state.dart Переглянути файл

@@ -2,7 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:zhiying_comm/models/user/user_info_model.dart';
import 'package:zhiying_comm/pages/login_page/invite/model/login_invite_user.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';

abstract class LoginInviteState extends Equatable {
const LoginInviteState();
@@ -16,7 +16,7 @@ class LoginInviteInitial extends LoginInviteState {}

/// 数据加载完毕状态
class LoginInviteLoadedState extends LoginInviteState {
final LoginModel model;
final LoginStyleModel model;

const LoginInviteLoadedState({@required this.model});

@@ -46,18 +46,19 @@ class LoginInviteSubmitSuccess extends LoginInviteState {

/// 邀请码失败
class LoginInviteSubmitErrorState extends LoginInviteState {
final String msg;

const LoginInviteSubmitErrorState({this.msg});
@override
bool operator ==(Object other) {
return false;
}

@override
List<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});



+ 21
- 16
lib/pages/login_page/invite/login_invite_page.dart Переглянути файл

@@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/mob_util/mob_util.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
@@ -39,7 +39,6 @@ class _LoginInvitePageContainerState extends State<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'),


+ 107
- 21
lib/pages/login_page/login_page.dart Переглянути файл

@@ -2,16 +2,22 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_alibc/alibc_model.dart';
import 'package:flutter_alibc/flutter_alibc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:zhiying_comm/pages/login_page/account/login_account_page.dart';
import 'package:zhiying_comm/pages/login_page/bind/login_bind_phone_page.dart';
import 'package:zhiying_comm/util/dialog/loading/loading.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/mob_util/mob_util.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:provider/provider.dart';

import 'bloc/bloc.dart';
import 'bloc/login_repository.dart';
import 'login_page_sk.dart';
import 'model/login_model.dart';
import 'model/login_style_model.dart';

///
/// 登陆页面
@@ -37,13 +43,15 @@ class LoginPageContainer extends StatefulWidget {
}

class _LoginPageContainerState extends State<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) {


lib/pages/login_page/login_util.dart → lib/pages/login_page/login_style_util.dart Переглянути файл

@@ -3,10 +3,10 @@ import 'package:zhiying_comm/util/shared_prefe_util.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/global_config.dart';

import 'model/login_model.dart';
import 'model/login_style_model.dart';

/// 登陆数据管理工具类
class LoginUtil {
class LoginStyleUtil {
static final String _URL = '/api/v1/sign/in';

static void init() async {
@@ -17,7 +17,7 @@ class LoginUtil {
}

/// 获取数据
static Future<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;

lib/pages/login_page/model/login_model.dart → lib/pages/login_page/model/login_style_model.dart Переглянути файл

@@ -5,32 +5,36 @@
/// invite : {"app_bar_title":"登陆","app_bar_title_color":"#333333","app_bar_bg_color":"#FFFFFF","title":"输入邀请码","title_color":"#333333","input_hint_color":"#999999","input_bg_color":"#F7F7F7","btn_ban_bg_color":"#F5F5F5","btn_ban_text_color":"#999999","input_invite_icon":"http://xxxx","input_invite_text":"请输入邀请码","input_invite_text_color":"#999999","btn_submit_text":"进入智莺生活","btn_submit_text_color":"#FFFFFF","btn_submit_bg_color":"#FF3939","btn_submit_shadow_color":"#FF0000"}
/// quick : {"app_bar_title":"","app_bar_bg_color":"","app_bar_title_color":"#FFFFFF","account_color":"#333333","text_tip":"切换账号","text_tip_color":"#FF3939","btn_submit_text":"立即登录","btn_submit_text_color":"#FFFFFF","btn_submit_bg_color":"#FF3939","btn_submit_shadow_color":"#FF0000","protocol_select_icon":"http://xxxx","protocol_unselect_icon":"http://xxxxx","text_bottom_tip":"中国电信提供认证服务","text_bottom_tip_color":"#C0C0C0","protocol":[{"text":"同意","text_color":"#C0C0C0","url":""},{"text":"《智莺生活用户协议》","text_color":"#FF3939","url":"http://www.hairuyi.com/?mod=appapi&act=privacy&ctrl=index&type=protocol"},{"text":"及","text_color":"#C0C0C0","url":""},{"text":"《隐私政策》","text_color":"#FF3939","url":"http://www.hairuyi.com/?mod=appapi&act=privacy&ctrl=index&type=privacyPolicy"}]}
/// flash_login_enable : "1"
class LoginModel {
class LoginStyleModel {
// 返回图标
String backImg;

// logo
String logoImg;

// 登录首页的UI
Main main;

// 手机绑定
Mobile mobile;

// 邀请好友页面
Invite invite;

// 一键登录
Quick quick;

// 是否需要填写邀请码
String flashLoginEnable;

LoginModel(
{this.backImg,
this.logoImg,
this.main,
this.mobile,
this.invite,
this.quick,
this.flashLoginEnable});
LoginStyleModel({this.backImg, this.logoImg, this.main, this.mobile, this.invite, this.quick, this.flashLoginEnable});

LoginModel.fromJson(Map<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'];

+ 6
- 3
lib/util/global_config.dart Переглянути файл

@@ -10,6 +10,12 @@ class GlobalConfig {
/// 通用标志key
static final String SKIP_IDENTIFIER = 'skip_identifier';

/// ====================== 第三方登录key ====================== ///
static const String LOGIN_THIRD_ALI = 'taobao'; // 淘宝登录
static const String LOGIN_THIRD_WECHAT = 'wechat'; // 微信
static const String LOGIN_THIRD_QQ = 'qq'; // QQ
static const String LOGIN_THIRD_APPLE = 'apple'; // 苹果登录

/// ====================== 各个渠道的key ====================== ///
static const String PROVIDER_TB = 'taobao'; // 淘宝
static const String PROVIDER_TM = 'tianmao'; // 天猫
@@ -35,7 +41,4 @@ class GlobalConfig {
/// 货币类型
static final String MONEY_TYPE = "¥ ";

// /// 天猫 淘宝类型
// static final String PROVIDER_TM = 'tianmao';
// static final String PROVIDER_TB = 'taobao';
}

+ 1
- 1
lib/util/mob_util/mob_util.dart Переглянути файл

@@ -1,6 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:mobsms/mobsms.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/enum_util.dart';
import 'package:zhiying_comm/util/global_config.dart';


+ 1
- 1
lib/util/mob_util/secverify/quick_login_util.dart Переглянути файл

@@ -7,7 +7,7 @@ import 'package:zhiying_comm/models/user/user_info_model.dart';
import 'package:zhiying_comm/models/user/user_info_model_notifier.dart';
import 'package:zhiying_comm/pages/login_page/account/login_account_page.dart';
import 'package:zhiying_comm/pages/login_page/invite/login_invite_page.dart';
import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
import 'package:zhiying_comm/pages/login_page/model/login_style_model.dart';
import 'package:zhiying_comm/util/empty_util.dart';
import 'package:zhiying_comm/util/global_config.dart';
import 'package:zhiying_comm/util/log/let_log.dart';


+ 6
- 3
lib/util/net_util.dart Переглянути файл

@@ -145,7 +145,10 @@ class NetUtil {
}
}

// 退出登陆
///
/// 401003 用户被逼下线
/// 退出登陆(清理token等用户信息)
///
if (result[GlobalConfig.HTTP_RESPONSE_KEY_CODE]?.toString() == '401003') {
try {
Future.delayed(Duration(seconds: 0)).then((onValue) {
@@ -178,7 +181,7 @@ class NetUtil {
}

try {
Map result = await NetUtil.post(path, method: method, params: params, queryParameters: queryParameters, showToast: showToast);
Map result = await NetUtil.post(path, method: method, params: params, queryParameters: queryParameters, showToast: showToast, cache: onCache != null);
// TODO 解密?
if (isSuccess(result)) {
if (onSuccess != null) {
@@ -323,7 +326,7 @@ class NetUtil {
// 站长ID
String masterId = setting['master_id'];
if (null != masterId && masterId != '' && (!params.containsKey('master_id') || params['master_id'] == '')) {
params['master_id'] = masterId ?? 'template_database';
params['master_id'] = masterId; //!EmptyUtil.isEmpty(masterId) ? masterId : 'template_database';
}

// token 读取SP缓存中的用户token


Завантаження…
Відмінити
Зберегти