mine_page.dart 17 KB

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