mine_page.dart 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_screenutil/flutter_screenutil.dart';
  4. import 'package:get/get.dart';
  5. import 'package:location/base/base_page.dart';
  6. import 'package:location/data/bean/member_status_info.dart';
  7. import 'package:location/resource/assets.gen.dart';
  8. import 'package:location/resource/colors.gen.dart';
  9. import 'package:location/resource/string.gen.dart';
  10. import 'package:location/utils/common_expand.dart';
  11. import '../../router/app_pages.dart';
  12. import '../../utils/date_util.dart';
  13. import '../../widget/common_view.dart';
  14. import 'mine_controller.dart';
  15. import 'mine_trial_membership_countdown_text.dart';
  16. class MinePage extends BasePage<MineController> {
  17. const MinePage({super.key});
  18. static void start() {
  19. Get.toNamed(RoutePath.mine);
  20. }
  21. @override
  22. bool immersive() {
  23. return true;
  24. }
  25. @override
  26. Color backgroundColor() {
  27. return '#FAFAFA'.color;
  28. }
  29. @override
  30. Widget buildBody(BuildContext context) {
  31. return Stack(
  32. children: [
  33. Assets.images.bgPageBackground.image(width: double.infinity),
  34. SafeArea(
  35. child: SingleChildScrollView(
  36. child: Column(children: [
  37. SizedBox(height: 70.w),
  38. GestureDetector(
  39. behavior: HitTestBehavior.opaque,
  40. onTap: () => controller.onLoginClick(),
  41. child: Row(
  42. children: [
  43. SizedBox(width: 12.w),
  44. Obx(() {
  45. return controller.isLogin
  46. ? Assets.images.iconMineLogged
  47. .image(width: 54.w, height: 54.w)
  48. : Assets.images.iconMineNoLogin
  49. .image(width: 54.w, height: 54.w);
  50. }),
  51. SizedBox(width: 10.w),
  52. buildLoginInfo(),
  53. Spacer(),
  54. Obx(() {
  55. return Visibility(
  56. visible: controller.isOpenFreeMember == true,
  57. child: GestureDetector(
  58. onTap: controller.onMemberTryOutClick,
  59. child: buildMemberTryOutView()));
  60. })
  61. ],
  62. ),
  63. ),
  64. SizedBox(height: 20.w),
  65. buildExperienceContent(),
  66. SizedBox(height: 16.w),
  67. buildFunList()
  68. ]),
  69. ),
  70. ),
  71. buildBackBtn(),
  72. ],
  73. );
  74. }
  75. Widget buildMineFunItem(
  76. ImageProvider icon, String funName, VoidCallback onTap) {
  77. return GestureDetector(
  78. behavior: HitTestBehavior.translucent,
  79. onTap: onTap,
  80. child: Container(
  81. padding: EdgeInsets.symmetric(vertical: 15.w, horizontal: 12.w),
  82. child: Row(
  83. children: [
  84. Image(image: icon, width: 24.w, height: 24.w),
  85. SizedBox(width: 6.w),
  86. Text(funName,
  87. style: TextStyle(fontSize: 15.sp, color: '#202020'.color)),
  88. Spacer(),
  89. Assets.images.iconMineFunArrow.image(width: 20.w, height: 20.w)
  90. ],
  91. ),
  92. ),
  93. );
  94. }
  95. Widget buildExperienceContent() {
  96. return Stack(
  97. children: [
  98. Column(
  99. children: [
  100. AspectRatio(
  101. aspectRatio: 332 / 57, child: SizedBox(width: double.infinity)),
  102. Obx(() {
  103. return Visibility(
  104. visible: controller.isOpenFreeMember == true,
  105. child: GestureDetector(
  106. onTap: controller.onMemberTryOutClick,
  107. child: Stack(
  108. children: [
  109. Container(
  110. margin: EdgeInsets.symmetric(horizontal: 14.w),
  111. width: double.infinity,
  112. height: 50.w,
  113. decoration: BoxDecoration(
  114. borderRadius: BorderRadius.only(
  115. bottomLeft: Radius.circular(8.w),
  116. bottomRight: Radius.circular(8.w)),
  117. gradient: LinearGradient(
  118. begin: Alignment.centerLeft,
  119. end: Alignment.centerRight,
  120. colors: ['#FFF8DA'.color, '#FFF1BA'.color]),
  121. ),
  122. ),
  123. Positioned(
  124. bottom: 0,
  125. left: 0,
  126. right: 0,
  127. child: Container(
  128. margin: EdgeInsets.symmetric(horizontal: 14.w),
  129. height: 32.w,
  130. child: Row(
  131. children: [
  132. SizedBox(width: 15.w),
  133. Assets.images.iconExperiment
  134. .image(width: 16.w, height: 16.w),
  135. SizedBox(width: 4.w),
  136. Text(StringName.memberExperienceVip,
  137. style: TextStyle(
  138. fontSize: 13.sp, color: '#8A5F03'.color)),
  139. Spacer(),
  140. Text(StringName.memberExperienceVipReceive,
  141. style: TextStyle(
  142. fontSize: 13.sp, color: '#8A5F03'.color)),
  143. Assets.images.iconMemberVipReceiveArrow
  144. .image(width: 16.w, height: 16.w),
  145. SizedBox(width: 13.w),
  146. ],
  147. ),
  148. ),
  149. )
  150. ],
  151. ),
  152. ),
  153. );
  154. })
  155. ],
  156. ),
  157. buildMemberCard()
  158. ],
  159. );
  160. }
  161. Widget buildLoginInfo() {
  162. return Column(
  163. mainAxisAlignment: MainAxisAlignment.center,
  164. crossAxisAlignment: CrossAxisAlignment.start,
  165. children: [
  166. Row(
  167. children: [
  168. Obx(() {
  169. String desc = "";
  170. if (controller.isLogin && controller.phone?.isNotEmpty == true) {
  171. desc = controller.getUserName(controller.phone!);
  172. } else {
  173. desc = StringName.mineAccountGoLogin;
  174. }
  175. return Text(desc,
  176. style: TextStyle(
  177. fontSize: 16.sp,
  178. color: '#333333'.color,
  179. fontWeight: FontWeight.bold));
  180. }),
  181. SizedBox(width: 6.w),
  182. Obx(() {
  183. return Visibility(
  184. visible: controller.isLogin &&
  185. controller.memberStatusInfo != null &&
  186. controller.memberStatusInfo?.expired == false,
  187. child: Assets.images.iconVip.image(width: 28.w));
  188. })
  189. ],
  190. ),
  191. SizedBox(height: 6.w),
  192. buildLoginDesc(),
  193. ],
  194. );
  195. }
  196. Container buildMemberTryOutView() {
  197. return Container(
  198. margin: EdgeInsets.only(right: 16.w),
  199. decoration: BoxDecoration(
  200. color: '#267B7DFF'.color, borderRadius: BorderRadius.circular(26.w)),
  201. padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 5.w),
  202. child: Text(StringName.memberTryOut,
  203. style: TextStyle(fontSize: 12.sp, color: '#8163FF'.color)),
  204. );
  205. }
  206. Widget buildBackBtn() {
  207. return SafeArea(
  208. child: GestureDetector(
  209. onTap: controller.onBack,
  210. child: Container(
  211. margin: EdgeInsets.only(top: 16.w, left: 14.w),
  212. child: CommonView.getBackBtnView())),
  213. );
  214. }
  215. Widget buildLoginDesc() {
  216. return Obx(() {
  217. String txt = '';
  218. if (!controller.isLogin) {
  219. txt = StringName.mineNotLoginDesc;
  220. } else if (controller.memberStatusInfo != null &&
  221. controller.memberStatusInfo?.expired == false) {
  222. txt = StringName.mineVip;
  223. } else {
  224. txt = StringName.mineOpenVip;
  225. }
  226. return Text(txt,
  227. style: TextStyle(fontSize: 13.sp, color: '#727272'.color));
  228. });
  229. }
  230. Widget buildMemberCard() {
  231. print("controllerffemberStatusInfos--${controller.memberStatusInfo}");
  232. return Container(
  233. decoration: BoxDecoration(
  234. borderRadius: BorderRadius.only(
  235. topLeft: Radius.circular(20.w),
  236. topRight: Radius.circular(20.w),
  237. bottomLeft: Radius.circular(8.w),
  238. bottomRight: Radius.circular(8.w)),
  239. gradient: LinearGradient(
  240. begin: Alignment.centerLeft,
  241. end: Alignment.centerRight,
  242. stops: [0.0, 0.1],
  243. colors: ['#FFF8DA'.color, '#FFF1BA'.color])),
  244. margin: EdgeInsets.symmetric(horizontal: 14.w),
  245. child: Column(
  246. children: [
  247. GestureDetector(
  248. onTap: controller.onMemberTryOutClick,
  249. child: AspectRatio(
  250. aspectRatio: 332 / 75,
  251. child: Container(
  252. //margin: EdgeInsets.symmetric(horizontal: 14.w),
  253. decoration: BoxDecoration(
  254. image: DecorationImage(
  255. image: Assets.images.bgMineMemberCard.provider(),
  256. fit: BoxFit.fill)),
  257. child: Row(
  258. children: [
  259. SizedBox(width: 14.w),
  260. Column(
  261. crossAxisAlignment: CrossAxisAlignment.start,
  262. mainAxisAlignment: MainAxisAlignment.center,
  263. children: [
  264. Row(
  265. children: [
  266. Assets.images.iconMineUnlockVip.image(width: 68.w),
  267. SizedBox(width: 6.5.w),
  268. Assets.images.iconMineSmallVip
  269. .image(width: 21.6.w, height: 21.6.w),
  270. ],
  271. ),
  272. SizedBox(height: 6.w),
  273. buildMemberCardVipDesc()
  274. ],
  275. ),
  276. Spacer(),
  277. buildBuyMemberCardBtn()
  278. ],
  279. ),
  280. ),
  281. ),
  282. ),
  283. Obx(() {
  284. return Visibility(
  285. visible: controller.isLogin,
  286. child: GestureDetector(
  287. onTap:!(controller.memberStatusInfo?.trialed ?? false) ? controller.promptWindowPopsCountdownExpires : null,
  288. child: Container(
  289. width: double.infinity,
  290. padding: EdgeInsets.symmetric(horizontal: 15.w),
  291. height: 32.w,
  292. child: Row(
  293. children: [
  294. Assets.images.iconMemberVipSign.image(width: 16.w,height: 16.w),
  295. SizedBox(width: 4.w,),
  296. Expanded(
  297. child: Obx(() {
  298. print("controllerffemberStatusInfos-CT-${controller.memberStatusInfo}");
  299. return MineTrialMembershipCountdownText(
  300. memberStatusInfo: controller.memberStatusInfo ?? MemberStatusInfo(level: 0, endTimestamp: 0, expired: false, permanent: false),
  301. trialHasExpiredCallBack: controller.promptWindowPopsCountdownExpires,
  302. );
  303. }),
  304. ),
  305. Visibility(
  306. visible: !(controller.memberStatusInfo?.trialed ?? false),
  307. child: Row(
  308. children: [
  309. Text(
  310. StringName.memberExperienceVipReceive,
  311. style: TextStyle(
  312. fontSize: 13.sp,
  313. color: "#8A5F03".color,
  314. fontWeight: FontWeight.w400
  315. )
  316. ),
  317. Assets.images.iconMemberVipMore.image(width: 16.w,height: 16.w)
  318. ],
  319. )
  320. ),
  321. ],
  322. ),
  323. ),
  324. )
  325. );
  326. })
  327. ],
  328. ),
  329. );
  330. }
  331. Widget buildMemberCardVipDesc() {
  332. return Obx(() {
  333. String desc = '';
  334. if (!controller.isLogin) {
  335. desc = StringName.memberCardNoLoginDesc;
  336. } else if (controller.memberStatusInfo == null ||
  337. controller.memberStatusInfo?.expired == true) {
  338. desc = StringName.memberCardNoVipDesc;
  339. } else if (controller.memberStatusInfo?.expired == false &&
  340. controller.memberStatusInfo?.permanent == true) {
  341. desc = StringName.memberCardPermanentVipDesc;
  342. } else {
  343. desc =
  344. '${DateUtil.fromMillisecondsSinceEpoch('yyyy.MM.dd', controller.memberStatusInfo?.endTimestamp ?? 0)} ${StringName.memberCardExpirationDesc}';
  345. }
  346. return Text(desc,
  347. style: TextStyle(fontSize: 12.sp, color: ColorName.white80));
  348. });
  349. }
  350. Widget buildBuyMemberCardBtn() {
  351. return Obx(() {
  352. String txt = "";
  353. if (!controller.isLogin ||
  354. controller.memberStatusInfo == null ||
  355. controller.memberStatusInfo?.expired == true) {
  356. txt = StringName.memberVipUnlock;
  357. } else if (controller.memberStatusInfo?.expired == false &&
  358. controller.memberStatusInfo?.permanent == true) {
  359. txt = StringName.mineMemberPermanent;
  360. } else {
  361. txt = StringName.memberVipRenew;
  362. }
  363. return Container(
  364. margin: EdgeInsets.only(right: 20.w),
  365. decoration: BoxDecoration(
  366. color: ColorName.white, borderRadius: BorderRadius.circular(26.w)),
  367. padding: EdgeInsets.symmetric(horizontal: 13.w, vertical: 6.w),
  368. child: Text(txt,
  369. style: TextStyle(
  370. fontSize: 12.sp,
  371. color: '#5558FC'.color,
  372. fontWeight: FontWeight.bold)),
  373. );
  374. });
  375. }
  376. Widget buildFunList() {
  377. return Container(
  378. decoration: BoxDecoration(
  379. color: ColorName.white, borderRadius: BorderRadius.circular(12.w)),
  380. margin: EdgeInsets.symmetric(horizontal: 12.w),
  381. padding: EdgeInsets.symmetric(vertical: 5.w),
  382. child: Column(
  383. children: [
  384. buildMineFunItem(
  385. Assets.images.iconMineUrgentContact.provider(),
  386. StringName.mineUrgentContact,
  387. () => controller.onUrgentContactClick()),
  388. buildMineFunItem(Assets.images.iconMineFunShare.provider(),
  389. StringName.mineFunShare, () => controller.onShareClick()),
  390. buildMineFunItem(
  391. Assets.images.iconMineFunCustomerService.provider(),
  392. StringName.mineFunCustomerService,
  393. () => controller.onCustomerServiceClick()),
  394. buildMineFunItem(
  395. Assets.images.iconMineFunPermissionSetting.provider(),
  396. StringName.mineFunPermissionSetting,
  397. () => controller.onPermissionSettingClick()),
  398. buildMineFunItem(
  399. Assets.images.iconMineFunAccountFeedback.provider(),
  400. StringName.mineFunAccountFeedback,
  401. () => controller.onAccountFeedbackClick()),
  402. buildMineFunItem(Assets.images.iconMineFunAbout.provider(),
  403. StringName.mineFunAbout, () => controller.onAboutClick()),
  404. Obx(() {
  405. return Visibility(
  406. visible: controller.isLogin,
  407. child: buildMineFunItem(
  408. Assets.images.iconMineFunLogoutAccount.provider(),
  409. StringName.mineFunLogoutAccount,
  410. () => controller.onLogoutAccountClick()),
  411. );
  412. }),
  413. Obx(() {
  414. return Visibility(
  415. visible: controller.isLogin,
  416. child: buildMineFunItem(
  417. Assets.images.iconMineFunExitAccount.provider(),
  418. StringName.mineFunExitAccount,
  419. () => controller.onFunExitAccountClick()),
  420. );
  421. }),
  422. ],
  423. ),
  424. );
  425. }
  426. }