基础库
 
 
 
 
 

347 lines
11 KiB

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_bloc/flutter_bloc.dart';
  3. import 'package:provider/provider.dart';
  4. import 'package:zhiying_comm/pages/login_page/model/login_model.dart';
  5. import 'package:zhiying_comm/zhiying_comm.dart';
  6. import 'package:cached_network_image/cached_network_image.dart';
  7. import 'package:zhiying_comm/util/empty_util.dart';
  8. import 'bloc/bloc.dart';
  9. import 'bloc/login_invite_repository.dart';
  10. import 'model/login_invite_user.dart';
  11. ///
  12. /// 邀请页面
  13. ///
  14. class LoginInvitePage extends StatelessWidget {
  15. @override
  16. Widget build(BuildContext context) {
  17. return Scaffold(
  18. resizeToAvoidBottomInset: false,
  19. backgroundColor: HexColor.fromHex('#FFFFFF'),
  20. body: BlocProvider(
  21. create: (_) => LoginInviteBloc(repostitory: LoginInviteRepository())..add(LoginInviteInitEvent()),
  22. child: LoginInvitePageContainer(),
  23. ),
  24. );
  25. }
  26. }
  27. ///
  28. /// 邀请
  29. class LoginInvitePageContainer extends StatefulWidget {
  30. @override
  31. _LoginInvitePageContainerState createState() => _LoginInvitePageContainerState();
  32. }
  33. class _LoginInvitePageContainerState extends State<LoginInvitePageContainer> {
  34. TextEditingController _editingController;
  35. FocusNode _focusNode;
  36. bool _showInviteInfo = false;
  37. // 是否登录中
  38. bool _isLogging = false;
  39. /// 返回上一页
  40. void _openPop() {
  41. if (Navigator.canPop(context)) {
  42. Navigator.pop(context);
  43. }
  44. }
  45. /// 注册成功跳转
  46. void _successJump(){
  47. RouterUtil.hideKeyboard(context);
  48. Navigator.pushAndRemoveUntil(
  49. context,
  50. MaterialPageRoute(builder: (BuildContext context) => PageFactory.create('homePage', null)),
  51. (Route<dynamic> route) => false,
  52. );
  53. }
  54. /// 输入框输入变化
  55. void _onChange(String string) {
  56. setState(() {
  57. _showInviteInfo = false;
  58. });
  59. print('$string');
  60. if (!EmptyUtil.isEmpty(string) && string.length >= 3) {
  61. _queryInviteInfo(string);
  62. }
  63. }
  64. /// 查询邀请人
  65. void _queryInviteInfo(String inviteNum) {
  66. if (!EmptyUtil.isEmpty(inviteNum) && inviteNum.length < 3) {
  67. return;
  68. }
  69. BlocProvider.of<LoginInviteBloc>(context).add(LoginInviteQueryEvent(num: inviteNum));
  70. }
  71. /// 填写邀请啊吗
  72. void _submitOnClick(LoginInviteUser inviteUser) async {
  73. _focusNode.unfocus();
  74. /// 邀请码
  75. String inviteNum = inviteUser?.userId ?? '';
  76. /// 手机号
  77. UserInfoModel model = await Provider.of<UserInfoNotifier>(context, listen: false)?.getUserInfoModel();
  78. String mobile = model?.mobile ?? '';
  79. if (!EmptyUtil.isEmpty(inviteNum) && !EmptyUtil.isEmpty(mobile)) {
  80. BlocProvider.of<LoginInviteBloc>(context).add(LoginInviteSubmitEvent(mobile: mobile, num: inviteNum));
  81. }
  82. }
  83. @override
  84. void initState() {
  85. _editingController = TextEditingController();
  86. _focusNode = FocusNode();
  87. super.initState();
  88. }
  89. @override
  90. void didChangeDependencies() {
  91. super.didChangeDependencies();
  92. }
  93. @override
  94. void dispose() {
  95. _editingController?.dispose();
  96. _focusNode?.unfocus();
  97. _focusNode?.dispose();
  98. super.dispose();
  99. }
  100. @override
  101. Widget build(BuildContext context) {
  102. return BlocConsumer<LoginInviteBloc, LoginInviteState>(
  103. listener: (context, state) {},
  104. buildWhen: (previous, current) {
  105. /// 提交失败
  106. if (current is LoginInviteSubmitErrorState) {
  107. return false;
  108. }
  109. /// 数据加载出错
  110. if (current is LoginInviteErrorState) {
  111. return false;
  112. }
  113. /// 查询邀请人失败
  114. if(current is LoginInviteQueryErrorState){
  115. return false;
  116. }
  117. /// 邀请人查询成功
  118. if(current is LoginInviteQuerySuccessState){
  119. _showInviteInfo = true;
  120. return true;
  121. }
  122. /// 邀请码成功 跳转
  123. if (current is LoginInviteSubmitSuccess) {
  124. // 缓存数据
  125. Provider.of<UserInfoNotifier>(context, listen: false).setUserInfo(current.model);
  126. _successJump();
  127. return false;
  128. }
  129. return true;
  130. },
  131. builder: (context, state) {
  132. print(state);
  133. if (state is LoginInviteLoadedState) {
  134. return _getMainWidget(state.model, null);
  135. }
  136. if (state is LoginInviteQuerySuccessState) {
  137. return _getMainWidget(state.pageMdel, state.model);
  138. }
  139. /// 骨架屏
  140. return Container();
  141. },
  142. );
  143. }
  144. /// 主视图
  145. Widget _getMainWidget(LoginModel model, LoginInviteUser inviteUser) {
  146. return Column(
  147. children: <Widget>[
  148. /// appbar
  149. _getAppBar(model),
  150. /// 标题
  151. Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 40), child: _getTitleWidget(model)),
  152. /// 输入框
  153. Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 30), child: _getInviteInputWidget(model)),
  154. /// 邀请人信息
  155. Visibility(
  156. visible: inviteUser != null && _showInviteInfo,
  157. child: Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 8), child: _getInviteInfoWidget(inviteUser))),
  158. /// 按钮
  159. Padding(padding: const EdgeInsets.only(left: 27.5, right: 27.5, top: 30), child: _getSubmiBtnWidget(model, inviteUser)),
  160. ],
  161. );
  162. }
  163. /// appBar
  164. Widget _getAppBar(LoginModel model) {
  165. return AppBar(
  166. brightness: Brightness.light,
  167. backgroundColor: HexColor.fromHex('#FFFFFF'),
  168. elevation: 0,
  169. title: Text(
  170. model?.invite?.appBarTitle ?? '登录',
  171. style: TextStyle(color: HexColor.fromHex(model?.invite?.appBarTitleColor ?? '#333333')),
  172. ),
  173. centerTitle: true,
  174. leading: IconButton(
  175. icon: Icon(
  176. Icons.arrow_back_ios,
  177. size: 22,
  178. color: HexColor.fromHex('#333333'),
  179. ),
  180. onPressed: () => _openPop(),
  181. ),
  182. );
  183. }
  184. /// title
  185. Widget _getTitleWidget(LoginModel model) {
  186. return Align(
  187. alignment: Alignment.centerLeft,
  188. child: Text(
  189. model?.invite?.title ?? '输入邀请码',
  190. style: TextStyle(color: HexColor.fromHex(model?.invite?.titleColor ?? '#333333'), fontSize: 25),
  191. ));
  192. }
  193. /// 邀请码输入框
  194. Widget _getInviteInputWidget(LoginModel model) {
  195. return _getCustomInputWidget(
  196. hint: model?.invite?.inputInviteText ?? '请输入邀请码',
  197. controller: _editingController,
  198. focusNode: _focusNode,
  199. onChanged: _onChange,
  200. hintColor: model?.invite?.inputHintColor ?? '#999999',
  201. bgColor: model?.invite?.inputBgColor ?? '#F7F7F7',
  202. textColor: model?.invite?.inputInviteTextColor ?? '#333333',
  203. iconUrl: model?.invite?.inputInviteIcon ?? '');
  204. }
  205. /// 邀请人信息
  206. Widget _getInviteInfoWidget(LoginInviteUser model) {
  207. return Container(
  208. // height: 77.5,
  209. decoration: BoxDecoration(borderRadius: BorderRadius.circular(8), border: Border.all(color: HexColor.fromHex('#E8E8E8'), width: 0.5)),
  210. padding: const EdgeInsets.all(15),
  211. child: Row(
  212. children: <Widget>[
  213. /// 头像
  214. CircleAvatar(
  215. radius: 23.5,
  216. backgroundImage: CachedNetworkImageProvider(model?.avatar ?? ''),
  217. ),
  218. const SizedBox(width: 13),
  219. Column(
  220. mainAxisAlignment: MainAxisAlignment.spaceAround,
  221. crossAxisAlignment: CrossAxisAlignment.start,
  222. children: <Widget>[
  223. /// 名字
  224. Text(
  225. '${model?.nickname}',
  226. style: TextStyle(color: HexColor.fromHex(model?.nickNameColor), fontSize: 13),
  227. ),
  228. /// 邀请
  229. RichText(
  230. text: TextSpan(text: '邀请您进入', style: TextStyle(fontSize: 11, color: HexColor.fromHex(model?.nickNameColor)), children: [
  231. TextSpan(
  232. text: '${model?.appName}',
  233. style: TextStyle(fontSize: 11, color: HexColor.fromHex(model?.appNameColor)),
  234. ),
  235. ]),
  236. )
  237. ],
  238. )
  239. ],
  240. ),
  241. );
  242. }
  243. /// 按钮
  244. Widget _getSubmiBtnWidget(LoginModel model, LoginInviteUser inviteUser) {
  245. return Material(
  246. child: Container(
  247. height: 52,
  248. width: double.infinity,
  249. color: Colors.white,
  250. child: RaisedButton(
  251. child: Text(
  252. model?.invite?.btnSubmitText ?? '进入智莺生活',
  253. style: TextStyle(fontSize: 15),
  254. ),
  255. textColor: HexColor.fromHex(model?.invite?.btnSubmitTextColor ?? '#FFFFFF'),
  256. color: HexColor.fromHex(model?.invite?.btnSubmitBgColor ?? '#FF3939'),
  257. disabledColor: HexColor.fromHex(model?.invite?.btnBanBgColor ?? '#F5F5F5'),
  258. disabledTextColor: HexColor.fromHex(model?.invite?.btnBanTextColor ?? '#999999'),
  259. elevation: 5,
  260. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(52 / 2)),
  261. onPressed: _showInviteInfo && inviteUser != null ? ()=> _submitOnClick(inviteUser) : null,
  262. ),
  263. ),
  264. );
  265. }
  266. /// 自定义输入框
  267. Widget _getCustomInputWidget(
  268. {String hint, String hintColor, String bgColor, String textColor, String iconUrl, TextEditingController controller, ValueChanged<String> onChanged, FocusNode focusNode}) {
  269. var border = OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: HexColor.fromHex(bgColor), width: 0));
  270. return Container(
  271. height: 42,
  272. padding: const EdgeInsets.symmetric(horizontal: 15),
  273. decoration: BoxDecoration(
  274. color: HexColor.fromHex(bgColor),
  275. borderRadius: BorderRadius.circular(8),
  276. ),
  277. child: Row(
  278. mainAxisAlignment: MainAxisAlignment.start,
  279. crossAxisAlignment: CrossAxisAlignment.center,
  280. children: <Widget>[
  281. CachedNetworkImage(
  282. imageUrl: iconUrl ?? '',
  283. width: 10,
  284. ),
  285. Expanded(
  286. child: TextField(
  287. controller: controller,
  288. focusNode: focusNode,
  289. onChanged: onChanged,
  290. expands: false,
  291. style: TextStyle(color: HexColor.fromHex(textColor)),
  292. maxLines: 1,
  293. keyboardType: TextInputType.number,
  294. decoration: InputDecoration(
  295. contentPadding: EdgeInsets.only(top: 30, left: 7.5),
  296. hintText: hint,
  297. hintStyle: TextStyle(fontSize: 13, color: HexColor.fromHex(hintColor)),
  298. hintMaxLines: 1,
  299. filled: true,
  300. fillColor: Colors.transparent,
  301. border: border,
  302. focusedBorder: border,
  303. enabledBorder: border,
  304. disabledBorder: border,
  305. errorBorder: border,
  306. focusedErrorBorder: border,
  307. ),
  308. ),
  309. ),
  310. ],
  311. ),
  312. );
  313. }
  314. }