mine_page.dart 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. return Container(
  235. decoration: BoxDecoration(
  236. borderRadius: BorderRadius.only(
  237. topLeft: Radius.circular(20.w),
  238. topRight: Radius.circular(20.w),
  239. bottomLeft: Radius.circular(8.w),
  240. bottomRight: Radius.circular(8.w)),
  241. gradient: LinearGradient(
  242. begin: Alignment.centerLeft,
  243. end: Alignment.centerRight,
  244. stops: [0.0, 0.1],
  245. colors: ['#FFF8DA'.color, '#FFF1BA'.color])),
  246. margin: EdgeInsets.symmetric(horizontal: 14.w),
  247. child: Column(
  248. children: [
  249. GestureDetector(
  250. onTap: controller.onMemberCardClick,
  251. child: AspectRatio(
  252. aspectRatio: 332 / 75,
  253. child: Container(
  254. //margin: EdgeInsets.symmetric(horizontal: 14.w),
  255. decoration: BoxDecoration(
  256. image: DecorationImage(
  257. image: Assets.images.bgMineMemberCard.provider(),
  258. fit: BoxFit.fill)),
  259. child: Row(
  260. children: [
  261. SizedBox(width: 14.w),
  262. Column(
  263. crossAxisAlignment: CrossAxisAlignment.start,
  264. mainAxisAlignment: MainAxisAlignment.center,
  265. children: [
  266. Row(
  267. children: [
  268. Assets.images.iconMineUnlockVip.image(width: 68.w),
  269. SizedBox(width: 6.5.w),
  270. Assets.images.iconMineSmallVip
  271. .image(width: 21.6.w, height: 21.6.w),
  272. ],
  273. ),
  274. SizedBox(height: 6.w),
  275. buildMemberCardVipDesc()
  276. ],
  277. ),
  278. Spacer(),
  279. buildBuyMemberCardBtn()
  280. ],
  281. ),
  282. ),
  283. ),
  284. ),
  285. Obx(() {
  286. return Visibility(
  287. visible: controller.isLogin,
  288. child: GestureDetector(
  289. onTap:!(controller.memberStatusInfo?.trialed ?? false) ? controller.onMemberTryOutClick : null,
  290. child: Container(
  291. width: double.infinity,
  292. padding: EdgeInsets.symmetric(horizontal: 15.w),
  293. height: 32.w,
  294. child: Row(
  295. children: [
  296. Assets.images.iconMemberVipSign.image(width: 16.w,height: 16.w),
  297. SizedBox(width: 4.w,),
  298. Expanded(
  299. child: Obx(() {
  300. return MineTrialMembershipCountdownText(
  301. memberStatusInfo: controller.memberStatusInfo ?? MemberStatusInfo(level: 0, endTimestamp: 0, expired: false, permanent: false),
  302. trialHasExpiredCallBack: controller.promptWindowPopsCountdownExpires,
  303. );
  304. }),
  305. ),
  306. Visibility(
  307. visible: !(controller.memberStatusInfo?.trialed ?? false),
  308. child: Row(
  309. children: [
  310. Text(
  311. StringName.memberExperienceVipReceive,
  312. style: TextStyle(
  313. fontSize: 13.sp,
  314. color: "#8A5F03".color,
  315. fontWeight: FontWeight.w400
  316. )
  317. ),
  318. Assets.images.iconMemberVipMore.image(width: 16.w,height: 16.w)
  319. ],
  320. )
  321. ),
  322. ],
  323. ),
  324. ),
  325. )
  326. );
  327. })
  328. ],
  329. ),
  330. );
  331. }
  332. Widget buildMemberCardVipDesc() {
  333. return Obx(() {
  334. String desc = '';
  335. if (!controller.isLogin) {
  336. desc = StringName.memberCardNoLoginDesc;
  337. } else if (controller.memberStatusInfo == null ||
  338. controller.memberStatusInfo?.expired == true) {
  339. desc = StringName.memberCardNoVipDesc;
  340. } else if (controller.memberStatusInfo?.expired == false &&
  341. controller.memberStatusInfo?.permanent == true) {
  342. desc = StringName.memberCardPermanentVipDesc;
  343. } else {
  344. desc =
  345. '${DateUtil.fromMillisecondsSinceEpoch('yyyy.MM.dd', controller.memberStatusInfo?.endTimestamp ?? 0)} ${StringName.memberCardExpirationDesc}';
  346. }
  347. return Text(desc,
  348. style: TextStyle(fontSize: 12.sp, color: ColorName.white80));
  349. });
  350. }
  351. Widget buildBuyMemberCardBtn() {
  352. return Obx(() {
  353. String txt = "";
  354. if (!controller.isLogin ||
  355. controller.memberStatusInfo == null ||
  356. controller.memberStatusInfo?.expired == true) {
  357. txt = StringName.memberVipUnlock;
  358. } else if (controller.memberStatusInfo?.expired == false &&
  359. controller.memberStatusInfo?.permanent == true) {
  360. txt = StringName.mineMemberPermanent;
  361. } else {
  362. txt = StringName.memberVipRenew;
  363. }
  364. return Container(
  365. margin: EdgeInsets.only(right: 20.w),
  366. decoration: BoxDecoration(
  367. color: ColorName.white, borderRadius: BorderRadius.circular(26.w)),
  368. padding: EdgeInsets.symmetric(horizontal: 13.w, vertical: 6.w),
  369. child: Text(txt,
  370. style: TextStyle(
  371. fontSize: 12.sp,
  372. color: '#5558FC'.color,
  373. fontWeight: FontWeight.bold)),
  374. );
  375. });
  376. }
  377. Widget buildFunList() {
  378. return Container(
  379. decoration: BoxDecoration(
  380. color: ColorName.white, borderRadius: BorderRadius.circular(12.w)),
  381. margin: EdgeInsets.symmetric(horizontal: 12.w),
  382. padding: EdgeInsets.symmetric(vertical: 5.w),
  383. child: Column(
  384. children: [
  385. buildMineFunItem(
  386. Assets.images.iconMineUrgentContact.provider(),
  387. StringName.mineUrgentContact,
  388. () => controller.onUrgentContactClick()),
  389. buildMineFunItem(Assets.images.iconMineFunShare.provider(),
  390. StringName.mineFunShare, () => controller.onShareClick()),
  391. buildMineFunItem(
  392. Assets.images.iconMineFunCustomerService.provider(),
  393. StringName.mineFunCustomerService,
  394. () => controller.onCustomerServiceClick()),
  395. buildMineFunItem(
  396. Assets.images.iconMineFunPermissionSetting.provider(),
  397. StringName.mineFunPermissionSetting,
  398. () => controller.onPermissionSettingClick()),
  399. buildMineFunItem(
  400. Assets.images.iconMineFunAccountFeedback.provider(),
  401. StringName.mineFunAccountFeedback,
  402. () => controller.onAccountFeedbackClick()),
  403. buildMineFunItem(Assets.images.iconMineFunAbout.provider(),
  404. StringName.mineFunAbout, () => controller.onAboutClick()),
  405. Obx(() {
  406. return Visibility(
  407. visible: controller.isLogin,
  408. child: buildMineFunItem(
  409. Assets.images.iconMineFunLogoutAccount.provider(),
  410. StringName.mineFunLogoutAccount,
  411. () => controller.onLogoutAccountClick()),
  412. );
  413. }),
  414. Obx(() {
  415. return Visibility(
  416. visible: controller.isLogin,
  417. child: buildMineFunItem(
  418. Assets.images.iconMineFunExitAccount.provider(),
  419. StringName.mineFunExitAccount,
  420. () => controller.onFunExitAccountClick()),
  421. );
  422. }),
  423. ],
  424. ),
  425. );
  426. }
  427. Widget buildAvatarView(String avatar) {
  428. return Container(
  429. decoration: BoxDecoration(
  430. shape: BoxShape.circle,
  431. border: Border.all(
  432. color: '#E8E1FF'.color,
  433. width: 1.w,
  434. ),
  435. ),
  436. child: ClipOval(
  437. child: CachedNetworkImage(
  438. width: 54.w, height: 54.w, imageUrl: avatar, fit: BoxFit.cover),
  439. ),
  440. );
  441. }
  442. }