mine_page.dart 17 KB

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