|
|
@@ -1,11 +1,24 @@
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
+import 'package:flutter/gestures.dart';
|
|
|
+import 'package:flutter/material.dart';
|
|
|
import 'package:flutter/src/widgets/framework.dart';
|
|
|
+import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
import 'package:get/get.dart';
|
|
|
import 'package:get/get_core/src/get_main.dart';
|
|
|
import 'package:location/base/base_page.dart';
|
|
|
import 'package:location/module/member/member_controller.dart';
|
|
|
-
|
|
|
+import 'package:location/resource/assets.gen.dart';
|
|
|
+import 'package:location/resource/colors.gen.dart';
|
|
|
+import 'package:location/utils/common_expand.dart';
|
|
|
+import 'package:location/utils/project_expand.dart';
|
|
|
+import 'package:location/widget/auto_scroll_list_view.dart';
|
|
|
+import '../../data/bean/member_status_info.dart';
|
|
|
+import '../../resource/fonts.gen.dart';
|
|
|
+import '../../resource/string.gen.dart';
|
|
|
import '../../router/app_pages.dart';
|
|
|
+import '../../utils/date_util.dart';
|
|
|
+import '../../widget/animated_switcher_widget.dart';
|
|
|
+import 'member_evaluate_bean.dart';
|
|
|
|
|
|
class MemberPage extends BasePage<MemberController> {
|
|
|
const MemberPage({super.key});
|
|
|
@@ -15,7 +28,479 @@ class MemberPage extends BasePage<MemberController> {
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
+ bool immersive() {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ bool statusBarDarkFont() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
Widget buildBody(BuildContext context) {
|
|
|
- return Text('这是会员页');
|
|
|
+ return Stack(
|
|
|
+ children: [
|
|
|
+ SingleChildScrollView(
|
|
|
+ controller: controller.scrollController,
|
|
|
+ child: Stack(
|
|
|
+ children: [
|
|
|
+ Assets.images.bgMemberHeader.image(width: double.infinity),
|
|
|
+ SafeArea(
|
|
|
+ child: Column(
|
|
|
+ children: [
|
|
|
+ SizedBox(height: 62.w),
|
|
|
+ buildUserInfoView(),
|
|
|
+ SizedBox(height: 26.w),
|
|
|
+ Container(
|
|
|
+ width: double.infinity,
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: BorderRadius.only(
|
|
|
+ topLeft: Radius.circular(14.w),
|
|
|
+ topRight: Radius.circular(14.w)),
|
|
|
+ gradient: LinearGradient(
|
|
|
+ begin: Alignment.topCenter,
|
|
|
+ end: Alignment.bottomCenter,
|
|
|
+ stops: [0.0, 0.1],
|
|
|
+ colors: ['#EFE9FF'.color, Colors.white])),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ SizedBox(height: 23.w),
|
|
|
+ buildGoodsList(),
|
|
|
+ SizedBox(height: 12.w),
|
|
|
+ buildPrivacyPolicyView(),
|
|
|
+ SizedBox(height: 30.w),
|
|
|
+ Padding(
|
|
|
+ padding: EdgeInsets.only(left: 12.w),
|
|
|
+ child: Text(StringName.memberEquityIntroduction,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 16.sp,
|
|
|
+ color: ColorName.black90,
|
|
|
+ fontWeight: FontWeight.bold)),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 19.w),
|
|
|
+ buildFunctionList(),
|
|
|
+ SizedBox(height: 40.w),
|
|
|
+ Padding(
|
|
|
+ padding: EdgeInsets.only(left: 12.w),
|
|
|
+ child: Text(StringName.memberUserEvaluate,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 16.sp,
|
|
|
+ color: ColorName.black90,
|
|
|
+ fontWeight: FontWeight.bold)),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 8.w),
|
|
|
+ buildUserEvaluateList(),
|
|
|
+ SizedBox(height: 20.w),
|
|
|
+ Container(
|
|
|
+ padding: EdgeInsets.all(12.w),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: '#F7F7F7'.color,
|
|
|
+ borderRadius: BorderRadius.circular(6.w)),
|
|
|
+ margin: EdgeInsets.symmetric(horizontal: 12.w),
|
|
|
+ child: Text(StringName.memberTips,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 12.sp, color: '#A7A7A7'.color)),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 100.w)
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ buildHeadBar(),
|
|
|
+ buildMemberBottomView()
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildGoodsList() {
|
|
|
+ return Obx(() {
|
|
|
+ return SizedBox(
|
|
|
+ height: 123.w,
|
|
|
+ child: ListView.builder(
|
|
|
+ padding: EdgeInsets.only(left: 12.w),
|
|
|
+ physics: const BouncingScrollPhysics(
|
|
|
+ parent: AlwaysScrollableScrollPhysics()),
|
|
|
+ scrollDirection: Axis.horizontal,
|
|
|
+ itemBuilder: (BuildContext ctx, int index) {
|
|
|
+ return Obx(() {
|
|
|
+ final item = controller.goodsList[index];
|
|
|
+ bool isSelected = controller.selectedGoods?.id == item.id;
|
|
|
+ return GestureDetector(
|
|
|
+ behavior: HitTestBehavior.translucent,
|
|
|
+ onTap: () => controller.onGoodsItemClick(item),
|
|
|
+ child: Container(
|
|
|
+ margin: EdgeInsets.only(right: 10.w),
|
|
|
+ width: 138.w,
|
|
|
+ height: 123.w,
|
|
|
+ child: Stack(
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ width: double.infinity,
|
|
|
+ height: double.infinity,
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: isSelected
|
|
|
+ ? '#6BC4BAFF'.color
|
|
|
+ : ColorName.white20,
|
|
|
+ borderRadius: BorderRadius.circular(18.w),
|
|
|
+ border: Border.all(
|
|
|
+ color: isSelected
|
|
|
+ ? '#C4BAFF'.color
|
|
|
+ : '#E8E8E8'.color,
|
|
|
+ width: 3.w)),
|
|
|
+ padding: EdgeInsets.only(left: 10.w),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Spacer(flex: 2),
|
|
|
+ Text(
|
|
|
+ item.name,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 14.sp,
|
|
|
+ color: ColorName.black90,
|
|
|
+ fontWeight: FontWeight.bold),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 3.w),
|
|
|
+ Text('¥${item.originalAmount.divideBy100()}',
|
|
|
+ style: TextStyle(
|
|
|
+ decoration: TextDecoration.lineThrough,
|
|
|
+ fontSize: 10.sp,
|
|
|
+ color: ColorName.black60)),
|
|
|
+ Spacer(flex: 1),
|
|
|
+ RichText(
|
|
|
+ text: TextSpan(
|
|
|
+ style: TextStyle(
|
|
|
+ color: isSelected
|
|
|
+ ? '#EA1231'.color
|
|
|
+ : ColorName.black80,
|
|
|
+ fontWeight: FontWeight.bold),
|
|
|
+ children: [
|
|
|
+ TextSpan(
|
|
|
+ text: '¥',
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 20.sp, height: 1)),
|
|
|
+ TextSpan(
|
|
|
+ text: item.amount.divideBy100(),
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 34.sp,
|
|
|
+ height: 1,
|
|
|
+ fontFamily: FontFamily.oppoSans))
|
|
|
+ ])),
|
|
|
+ Padding(
|
|
|
+ padding: EdgeInsets.only(left: 7.w),
|
|
|
+ child: Text(item.description ?? '',
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 12.sp,
|
|
|
+ color: ColorName.black40)),
|
|
|
+ ),
|
|
|
+ Spacer(
|
|
|
+ flex: 1,
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Visibility(
|
|
|
+ visible: item.tag?.isNotEmpty == true,
|
|
|
+ child: Positioned(
|
|
|
+ top: 0,
|
|
|
+ right: 0,
|
|
|
+ child: Container(
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ gradient: LinearGradient(colors: [
|
|
|
+ '#A26CFF'.color,
|
|
|
+ '#FF7CD8'.color,
|
|
|
+ '#898BFF'.color
|
|
|
+ ]),
|
|
|
+ borderRadius: BorderRadius.only(
|
|
|
+ topRight: Radius.circular(11.w),
|
|
|
+ bottomLeft: Radius.circular(11.w))),
|
|
|
+ padding: EdgeInsets.symmetric(
|
|
|
+ horizontal: 10.w, vertical: 4.w),
|
|
|
+ child: Text(item.tag ?? '',
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 12.sp,
|
|
|
+ color: Colors.white)),
|
|
|
+ ),
|
|
|
+ ))
|
|
|
+ ],
|
|
|
+ )),
|
|
|
+ );
|
|
|
+ });
|
|
|
+ },
|
|
|
+ itemCount: controller.goodsList.length),
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildMemberBottomView() {
|
|
|
+ return Align(
|
|
|
+ alignment: Alignment.bottomCenter,
|
|
|
+ child: Container(
|
|
|
+ padding:
|
|
|
+ EdgeInsets.only(left: 12.w, right: 12.w, top: 13.w, bottom: 20.w),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: Colors.white,
|
|
|
+ boxShadow: [
|
|
|
+ BoxShadow(
|
|
|
+ color: Colors.black.withOpacity(0.05),
|
|
|
+ offset: Offset(0, -2),
|
|
|
+ blurRadius: 4)
|
|
|
+ ],
|
|
|
+ borderRadius: BorderRadius.only(
|
|
|
+ topLeft: Radius.circular(16.w), topRight: Radius.circular(16.w)),
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ children: [
|
|
|
+ Text('¥',
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 14.sp,
|
|
|
+ color: '#EA1231'.color,
|
|
|
+ fontWeight: FontWeight.bold)),
|
|
|
+ Text(
|
|
|
+ '168',
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 24.sp,
|
|
|
+ color: '#EA1231'.color,
|
|
|
+ fontWeight: FontWeight.bold),
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ ' / 永久会员',
|
|
|
+ style: TextStyle(fontSize: 12.sp, color: '#000000'.color),
|
|
|
+ ),
|
|
|
+ Spacer(),
|
|
|
+ Container(
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: ColorName.colorPrimary,
|
|
|
+ borderRadius: BorderRadius.circular(100.w)),
|
|
|
+ width: 164.w,
|
|
|
+ height: 44.w,
|
|
|
+ child: Center(
|
|
|
+ child: Text(
|
|
|
+ '立即解锁',
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 15.sp,
|
|
|
+ color: Colors.white,
|
|
|
+ fontWeight: FontWeight.bold),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildUserInfoView() {
|
|
|
+ return Row(
|
|
|
+ children: [
|
|
|
+ SizedBox(width: 20.w),
|
|
|
+ Assets.images.iconMemberAvatar.image(width: 40.w, height: 40.w),
|
|
|
+ SizedBox(width: 10.w),
|
|
|
+ Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Obx(() {
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: controller.onLoginClick,
|
|
|
+ child: Text(
|
|
|
+ controller.phone?.isNotEmpty == true
|
|
|
+ ? controller.getUserName(controller.phone!)
|
|
|
+ : StringName.mineAccountGoLogin,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 16.sp,
|
|
|
+ color: Colors.white,
|
|
|
+ fontWeight: FontWeight.bold)),
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ buildMemberCardVipDesc()
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ Spacer(),
|
|
|
+ Container(
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: '#272F51'.color,
|
|
|
+ border: Border.all(color: '#99CAB0F0'.color, width: 1.w),
|
|
|
+ borderRadius: BorderRadius.circular(100.w),
|
|
|
+ ),
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 6.w),
|
|
|
+ child: Obx(() {
|
|
|
+ return Text(
|
|
|
+ MemberStatusInfo.getLevelDesc(controller.memberStatusInfo),
|
|
|
+ style: TextStyle(fontSize: 12.sp, color: '#D2CCFF'.color));
|
|
|
+ })),
|
|
|
+ SizedBox(width: 18.w)
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildMemberCardVipDesc() {
|
|
|
+ return Obx(() {
|
|
|
+ String desc = '';
|
|
|
+ if (!controller.isLogin) {
|
|
|
+ desc = StringName.memberCardNoLoginDesc;
|
|
|
+ } else if (controller.memberStatusInfo == null ||
|
|
|
+ controller.memberStatusInfo?.expired == true) {
|
|
|
+ desc = StringName.memberCardNoVipDesc;
|
|
|
+ } else if (controller.memberStatusInfo?.expired == false &&
|
|
|
+ controller.memberStatusInfo?.permanent == true) {
|
|
|
+ desc = StringName.memberCardPermanentVipDesc;
|
|
|
+ } else {
|
|
|
+ desc =
|
|
|
+ '${DateUtil.fromMillisecondsSinceEpoch('yyyy.MM.dd', controller.memberStatusInfo?.endTimestamp ?? 0)} ${StringName.memberCardExpirationDesc}';
|
|
|
+ }
|
|
|
+ return Text(desc,
|
|
|
+ style: TextStyle(fontSize: 12.sp, color: Colors.white60));
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildHeadBar() {
|
|
|
+ return Obx(() {
|
|
|
+ return Container(
|
|
|
+ color: ColorName.colorPrimary.withOpacity(controller.toolBarOpacity),
|
|
|
+ child: SafeArea(
|
|
|
+ child: SizedBox(
|
|
|
+ width: double.infinity,
|
|
|
+ height: 56.w,
|
|
|
+ child: Stack(alignment: Alignment.center, children: [
|
|
|
+ Positioned(
|
|
|
+ left: 12.w,
|
|
|
+ child: GestureDetector(
|
|
|
+ onTap: controller.back,
|
|
|
+ child: Assets.images.iconWhiteBack
|
|
|
+ .image(width: 24.w, height: 24.w),
|
|
|
+ )),
|
|
|
+ Container(child: buildVerticalSlideshowWidget())
|
|
|
+ ]),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildVerticalSlideshowWidget() {
|
|
|
+ return Container(
|
|
|
+ width: 220.w,
|
|
|
+ height: 24.w,
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: '#1F000000'.color,
|
|
|
+ borderRadius: BorderRadius.circular(100.w),
|
|
|
+ ),
|
|
|
+ child: Center(
|
|
|
+ child: AnimatedSwitcherWidget(
|
|
|
+ controller: controller.switcherController)),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildPrivacyPolicyView() {
|
|
|
+ return Padding(
|
|
|
+ padding: EdgeInsets.only(left: 12.w),
|
|
|
+ child: RichText(
|
|
|
+ text: TextSpan(
|
|
|
+ style: TextStyle(fontSize: 12.sp, color: ColorName.black40),
|
|
|
+ children: [
|
|
|
+ TextSpan(text: '购买前请先阅读'),
|
|
|
+ TextSpan(
|
|
|
+ recognizer: TapGestureRecognizer()
|
|
|
+ ..onTap = () {
|
|
|
+ controller.onPrivacyPolicyClick();
|
|
|
+ },
|
|
|
+ text: '隐私政策',
|
|
|
+ style: TextStyle(
|
|
|
+ color: ColorName.black60,
|
|
|
+ decoration: TextDecoration.underline)),
|
|
|
+ TextSpan(text: '&'),
|
|
|
+ TextSpan(
|
|
|
+ recognizer: TapGestureRecognizer()
|
|
|
+ ..onTap = () {
|
|
|
+ controller.onTermOfServiceClick();
|
|
|
+ },
|
|
|
+ text: '服务条款',
|
|
|
+ style: TextStyle(
|
|
|
+ color: ColorName.black60,
|
|
|
+ decoration: TextDecoration.underline)),
|
|
|
+ ])),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildFunctionList() {
|
|
|
+ return SizedBox(
|
|
|
+ height: 80.w,
|
|
|
+ child: AutoScrollListView(
|
|
|
+ padding: EdgeInsets.only(left: 12.w),
|
|
|
+ itemBuilder: (ctx, index) {
|
|
|
+ final item = controller.funList[index];
|
|
|
+ return Padding(
|
|
|
+ padding: EdgeInsets.only(right: 20.w),
|
|
|
+ child: Column(
|
|
|
+ children: [
|
|
|
+ Image.asset(item.iconPath, width: 36.w, height: 36.w),
|
|
|
+ Spacer(flex: 3),
|
|
|
+ Text(item.funName,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 12.8.sp,
|
|
|
+ color: ColorName.black90,
|
|
|
+ fontWeight: FontWeight.bold)),
|
|
|
+ Spacer(flex: 2),
|
|
|
+ Text(item.funDesc,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 10.6.sp,
|
|
|
+ color: ColorName.black50,
|
|
|
+ )),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ itemCount: controller.funList.length));
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildUserEvaluateList() {
|
|
|
+ return Column(
|
|
|
+ children: [
|
|
|
+ for (int index = 0; index < controller.evaluateList.length; index++)
|
|
|
+ buildUserEvaluateItem(controller.evaluateList[index],
|
|
|
+ index == controller.evaluateList.length - 1)
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget buildUserEvaluateItem(MemberEvaluateBean item, bool isLast) {
|
|
|
+ return Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ SizedBox(height: 20.w),
|
|
|
+ Row(
|
|
|
+ children: [
|
|
|
+ SizedBox(width: 12.w),
|
|
|
+ Image.asset(item.avatarPath, width: 24.w, height: 24.w),
|
|
|
+ SizedBox(width: 8.w),
|
|
|
+ Text(
|
|
|
+ item.userName,
|
|
|
+ style: TextStyle(fontSize: 14.sp, color: Colors.black),
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ SizedBox(height: 1.w),
|
|
|
+ Padding(
|
|
|
+ padding: EdgeInsets.only(left: 44.w, right: 12.w),
|
|
|
+ child: Text(
|
|
|
+ item.userEvaluate,
|
|
|
+ style: TextStyle(fontSize: 14.sp, color: '#BF000000'.color),
|
|
|
+ )),
|
|
|
+ SizedBox(height: 20.w),
|
|
|
+ Visibility(
|
|
|
+ child: Container(
|
|
|
+ margin: EdgeInsets.only(left: 26.w),
|
|
|
+ width: 288.w,
|
|
|
+ color: '#21000000'.color,
|
|
|
+ height: 1.w),
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ );
|
|
|
}
|
|
|
}
|