基础库
 
 
 
 
 

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