Prechádzať zdrojové kódy

fix:优化一些弹框的样式和跳转逻辑处理。

zhoukun 5 mesiacov pred
rodič
commit
b236a2aa66

BIN
assets/images/img_member_first_week_discount_container.webp


BIN
assets/images/img_member_retain_container.webp


BIN
assets/images/img_member_user_cancels_container.webp


+ 27 - 18
lib/dialog/member_retain_dialog.dart

@@ -41,11 +41,11 @@ class _MemberRetainDialogWidget extends Dialog {
             Stack(
               children: [
                 AspectRatio(
-                    aspectRatio: 1080 / 1296,
+                    aspectRatio: 1110 / 1296,
                     child: Assets.images.imgMemberRetainContainer
                         .image(width: 301.w)),
                 Positioned(
-                  top: 324.w,
+                  top: 360.w,
                   left: 73.w,
                   right: 73.w,
                   child: GestureDetector(
@@ -55,7 +55,20 @@ class _MemberRetainDialogWidget extends Dialog {
                     },
                     child: Container(
                       height: 40.w,
-                      decoration: getPrimaryBtnDecoration(100.w),
+                      decoration: BoxDecoration(
+                        gradient: LinearGradient(
+                          begin: Alignment.centerLeft, // 90度相当于从左到右
+                          end: Alignment.centerRight,
+                          colors: [
+                            Color(0xFF7B7DFF), // #7B7DFF
+                            Color(0xFF6365FF), // #6365FF
+                          ],
+                          stops: [0.0, 1.0],
+                          // 从0%到100%
+                        ),
+                        borderRadius: BorderRadius.circular(40.w / 2.0),
+                      ),
+                      //getPrimaryBtnDecoration(100.w),
                       child: Center(
                         child: Text(StringName.memberContinuePay,
                             style: TextStyle(
@@ -64,23 +77,19 @@ class _MemberRetainDialogWidget extends Dialog {
                     ),
                   ),
                 ),
-                Positioned(
-                  bottom: 0,
-                  left: 0,
-                  right: 0,
-                  child: Center(
-                    child: GestureDetector(
-                      onTap: () {
-                        MemberRetainDialog.dismiss();
-                        cancelClick();
-                      },
-                      child: Assets.images.iconMemberRetainClose
-                          .image(width: 32.w, height: 32.w),
-                    ),
-                  ),
-                )
               ],
             ),
+            SizedBox(height: 24.w,),
+            Center(
+              child: GestureDetector(
+                onTap: () {
+                  MemberRetainDialog.dismiss();
+                  cancelClick();
+                },
+                child: Assets.images.iconMemberRetainClose
+                    .image(width: 32.w, height: 32.w),
+              ),
+            )
           ],
         ),
       ),

+ 2 - 2
lib/module/add_friend/add_friend_dialog_controller.dart

@@ -64,7 +64,7 @@ class AddFriendDialogController extends BaseController {
       if (accountRepository.memberIsExpired()) {
         AddFriendLocateResultDialog.show(confirmOnTap: () {
           FocusScope.of(Get.context!).unfocus();
-          MemberPage.start();
+          MemberPage.start(enterTyp: MemberPageType.addFriendToEnter);
         });
       } else {
         ToastUtil.show(StringName.requestSuccess);
@@ -74,7 +74,7 @@ class AddFriendDialogController extends BaseController {
       if (accountRepository.memberIsExpired()) {
         AddFriendLocateResultDialog.show(confirmOnTap: () {
           FocusScope.of(Get.context!).unfocus();
-          MemberPage.start();
+          MemberPage.start(enterTyp: MemberPageType.addFriendToEnter);
         });
       } else {
         if (error is ServerErrorException) {

+ 64 - 4
lib/module/member/member_controller.dart

@@ -33,13 +33,18 @@ import '../../dialog/wechat_qr_code_dialog.dart';
 import '../../resource/string.gen.dart';
 import '../../sdk/wechat/wechat_share_util.dart';
 import '../../utils/http_handler.dart';
+import '../../utils/mmkv_util.dart';
 import '../../utils/payment_status_manager.dart';
 import '../../widget/animated_switcher_widget.dart';
 import '../browser/browser_view.dart';
+import '../mine/mine_controller.dart';
 import 'member_evaluate_bean.dart';
+import 'member_first_week_discount_dialog.dart';
 import 'member_fun_bean.dart';
 import 'package:apple_pay/apple_pay.dart';
+import 'member_page.dart';
 import 'member_payment_completed_dialog.dart';
+import 'member_user_cancel_pay_dialog.dart';
 
 @injectable
 class MemberController extends BaseController implements PaymentStatusCallback {
@@ -118,12 +123,15 @@ class MemberController extends BaseController implements PaymentStatusCallback {
         "用来遛狗也很方便,再也不用担心狗狗跑丢了,真是个好工具!"),
   ];
 
+  static const String _keMemberPageShowKey = "member_page_show_key";
+
   MemberController(
       this.accountRepository, this.memberRepository, this.paymentStatusManager);
 
   @override
   void onReady() async {
     super.onReady();
+    _isTherePopUpPrompt();
     _startAnimationSwitcher();
     scrollController.addListener(() {
       double offset = scrollController.offset;
@@ -138,6 +146,24 @@ class MemberController extends BaseController implements PaymentStatusCallback {
     refreshMemberData();
   }
 
+  ///是否弹窗提示
+  void _isTherePopUpPrompt() {
+    MemberPageType pageType = Get.arguments ?? MemberPageType.universalAccessEnter;
+    if (pageType == MemberPageType.afeterTrialMemberEnter) {
+      MemberFirstWeekDiscountDialog.show(
+          confirmOnTap: () {
+            onBuyClick();
+          },
+          onPrivacyPolicyClick: () {
+            onPrivacyPolicyClick();
+          },
+          onTermOfServiceClick: () {
+            onTermOfServiceClick();
+          }
+      );
+    }
+  }
+
   void _startAnimationSwitcher() {
     _changeStreamController = AsyncUtil.interval(
         (time) => changeSwitcherContent(), Duration(seconds: 3), -1);
@@ -244,17 +270,46 @@ class MemberController extends BaseController implements PaymentStatusCallback {
       back();
       if (accountRepository.memberIsExpired()) {
         FocusScope.of(Get.context!).unfocus();
-        showRetainDialog();
+        userCancelsPaymentDisplay();
       }
     } else {
       if (accountRepository.memberIsExpired()) {
-        showRetainDialog();
+        userCancelsPaymentDisplay();
       } else {
         back();
       }
     }
   }
 
+  ///用户取消支付展示
+  void userCancelsPaymentDisplay() {
+    if (_isPopBackInProgress) {
+      // 如果正在处理返回逻辑,直接跳过
+      return;
+    }
+    _isPopBackInProgress = true; // 锁定状态
+    //_keMemberPageShowKey
+    String? memberPageKeyStr = KVUtil.getString(_keMemberPageShowKey, '');
+    if ((memberPageKeyStr ?? '').isEmpty && (accountRepository.memberStatusInfo.value?.trialed == false)) {
+      ///永久化存储
+      KVUtil.putString(_keMemberPageShowKey, _keMemberPageShowKey);
+      MemberUserCancelPayDialog.show(payClick: () {
+        //获取会员
+        MineController attributionController = Get.find<MineController>();
+        attributionController.onMemberTryOutClick();
+        _isPopBackInProgress = false;
+      }, cancelClick: () {
+        _isPopBackInProgress = false;
+        if (!Platform.isIOS) {
+          back();
+        }
+      });
+    } else {
+      _isPopBackInProgress = false;
+    }
+  }
+
+  ///支付错误的时候调用
   void showRetainDialog() {
     if (_isPopBackInProgress) {
       // 如果正在处理返回逻辑,直接跳过
@@ -314,6 +369,8 @@ class MemberController extends BaseController implements PaymentStatusCallback {
         ToastUtil.show(StringName.payNotSupport);
       }
     }).catchError((error) {
+      //处理购买失败
+      showRetainDialog();
       if (error is ServerErrorException) {
         if (error.code == ErrorCode.payOrderError) {
           refreshMemberData();
@@ -545,8 +602,11 @@ class MemberController extends BaseController implements PaymentStatusCallback {
   @override
   void onPaymentSuccess(
       String orderNo, PayItemBean paymentWay, GoodsBean storeItemBean) {
-    ///购买成功之后弹出
-    afterTheFirstPurchasePromptSharingBoxPops();
+    MemberPageType pageType = Get.arguments ?? MemberPageType.universalAccessEnter;
+    if (pageType == MemberPageType.addFriendToEnter) {
+      ///购买成功之后弹出
+      afterTheFirstPurchasePromptSharingBoxPops();
+    }
     try {
       WechatQrCodeDialog.dismiss();
       AlipayQrCodeDialog.dismiss();

+ 163 - 0
lib/module/member/member_first_week_discount_dialog.dart

@@ -0,0 +1,163 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.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/utils/common_expand.dart';
+
+import '../../resource/assets.gen.dart';
+import '../../resource/colors.gen.dart';
+
+class MemberFirstWeekDiscountDialog {
+  static void show({
+    VoidCallback? confirmOnTap,
+    VoidCallback? onPrivacyPolicyClick,
+    VoidCallback? onTermOfServiceClick,
+  }) {
+    Get.dialog(
+        SimpleDialog(
+          titlePadding: EdgeInsets.zero,
+          contentPadding: EdgeInsets.zero,
+          insetPadding: EdgeInsets.zero,
+          backgroundColor:Colors.transparent,
+          children: [
+            MemberFirstWeekDiscountDialogTipView(
+                onPrivacyPolicyClick: onPrivacyPolicyClick,
+                onTermOfServiceClick: onTermOfServiceClick,
+                confirmOnTap: confirmOnTap)
+          ],
+        )
+    );
+  }
+}
+
+
+class MemberFirstWeekDiscountDialogTipView extends StatefulWidget {
+  final VoidCallback? onPrivacyPolicyClick;
+  final VoidCallback? onTermOfServiceClick;
+  final VoidCallback? confirmOnTap;
+
+
+  const MemberFirstWeekDiscountDialogTipView({
+    super.key,
+    this.onPrivacyPolicyClick,
+    this.onTermOfServiceClick,
+    required this.confirmOnTap,
+  });
+
+  @override
+  State<MemberFirstWeekDiscountDialogTipView> createState() => _MemberPaymentCompletedTipViewState();
+}
+
+class _MemberPaymentCompletedTipViewState extends State<MemberFirstWeekDiscountDialogTipView> {
+  @override
+  Widget build(BuildContext context) {
+    // TODO: implement build
+    return Container(
+      width: 1.sw,
+      margin: EdgeInsets.only(left: 25.w ,right: 13.w),
+      child: IntrinsicHeight(
+        child: Column(
+          children: [
+            Container(
+              padding: EdgeInsets.only(right: 12.w,),
+              decoration: BoxDecoration(
+                  color: Colors.transparent,
+                  image: DecorationImage(
+                    image: Assets.images.imgMemberFirstWeekDiscountContainer.provider(),
+                    //fit: BoxFit.fill,
+                  )
+              ),
+              child: Column(
+                children: [
+                  SizedBox(
+                    height: 337.w,
+                  ),
+                  GestureDetector(
+                    onTap: () {
+                      Get.back();
+                      widget.confirmOnTap!();
+                    },
+                    child: Container(
+                      decoration: BoxDecoration(
+                        gradient: LinearGradient(
+                          begin: Alignment.centerLeft, // 90度相当于从左到右
+                          end: Alignment.centerRight,
+                          colors: [
+                            Color(0xFF7B7DFF), // #7B7DFF
+                            Color(0xFF6365FF), // #6365FF
+                          ],
+                          stops: [0.0, 1.0],
+                          // 从0%到100%
+                        ),
+                        borderRadius: BorderRadius.circular(40.w / 2.0),
+                      ),
+                      margin: EdgeInsets.symmetric(horizontal: 25.w),
+                      height: 40.w,
+                      alignment: Alignment.center,
+                      child: Text("¥48 立即开通",
+                          style: TextStyle(
+                              fontSize: 14.sp,
+                              color: '#FFFFFF'.color,
+                              fontWeight: FontWeight.w500)
+                      ),
+                    ),
+                  ),
+                  SizedBox(
+                    height: 12.w,
+                  ),
+                  buildPrivacyPolicyView(),
+                  SizedBox(
+                    height: 19.w,
+                  ),
+                ],
+              ),
+            ),
+            SizedBox(height: 20.w,),
+            Center(
+              child: GestureDetector(
+                onTap: () {
+                  Get.back();
+                },
+                child: Assets.images.iconMemberRetainClose
+                    .image(width: 32.w, height: 32.w),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  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 = () {
+                        widget.onPrivacyPolicyClick!();
+                      },
+                    text: '隐私政策',
+                    style: TextStyle(
+                        color: ColorName.black60,
+                        decoration: TextDecoration.underline)),
+                TextSpan(text: '&'),
+                TextSpan(
+                    recognizer: TapGestureRecognizer()
+                      ..onTap = () {
+                        widget.onTermOfServiceClick!();
+                      },
+                    text: '服务条款',
+                    style: TextStyle(
+                        color: ColorName.black60,
+                        decoration: TextDecoration.underline)),
+              ])),
+    );
+  }
+}

+ 16 - 4
lib/module/member/member_page.dart

@@ -20,16 +20,28 @@ import '../../data/consts/payment_type.dart';
 import '../../resource/fonts.gen.dart';
 import '../../resource/string.gen.dart';
 import '../../router/app_pages.dart';
-import '../../utils/common_util.dart';
 import '../../utils/date_util.dart';
 import '../../widget/animated_switcher_widget.dart';
 import 'member_evaluate_bean.dart';
 
+///进入会员类型
+enum MemberPageType {
+  ///通用进入
+  universalAccessEnter,
+  ///倒计时试用完会员进入
+  afeterTrialMemberEnter,
+  ///加好友进入
+  addFriendToEnter,
+}
+
 class MemberPage extends BasePage<MemberController> {
-  const MemberPage({super.key});
 
-  static void start() {
-    Get.toNamed(RoutePath.member);
+  MemberPage({super.key,this.pageType});
+
+  late MemberPageType? pageType = MemberPageType.universalAccessEnter;
+
+  static void start({MemberPageType? enterTyp = MemberPageType.universalAccessEnter}) {
+    Get.toNamed(RoutePath.member,arguments: enterTyp);
   }
 
   @override

+ 97 - 0
lib/module/member/member_user_cancel_pay_dialog.dart

@@ -0,0 +1,97 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:location/resource/assets.gen.dart';
+import 'package:location/resource/string.gen.dart';
+
+class MemberUserCancelPayDialog {
+  static final String _tag = 'MemberUserCancelPayDialog';
+
+  static void show(
+      {required VoidCallback payClick, required VoidCallback cancelClick}) {
+    SmartDialog.show(
+        tag: _tag,
+        backDismiss: false,
+        clickMaskDismiss: false,
+        builder: (_) {
+          return _MemberUserCancelPayDialogWidget(
+              payClick: payClick, cancelClick: cancelClick);
+        });
+  }
+
+  static void dismiss() {
+    SmartDialog.dismiss(tag: _tag);
+  }
+}
+
+class _MemberUserCancelPayDialogWidget extends Dialog {
+  final VoidCallback payClick;
+  final VoidCallback cancelClick;
+
+  const _MemberUserCancelPayDialogWidget(
+      {required this.payClick, required this.cancelClick});
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      child: IntrinsicHeight(
+        child: Column(
+          children: [
+            Stack(
+              children: [
+                AspectRatio(
+                    aspectRatio: 1110 / 1296,
+                    child: Assets.images.imgMemberUserCancelsContainer
+                        .image(width: 301.w)),
+                Positioned(
+                  top: 360.w,
+                  left: 60.w,
+                  right: 60.w,
+                  child: GestureDetector(
+                    onTap: () {
+                      MemberUserCancelPayDialog.dismiss();
+                      payClick();
+                    },
+                    child: Container(
+                      height: 40.w,
+                      decoration: BoxDecoration(
+                        gradient: LinearGradient(
+                          begin: Alignment.centerLeft, // 90度相当于从左到右
+                          end: Alignment.centerRight,
+                          colors: [
+                            Color(0xFF7B7DFF), // #7B7DFF
+                            Color(0xFF6365FF), // #6365FF
+                          ],
+                          stops: [0.0, 1.0],
+                          // 从0%到100%
+                        ),
+                        borderRadius: BorderRadius.circular(40.w / 2.0),
+                      ),
+                      //getPrimaryBtnDecoration(100.w),
+                      child: Center(
+                        child: Text("立即领取",
+                            style: TextStyle(
+                                fontSize: 15.sp, color: Colors.white)),
+                      ),
+                    ),
+                  ),
+                ),
+              ],
+            ),
+            SizedBox(height: 24.w,),
+            Center(
+              child: GestureDetector(
+                onTap: () {
+                  MemberUserCancelPayDialog.dismiss();
+                  cancelClick();
+                },
+                child: Assets.images.iconMemberRetainClose
+                    .image(width: 32.w, height: 32.w),
+              ),
+            )
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 1 - 1
lib/module/mine/mine_countdown_timer_manager.dart

@@ -63,7 +63,7 @@ class MineCountdownTimerManager {
             .memberTrailInfo()
             .then((infoRespons) {
           MineExpirationReminderDialog.show(infoResponse: infoRespons,onDic: () {
-            MemberPage.start();
+            MemberPage.start(enterTyp: MemberPageType.afeterTrialMemberEnter);
           });
           //MineExpirationReminderDialog.show(infoResponse: infoResponse);
         }).catchError((){});

+ 10 - 0
lib/resource/assets.gen.dart

@@ -460,10 +460,18 @@ class $AssetsImagesGen {
   AssetGenImage get imgDialogLocationAlwaysTip3 => const AssetGenImage(
       'assets/images/img_dialog_location_always_tip_3.webp');
 
+  /// File path: assets/images/img_member_first_week_discount_container.webp
+  AssetGenImage get imgMemberFirstWeekDiscountContainer => const AssetGenImage(
+      'assets/images/img_member_first_week_discount_container.webp');
+
   /// File path: assets/images/img_member_retain_container.webp
   AssetGenImage get imgMemberRetainContainer =>
       const AssetGenImage('assets/images/img_member_retain_container.webp');
 
+  /// File path: assets/images/img_member_user_cancels_container.webp
+  AssetGenImage get imgMemberUserCancelsContainer => const AssetGenImage(
+      'assets/images/img_member_user_cancels_container.webp');
+
   /// File path: assets/images/img_track_example.webp
   AssetGenImage get imgTrackExample =>
       const AssetGenImage('assets/images/img_track_example.webp');
@@ -582,7 +590,9 @@ class $AssetsImagesGen {
         imgDialogLocationAlwaysTip1,
         imgDialogLocationAlwaysTip2,
         imgDialogLocationAlwaysTip3,
+        imgMemberFirstWeekDiscountContainer,
         imgMemberRetainContainer,
+        imgMemberUserCancelsContainer,
         imgTrackExample
       ];
 }