基础库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

394 lines
12 KiB

  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/gestures.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter_alibc/alibc_model.dart';
  6. import 'package:flutter_alibc/flutter_alibc.dart';
  7. import 'package:flutter_bloc/flutter_bloc.dart';
  8. import 'package:fluttertoast/fluttertoast.dart';
  9. import 'package:zhiying_comm/pages/login_page/account/login_account_page.dart';
  10. import 'package:zhiying_comm/pages/login_page/bind/login_bind_phone_page.dart';
  11. import 'package:zhiying_comm/util/dialog/loading/loading.dart';
  12. import 'package:zhiying_comm/util/empty_util.dart';
  13. import 'package:zhiying_comm/util/mob_util/mob_util.dart';
  14. import 'package:zhiying_comm/zhiying_comm.dart';
  15. import 'package:provider/provider.dart';
  16. import 'bloc/bloc.dart';
  17. import 'bloc/login_repository.dart';
  18. import 'login_page_sk.dart';
  19. import 'model/login_style_model.dart';
  20. ///
  21. /// 登陆页面
  22. ///
  23. class LoginPage extends StatelessWidget {
  24. const LoginPage({Key key}) : super(key: key);
  25. @override
  26. Widget build(BuildContext context) {
  27. return Scaffold(
  28. backgroundColor: HexColor.fromHex('#FFFFFF'),
  29. body: BlocProvider<LoginBloc>(
  30. create: (_) => LoginBloc(repository: LoginRepository())..add(LoginInitEvent()),
  31. child: LoginPageContainer(),
  32. ),
  33. );
  34. }
  35. }
  36. class LoginPageContainer extends StatefulWidget {
  37. @override
  38. _LoginPageContainerState createState() => _LoginPageContainerState();
  39. }
  40. class _LoginPageContainerState extends State<LoginPageContainer> {
  41. LoginModel _taoBao;
  42. /// 微信or手机登陆
  43. void _loginClick(String type, LoginStyleModel model) {
  44. print('登陆$type');
  45. RouterUtil.hideKeyboard(context);
  46. if (type == 'mobile') {
  47. if (model?.flashLoginEnable == '1') {
  48. // mob 一键登录
  49. MobUtil.openQuickLoginPage(context, model?.quick);
  50. } else {
  51. Navigator.push(context, CupertinoPageRoute(builder: (_) => LoginAccountPage(null)));
  52. }
  53. }
  54. }
  55. /// 第三方登陆
  56. void _otherLoginClick(BottomIcons model) async {
  57. print('第三方登陆${model.type}');
  58. if (EmptyUtil.isEmpty(model) || EmptyUtil.isEmpty(model.type)) {
  59. Fluttertoast.showToast(msg: '暂不支持~');
  60. return;
  61. }
  62. Loading.show(context);
  63. /// 淘宝登录
  64. if ('taobao' == model.type) {
  65. _taoBao = await FlutterAlibc.loginTaoBao();
  66. if (!EmptyUtil.isEmpty(_taoBao) && !EmptyUtil.isEmpty(_taoBao?.errorCode) && _taoBao.errorCode == '0') {
  67. BlocProvider.of<LoginBloc>(context).add(LoginThirdAliEvent(
  68. nick: _taoBao?.data?.nick,
  69. avatarUrl: _taoBao?.data?.avatarUrl,
  70. openId: _taoBao?.data?.openId,
  71. openSid: _taoBao?.data?.openSid,
  72. topAccessToken: _taoBao?.data?.topAccessToken,
  73. topAuthCode: _taoBao?.data?.topAuthCode));
  74. // Logger.warn(' tao login = ${taoBao?.errorCode} , msg = ${taoBao?.errorMessage}, nick = ${taoBao?.data?.nick}, '
  75. // 'avatar = ${taoBao?.data?.avatarUrl}, openId = ${taoBao?.data?.openId}, openSid = ${taoBao?.data?.openSid}, '
  76. // 'topAccessToken = ${taoBao?.data?.topAccessToken}, topAuthCode = ${taoBao?.data?.topAuthCode}');
  77. }
  78. }
  79. /// QQ登录
  80. if ('qq' == model.type) {
  81. Fluttertoast.showToast(msg: '暂不支持~');
  82. }
  83. /// 微信登录
  84. if ('wechat' == model.type) {
  85. Fluttertoast.showToast(msg: '暂不支持~');
  86. }
  87. /// 苹果登录
  88. if ('apple' == model.type) {
  89. Fluttertoast.showToast(msg: '暂不支持~');
  90. }
  91. Loading.dismiss();
  92. }
  93. /// 跳到用户协议
  94. void _jumpUserAgreement(String url) {
  95. if (!EmptyUtil.isEmpty(url)) {
  96. print('协议');
  97. RouterUtil.openWebview(url, context);
  98. }
  99. }
  100. /// 跳到绑定手机号
  101. void _jumpBindPhonePage(String thirdType) {
  102. /// 如果是淘宝登录
  103. if (GlobalConfig.LOGIN_THIRD_ALI == thirdType) {
  104. Navigator.push(
  105. context,
  106. CupertinoPageRoute(
  107. builder: (_) => LoginBindPhonePage({
  108. 'thirdType': thirdType,
  109. 'nick': _taoBao?.data?.nick,
  110. 'avatarUrl': _taoBao?.data?.avatarUrl,
  111. 'openId': _taoBao?.data?.openId,
  112. 'openSid': _taoBao?.data?.openSid,
  113. 'topAccessToken': _taoBao?.data?.topAccessToken,
  114. 'topAuthCode': _taoBao?.data?.topAuthCode,
  115. })));
  116. }
  117. }
  118. /// 跳到首页
  119. void _jumpHomePage() {
  120. RouterUtil.goBackHomePage(context);
  121. }
  122. /// 展开关闭其它登陆
  123. void _showOrCloseOtherLogin() {
  124. setState(() {
  125. _showOther = !_showOther;
  126. });
  127. }
  128. final _sizedHeight50 = const SizedBox(height: 50);
  129. final _sizedHeight9 = const SizedBox(height: 9);
  130. final _sizedHeight18 = const SizedBox(height: 18);
  131. final _sizedHeight21 = const SizedBox(height: 21);
  132. bool _showOther = true;
  133. @override
  134. Widget build(BuildContext context) {
  135. return BlocConsumer<LoginBloc, LoginState>(
  136. listener: (context, state) {
  137. // Fluttertoast.showToast(msg: '网络异常');
  138. },
  139. buildWhen: (prev, current) {
  140. if (current is LoginErrorState) {
  141. return false;
  142. }
  143. /// 登录失败
  144. if (current is LoginThirdLoginErrorState) {
  145. return false;
  146. }
  147. /// 登录成功
  148. if (current is LoginThirdLoginSuccessState) {
  149. // 需要绑定手机号
  150. if (current.model.bindPhoneEnable == '1') {
  151. // 打开绑定手机号页面
  152. _jumpBindPhonePage(current.thirdType);
  153. } else {
  154. // 更新登录数据
  155. Provider.of<UserInfoNotifier>(context, listen: false)?.setUserInfo(current.model);
  156. // 直接打开首页
  157. _jumpHomePage();
  158. Fluttertoast.showToast(msg: '登录成功~');
  159. }
  160. return false;
  161. }
  162. return true;
  163. },
  164. builder: (context, state) {
  165. if (state is LoginCacheState) {
  166. return _getMainWidget(state.model);
  167. }
  168. if (state is LoginLoadedState) {
  169. return _getMainWidget(state.model);
  170. }
  171. return LoginPageSkeleton(); // 骨架屏幕
  172. },
  173. );
  174. }
  175. /// 主视图
  176. Widget _getMainWidget(LoginStyleModel model) {
  177. return Column(
  178. children: <Widget>[
  179. /// 头部
  180. _headWidget(model),
  181. _sizedHeight50,
  182. /// 按钮
  183. _buttonsWidget(model),
  184. _sizedHeight9,
  185. /// 协议
  186. _protocolWidget(model),
  187. /// 其它登陆方式
  188. _otherLoginWidget(model),
  189. ],
  190. );
  191. }
  192. /// 头部Widget
  193. Widget _headWidget(LoginStyleModel model) {
  194. return Container(
  195. height: 228 + MediaQuery.of(context).padding.top,
  196. width: double.infinity,
  197. decoration: BoxDecoration(
  198. image: DecorationImage(
  199. image: CachedNetworkImageProvider(model?.main?.backgroundImg ?? ''),
  200. fit: BoxFit.fill,
  201. ),
  202. ),
  203. child: Stack(
  204. alignment: Alignment.center,
  205. children: <Widget>[
  206. AppBar(
  207. backgroundColor: Colors.transparent,
  208. elevation: 0,
  209. leading: IconButton(
  210. icon: Icon(
  211. Icons.arrow_back_ios,
  212. size: 22,
  213. color: HexColor.fromHex('#333333'),
  214. ),
  215. onPressed: () => Navigator.maybePop(context),
  216. ),
  217. ),
  218. Column(
  219. crossAxisAlignment: CrossAxisAlignment.center,
  220. mainAxisAlignment: MainAxisAlignment.center,
  221. children: <Widget>[
  222. /// logo
  223. Container(
  224. margin: EdgeInsets.only(bottom: 12, top: MediaQuery.of(context).padding.top),
  225. decoration: BoxDecoration(
  226. borderRadius: BorderRadius.circular(14),
  227. boxShadow: [
  228. BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0), blurRadius: 10.0, spreadRadius: 1.0),
  229. BoxShadow(color: Colors.grey[300], offset: Offset(0.0, 0.0)),
  230. ],
  231. ),
  232. height: 80,
  233. width: 80,
  234. child: CachedNetworkImage(imageUrl: model?.logoImg ?? ''),
  235. ),
  236. /// logo 名字
  237. CachedNetworkImage(
  238. imageUrl: model?.main?.appNameImg ?? '',
  239. width: 90,
  240. ),
  241. ],
  242. ),
  243. ],
  244. ),
  245. );
  246. }
  247. /// 按钮
  248. Widget _buttonsWidget(LoginStyleModel model) {
  249. return Container(
  250. padding: const EdgeInsets.symmetric(horizontal: 27.5),
  251. child: Column(
  252. children: model.main.importanceLogin.map((item) {
  253. return Padding(
  254. padding: const EdgeInsets.only(bottom: 8),
  255. child: _customButton(
  256. height: 40,
  257. text: item?.btnText,
  258. iconUrl: item?.btnMobileIcon ?? '',
  259. textColor: item?.btnTextColor,
  260. bgColor: item?.btnBgColor,
  261. borderColor: item?.btnBorderColor,
  262. onTap: () => _loginClick(item?.type, model)),
  263. );
  264. }).toList(),
  265. ),
  266. );
  267. }
  268. /// 协议
  269. Widget _protocolWidget(LoginStyleModel model) {
  270. return RichText(
  271. text: TextSpan(
  272. text: '',
  273. children: model.main.agreements.map((item) {
  274. return TextSpan(
  275. text: item?.text,
  276. style: TextStyle(color: HexColor.fromHex(item?.textColor), fontSize: 10),
  277. recognizer: TapGestureRecognizer()
  278. ..onTap = () {
  279. _jumpUserAgreement(item?.url);
  280. });
  281. }).toList()),
  282. );
  283. }
  284. /// 其它登陆方式
  285. Widget _otherLoginWidget(LoginStyleModel model) {
  286. return Expanded(
  287. child: Column(
  288. mainAxisAlignment: MainAxisAlignment.end,
  289. children: <Widget>[
  290. _getOtherLoginTitle(model),
  291. _sizedHeight18,
  292. Visibility(visible: _showOther, child: _getOtherLoginIcons(model)),
  293. Visibility(visible: _showOther, child: _sizedHeight21),
  294. ],
  295. ),
  296. );
  297. }
  298. /// 其它登陆方式的title
  299. Widget _getOtherLoginTitle(LoginStyleModel model) {
  300. return GestureDetector(
  301. behavior: HitTestBehavior.opaque,
  302. onTap: () => _showOrCloseOtherLogin(),
  303. child: Row(
  304. mainAxisAlignment: MainAxisAlignment.center,
  305. crossAxisAlignment: CrossAxisAlignment.center,
  306. children: <Widget>[
  307. Text('${model?.main?.otherIconsTitle}', style: TextStyle(fontSize: 13, color: HexColor.fromHex(model?.main?.otherIconsTitleColor))),
  308. SizedBox(width: 5.5),
  309. RotatedBox(
  310. quarterTurns: _showOther ? 0 : 2,
  311. child: CachedNetworkImage(imageUrl: model?.main?.otherExpansionIcon ?? '', width: 12),
  312. ),
  313. ],
  314. ),
  315. );
  316. }
  317. /// 其它登陆方式的按钮
  318. Widget _getOtherLoginIcons(LoginStyleModel model) {
  319. return Row(
  320. mainAxisAlignment: MainAxisAlignment.center,
  321. children: model.main.bottomIcons.map((item) {
  322. return GestureDetector(
  323. behavior: HitTestBehavior.opaque,
  324. onTap: () => _otherLoginClick(item),
  325. child: Container(
  326. width: 30,
  327. margin: const EdgeInsets.symmetric(horizontal: 20),
  328. child: CachedNetworkImage(imageUrl: item?.img ?? ''),
  329. ),
  330. );
  331. }).toList(),
  332. );
  333. }
  334. /// 自定义按钮
  335. Widget _customButton({double height, String text, String iconUrl, String textColor, String bgColor, String borderColor, GestureTapCallback onTap}) {
  336. return GestureDetector(
  337. onTap: onTap,
  338. child: Container(
  339. width: double.infinity,
  340. height: height ?? 0,
  341. decoration: BoxDecoration(
  342. border: Border.all(color: HexColor.fromHex(borderColor), width: 0.5),
  343. borderRadius: BorderRadius.circular(height ?? 0 / 2),
  344. color: HexColor.fromHex(bgColor),
  345. ),
  346. child: Row(
  347. mainAxisAlignment: MainAxisAlignment.center,
  348. crossAxisAlignment: CrossAxisAlignment.center,
  349. children: <Widget>[
  350. // icon
  351. CachedNetworkImage(imageUrl: iconUrl, width: 12),
  352. SizedBox(width: 8),
  353. // text
  354. Text(text, style: TextStyle(color: HexColor.fromHex(textColor), fontSize: 15))
  355. ],
  356. ),
  357. ),
  358. );
  359. }
  360. }