基础库
 
 
 
 
 

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