Hibok
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.
 
 
 
 
 
 

604 line
20 KiB

  1. import 'package:chat/data/UserData.dart';
  2. import 'package:chat/data/constants.dart';
  3. import 'package:chat/generated/i18n.dart';
  4. import 'package:chat/models/money_change.dart';
  5. import 'package:chat/utils/ChargeMoney.dart';
  6. import 'package:chat/utils/CustomUI.dart';
  7. import 'package:chat/utils/HttpUtil.dart';
  8. import 'package:chat/utils/MessageMgr.dart';
  9. import 'package:chat/utils/ShadowButton.dart';
  10. import 'package:chat/utils/TokenMgr.dart';
  11. import 'package:chat/utils/screen.dart';
  12. import 'package:dio/dio.dart';
  13. import 'package:flutter/material.dart';
  14. import 'package:oktoast/oktoast.dart';
  15. import 'package:provider/provider.dart';
  16. const double PaddingSize = 8;
  17. class VipPage extends StatefulWidget {
  18. VipPage({Key key}) : super(key: key);
  19. _VipPageState createState() => _VipPageState();
  20. }
  21. enum PayWay {
  22. wx,
  23. zfb,
  24. }
  25. class _VipPageState extends State<VipPage> with SingleTickerProviderStateMixin {
  26. TabController tabCtrl;
  27. List vipData = [];
  28. int selectId = 0;
  29. int selectMoney = 0;
  30. int payWay = PayWay.wx.index;
  31. bool isLoadingFish = false;
  32. bool isNormalVip = true;
  33. int subMoney = 0;
  34. List goodsList = [];
  35. Map memberInfo = {
  36. 'CheckNum': 0,
  37. 'PhotoOrAccount': 0,
  38. 'BurnTime': 0,
  39. 'PublishAd': 0,
  40. 'HumanTranslation': 0,
  41. 'ExclusiveCustomer': 0,
  42. 'PremiumUIDisplay': 0,
  43. };
  44. @override
  45. void initState() {
  46. super.initState();
  47. getVipInfo(1);
  48. }
  49. void getVipInfo(type) async {
  50. Map data = {
  51. "userid": UserData().basicInfo.userId,
  52. };
  53. data['sign'] = TokenMgr().getSign(data);
  54. data['type'] = type;
  55. Response res = await HttpUtil().post('goods/member/list',
  56. data: data, failback: () => Navigator.of(context).pop());
  57. Map resData = res.data;
  58. if (resData['code'] == 0 &&
  59. resData['data'] != null &&
  60. resData['data'].length > 0) {
  61. if (type == 2) subMoney = upgradNum(vipData, resData['data']['list']);
  62. memberInfo = resData['data']['memberInfo'];
  63. vipData = resData['data']['list'];
  64. selectId = vipData[0]['Id'];
  65. selectMoney = vipData[0]['TotalPrice'];
  66. isLoadingFish = true;
  67. isNormalVip = type == 1;
  68. setState(() {});
  69. }
  70. }
  71. @override
  72. void dispose() {
  73. super.dispose();
  74. }
  75. @override
  76. Widget build(BuildContext context) {
  77. Widget content = Scaffold(
  78. appBar: AppBar(
  79. backgroundColor: AppColors.NewAppbarBgColor,
  80. title: Text(
  81. I18n.of(context).member_centre,
  82. textScaleFactor: 1.0,
  83. style: TextStyle(color: AppColors.NewAppbarTextColor),
  84. ),
  85. centerTitle: true,
  86. leading: CustomUI.buildCustomLeading(context),
  87. ),
  88. body: SafeArea(
  89. child: Center(
  90. child: Container(
  91. height: MediaQuery.of(context).size.height,
  92. width: MediaQuery.of(context).size.width,
  93. child: _buildBody(),
  94. ),
  95. )));
  96. return CustomUI.buildPageLoading(context, content, !isLoadingFish);
  97. }
  98. Widget _buildBody() {
  99. return ListView(
  100. children: <Widget>[
  101. _buildTips(),
  102. _buildGoodsItemList(),
  103. _buildCommit(),
  104. ],
  105. );
  106. }
  107. //构建注册按钮
  108. Widget _buildCommit() {
  109. Text text = new Text(
  110. UserData().isVip
  111. ? I18n.of(context).renewal_fee
  112. : I18n.of(context).open_immediately,
  113. textScaleFactor: 1.0,
  114. style: TextStyle(fontSize: 17, color: Colors.white));
  115. LinearGradient gradientColor = new LinearGradient(colors: <Color>[
  116. Constants.ConfrimButtonColor,
  117. Constants.ConfrimButtonColor,
  118. ]);
  119. callback() {
  120. if (UserData().isSuperVip && isNormalVip) {
  121. showToast(I18n.of(context).cannot_vip);
  122. return;
  123. }
  124. if (UserData().isVip && !UserData().isSuperVip && !isNormalVip) {
  125. if (subMoney == 0) {
  126. return;
  127. }
  128. CustomUI.buildOneConfirm(
  129. context,
  130. I18n.of(context)
  131. .becomeSvip
  132. .replaceFirst('/s1', subMoney.toString()),
  133. I18n.of(context).determine, () {
  134. HttpUtil().buyVIP(subMoney, 0, 2, context, () {
  135. Navigator.of(context).pop();
  136. MessageMgr().emit('refresh_money');
  137. MessageMgr().emit('update_data');
  138. });
  139. });
  140. return;
  141. }
  142. if (Provider.of<MoneyChangeProvider>(context).money < selectMoney) {
  143. CustomUI.buildOneConfirm(context, I18n.of(context).balance_insufficien,
  144. I18n.of(context).recharge, () {
  145. Navigator.of(context).pop();
  146. ChargeMoney.showChargeSheet(context, () {
  147. setState(() {});
  148. });
  149. });
  150. return;
  151. }
  152. CustomUI.buildOneConfirm(
  153. context,
  154. I18n.of(context).confirm_pay +
  155. selectMoney.toString() +
  156. I18n.of(context).mask_coin,
  157. I18n.of(context).determine, () {
  158. HttpUtil().buyVIP(selectMoney, selectId, isNormalVip ? 1 : 2, context,
  159. () {
  160. Navigator.of(context).pop();
  161. MessageMgr().emit('refresh_money');
  162. MessageMgr().emit('update_data');
  163. });
  164. });
  165. }
  166. return Container(
  167. child: Column(
  168. children: <Widget>[
  169. Row(
  170. crossAxisAlignment: CrossAxisAlignment.center,
  171. children: <Widget>[
  172. Padding(
  173. padding: EdgeInsets.only(left: 28),
  174. child: Text(
  175. I18n.of(context).total,
  176. textScaleFactor: 1.0,
  177. style: TextStyle(fontSize: 15.49),
  178. ),
  179. ),
  180. Padding(
  181. padding: EdgeInsets.only(top: 1),
  182. child: Text(
  183. ' $selectMoney',
  184. textScaleFactor: 1.0,
  185. style: TextStyle(
  186. color: const Color(0xFFE30101),
  187. fontSize: 16,
  188. fontWeight: FontWeight.normal),
  189. ),
  190. ),
  191. Padding(
  192. padding: EdgeInsets.only(left: 2, top: 1),
  193. child: Text(
  194. I18n.of(context).mask_coin,
  195. textScaleFactor: 1.0,
  196. style:
  197. TextStyle(color: const Color(0xFFE30101), fontSize: 15),
  198. ),
  199. ),
  200. ],
  201. ),
  202. Container(
  203. margin: EdgeInsets.only(top: 21, left: 31, right: 31, bottom: 20),
  204. height: 44,
  205. child: ShadowButton().builder(gradientColor, text, callback),
  206. )
  207. ],
  208. ),
  209. );
  210. }
  211. // Widget _buildVerText(String str) {
  212. // List<Widget> child = [];
  213. // List list = str.split(' ');
  214. // list.forEach((str) {
  215. // child.add(Text(
  216. // str,
  217. // style: TextStyle(fontSize: 14, color: Constants.BlackTextColor),
  218. // ));
  219. // });
  220. // return Column(
  221. // mainAxisAlignment: MainAxisAlignment.center,
  222. // children: child,
  223. // );
  224. // }
  225. Widget _buildGoodsItem(month, money, oldMoney, leftTop, value) {
  226. bool isSelect = selectId == value['Id'];
  227. return InkWell(
  228. onTap: () {
  229. setState(() {
  230. selectId = value['Id'];
  231. selectMoney = value['TotalPrice'];
  232. });
  233. },
  234. child: Container(
  235. alignment: Alignment.center,
  236. height: 49.25,
  237. margin: EdgeInsets.only(bottom: 15, left: 12.5, right: 12.5),
  238. decoration: BoxDecoration(
  239. color: Colors.white,
  240. border: Border.all(
  241. width: 1,
  242. color: isSelect
  243. ? const Color(0xFF2D81FF)
  244. : const Color(0xFFC9C9C9)),
  245. boxShadow: [
  246. BoxShadow(
  247. color: isSelect
  248. ? const Color(0x7A2D81FF)
  249. : const Color(0x7ABCBCBC),
  250. offset: Offset(0, 5),
  251. blurRadius: 9,
  252. )
  253. ],
  254. borderRadius: BorderRadius.all(Radius.circular(10))),
  255. child: Stack(
  256. children: <Widget>[
  257. leftTop
  258. ? Positioned(
  259. left: 0,
  260. top: 0,
  261. child: Container(
  262. decoration: BoxDecoration(
  263. borderRadius: BorderRadius.only(
  264. topLeft: Radius.circular(9),
  265. bottomRight: Radius.circular(5)),
  266. gradient: LinearGradient(
  267. begin: Alignment.topCenter,
  268. end: Alignment.bottomCenter,
  269. colors: <Color>[
  270. const Color(0xFFCE0B0B),
  271. const Color(0xFFFF0000),
  272. ]),
  273. ),
  274. padding: EdgeInsets.only(left: 5, right: 5),
  275. child: Text(I18n.of(context).recommend,
  276. textScaleFactor: 1.0,
  277. style:
  278. TextStyle(fontSize: 13, color: Colors.white)),
  279. ))
  280. : Positioned(left: 0, top: 0, child: Container()),
  281. isSelect
  282. ? Positioned(
  283. right: -1,
  284. bottom: 0,
  285. child: Image.asset(
  286. 'assets/images/login/vip_rect2.png',
  287. ),
  288. width: 25,
  289. )
  290. : Positioned(
  291. right: 0,
  292. bottom: 0,
  293. child: Container(),
  294. ),
  295. Container(
  296. height: double.infinity,
  297. child: Row(
  298. mainAxisAlignment: MainAxisAlignment.end,
  299. children: <Widget>[
  300. Expanded(
  301. child: Container(
  302. alignment: Alignment.center,
  303. child: Row(
  304. crossAxisAlignment: CrossAxisAlignment.center,
  305. mainAxisAlignment: MainAxisAlignment.center,
  306. children: <Widget>[
  307. Text('$money',
  308. textScaleFactor: 1.0,
  309. style: TextStyle(
  310. color: const Color(0xFFE30101),
  311. fontSize: 22,
  312. fontWeight: FontWeight.normal)),
  313. Text('${I18n.of(context).mask_coin}',
  314. textScaleFactor: 1.0,
  315. style: TextStyle(
  316. color: const Color(0xFFE30101),
  317. fontSize: 20,
  318. fontWeight: FontWeight.normal)),
  319. ],
  320. )),
  321. ),
  322. Image.asset(
  323. 'assets/images/login/vip_rect3.png',
  324. height: 25,
  325. color: Colors.grey,
  326. ),
  327. Container(
  328. width: 110,
  329. alignment: Alignment.center,
  330. child: Text(month,
  331. textScaleFactor: 1.0,
  332. style: TextStyle(
  333. fontSize: 15, color: Constants.BlackTextColor)),
  334. ),
  335. ],
  336. ),
  337. )
  338. ],
  339. )));
  340. }
  341. Widget buildSelectContainer(str, bool isSelect, bool isNormalVip) {
  342. var color = Constants.BlackTextColor;
  343. return Container(
  344. alignment: Alignment.center,
  345. padding: EdgeInsets.only(bottom: isSelect ? 9 : 12),
  346. decoration: BoxDecoration(
  347. color: Colors.white,
  348. border: Border(
  349. bottom: BorderSide(
  350. color:
  351. isSelect ? const Color(0xFF2D81FF) : Colors.transparent,
  352. width: isSelect ? 4 : 1))),
  353. child: Row(
  354. mainAxisAlignment: MainAxisAlignment.center,
  355. children: <Widget>[
  356. Padding(
  357. padding: EdgeInsets.only(top: 0),
  358. child: Image.asset(
  359. isNormalVip
  360. ? 'assets/images/vip/hy_hy.png'
  361. : 'assets/images/vip/hy_cjhy.png',
  362. width: 18,
  363. ),
  364. ),
  365. SizedBox(width: 5),
  366. Text(str,
  367. textScaleFactor: 1.0,
  368. style: TextStyle(fontSize: 16, color: color))
  369. ],
  370. ),
  371. );
  372. }
  373. Widget _buildGoodsItemList() {
  374. Widget tip = Container(
  375. color: Colors.white,
  376. margin: EdgeInsets.only(bottom: 15),
  377. child: Row(
  378. mainAxisAlignment: MainAxisAlignment.spaceAround,
  379. children: <Widget>[
  380. InkWell(
  381. onTap: isNormalVip
  382. ? null
  383. : () {
  384. getVipInfo(1);
  385. },
  386. child: buildSelectContainer(
  387. I18n.of(context).member, isNormalVip, true)),
  388. InkWell(
  389. onTap: !isNormalVip
  390. ? null
  391. : () {
  392. getVipInfo(2);
  393. },
  394. child: buildSelectContainer(
  395. I18n.of(context).svip, !isNormalVip, false)),
  396. ],
  397. ));
  398. List<Widget> list = [tip];
  399. vipData.forEach((k) {
  400. var name = k['MonthValue'] == 0.5
  401. ? I18n.of(context).half_month
  402. : I18n.of(context)
  403. .month2
  404. .replaceFirst('/s1', k['MonthValue'].toInt().toString());
  405. list.add(_buildGoodsItem(
  406. name, k['TotalPrice'], 72, vipData.indexOf(k) == 0, k));
  407. });
  408. list.add(Container(
  409. height: 1,
  410. color: const Color(0xFFDADADA),
  411. margin: EdgeInsets.only(left: 14, right: 14, bottom: 13),
  412. ));
  413. return Container(
  414. child: Wrap(
  415. alignment: WrapAlignment.spaceEvenly,
  416. children: list,
  417. ),
  418. );
  419. }
  420. double subNum(data) {
  421. return data['MonthPrice'] / 30;
  422. }
  423. //补差价
  424. int upgradNum(vipList, sVipList) {
  425. if (UserData().memberEndTime == '') {
  426. return 0;
  427. }
  428. int day = 0;
  429. const moneyDay = 30;
  430. try {
  431. DateTime endTime = DateTime.parse(UserData().memberEndTime);
  432. day = endTime.difference(DateTime.now()).inDays;
  433. if (day < 0) {
  434. return 0;
  435. }
  436. //小于最小天数按最小天数补
  437. if (day < vipList[0]['MonthValue'] * moneyDay) {
  438. return (day * (subNum(sVipList[0]) - subNum(vipList[0]))).ceil();
  439. }
  440. //大于最大天数按最大天数补
  441. if (day > vipList[vipList.length - 1]['MonthValue'] * moneyDay) {
  442. return (day *
  443. (subNum(sVipList[vipList.length - 1]) -
  444. subNum(vipList[vipList.length - 1])))
  445. .ceil();
  446. }
  447. for (int i = 0; i < vipList.length; i++) {
  448. int standDay = (vipList[i]['MonthValue'] * moneyDay).ceil();
  449. if (day < standDay) {
  450. return (day * (subNum(sVipList[i - 1]) - subNum(vipList[i - 1])))
  451. .ceil();
  452. }
  453. }
  454. } catch (e) {}
  455. return 0;
  456. }
  457. Widget _buildTipItem(leftStr, rightStr, {isShow = true}) {
  458. var color = isShow ? Colors.white : Colors.white.withOpacity(0);
  459. return Container(
  460. margin: EdgeInsets.only(left: 39, right: 5),
  461. child: Row(
  462. children: <Widget>[
  463. Container(
  464. margin: EdgeInsets.only(right: 20.5),
  465. child: Text(
  466. leftStr,
  467. textScaleFactor: 1.0,
  468. style: TextStyle(
  469. color: color, fontSize: 11.44, fontWeight: FontWeight.w600),
  470. ),
  471. ),
  472. Expanded(
  473. child: Container(
  474. padding: EdgeInsets.only(right: 5),
  475. child: Text(
  476. rightStr,
  477. textScaleFactor: 1.0,
  478. style: TextStyle(
  479. color: color,
  480. fontSize: 10.4,
  481. ),
  482. ),
  483. )),
  484. ],
  485. ),
  486. );
  487. }
  488. Widget _buildTips() {
  489. Widget tip = Container(
  490. margin: EdgeInsets.only(left: PaddingSize, right: PaddingSize),
  491. padding: EdgeInsets.only(top: 9, left: 12, bottom: 10),
  492. child: Row(
  493. children: <Widget>[
  494. Image.asset(
  495. 'assets/images/vip/hy_tq.png',
  496. width: 16,
  497. ),
  498. Text(
  499. I18n.of(context).members_privilege,
  500. textScaleFactor: 1.0,
  501. style: TextStyle(color: Colors.white, fontSize: 13.54),
  502. ),
  503. ],
  504. ));
  505. return Container(
  506. color: Colors.white,
  507. width: Screen.width,
  508. child: Stack(
  509. children: <Widget>[
  510. Container(
  511. color: Colors.white,
  512. margin: EdgeInsets.only(left: PaddingSize, right: PaddingSize),
  513. alignment: Alignment.center,
  514. child: Image.asset(
  515. 'assets/images/vip/hy_bg.png',
  516. fit: BoxFit.fitWidth,
  517. ),
  518. ),
  519. // Container(
  520. // height: 150,
  521. // margin: EdgeInsets.only(top:5,left: PaddingSize, right: PaddingSize),
  522. // alignment: Alignment.center,
  523. // child: Text(''),
  524. // decoration: BoxDecoration(
  525. // borderRadius: BorderRadius.circular(12),
  526. // gradient: LinearGradient(
  527. // begin: Alignment.centerLeft,
  528. // end: Alignment.centerRight,
  529. // colors: [Color(0xffff9186), Color(0xffff5599)],
  530. //
  531. // )),
  532. // ),
  533. Positioned(
  534. child: Container(
  535. height: (Screen.width - PaddingSize * 2) / 2.18,
  536. padding: EdgeInsets.only(bottom: 15),
  537. child: Column(
  538. mainAxisAlignment: MainAxisAlignment.spaceAround,
  539. crossAxisAlignment: CrossAxisAlignment.start,
  540. children: <Widget>[
  541. tip,
  542. _buildTipItem(I18n.of(context).see_more,
  543. I18n.of(context).unlimited_see),
  544. _buildTipItem(
  545. I18n.of(context).see_cheaper,
  546. I18n.of(context).free10.replaceFirst('/s1',
  547. memberInfo['PhotoOrAccount'].toString())),
  548. _buildTipItem(
  549. I18n.of(context).see_longer,
  550. I18n.of(context).towto6.replaceFirst('/s1',
  551. (memberInfo['BurnTime'] + 2).toString())),
  552. _buildTipItem(
  553. I18n.of(context).see_better,
  554. I18n.of(context).free_program.replaceFirst(
  555. '/s1', memberInfo['PublishAd'].toString())),
  556. _buildTipItem(I18n.of(context).right5,
  557. I18n.of(context).free_translate,
  558. isShow: !isNormalVip),
  559. _buildTipItem(I18n.of(context).right6,
  560. I18n.of(context).personalTraff,
  561. isShow: !isNormalVip),
  562. ],
  563. ))),
  564. ],
  565. ));
  566. }
  567. }