mine_page.dart 17 KB

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