mine_page.dart 14 KB

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