基础库
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.
 
 
 
 
 

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