Procházet zdrojové kódy

[New]新增会员活动页关闭按钮配置

zhipeng před 11 měsíci
rodič
revize
c5cdc5d5e1

+ 38 - 11
lib/data/repositories/config_repository.dart

@@ -11,7 +11,19 @@ import '../bean/member_pop_up_bean.dart';
 class ConfigRepository {
   ConfigRepository._();
 
-  final enable = false.obs;
+  static const _memberPopUpConfigKey = "member_pop_up";
+  static const _discountPageCloseConfigKey = "discount_page_close";
+
+  final discountShowAfterStore = false.obs;
+
+  final showDiscountClose = true.obs;
+
+  Future<ConfigResponse> requestConfigsData() {
+    return atmobApi
+        .confs(ConfigRequest(
+            confCodes: [_memberPopUpConfigKey, _discountPageCloseConfigKey]))
+        .then(HttpHandler.handle(true));
+  }
 
   void refreshConfig() {
     AsyncUtil.retry(() => requestConfigsData(), Duration(seconds: 3),
@@ -22,21 +34,36 @@ class ConfigRepository {
         debugPrint('refreshConfig....list is empty');
         return;
       }
-      if (list.first.value is Map<String, dynamic>) {
-        final memberPopUpBean =
-            MemberPopUpBean.fromJson(list.first.value as Map<String, dynamic>);
+      for (var config in list) {
+        var key = config.confCode;
+        var value = config.value;
         debugPrint(
-            'refreshConfig....memberPopUpBean: ${memberPopUpBean.toJson()}');
-        enable.value = memberPopUpBean.enable == true;
-        debugPrint('refreshConfig....enable: ${enable.value}');
+            'refreshConfig....key: $key, value: $value, type: ${value.runtimeType}');
+        if (value == null || value is! Map<String, dynamic>) {
+          continue;
+        }
+        switch (key) {
+          case _memberPopUpConfigKey:
+            onMemberPopUpConfigUpdate(value);
+            break;
+          case _discountPageCloseConfigKey:
+            onDiscountPageCloseConfigUpdate(value);
+            break;
+          default:
+            debugPrint('refreshConfig....unknown config key: $key');
+            break;
+        }
       }
     });
   }
 
-  Future<ConfigResponse> requestConfigsData() {
-    return atmobApi
-        .confs(ConfigRequest(confCodes: ['member_pop_up']))
-        .then(HttpHandler.handle(true));
+  void onMemberPopUpConfigUpdate(value) {
+    final memberPopUpBean = MemberPopUpBean.fromJson(value);
+    discountShowAfterStore.value = memberPopUpBean.enable == true;
+  }
+
+  void onDiscountPageCloseConfigUpdate(value) {
+    showDiscountClose.value = value['showClose'] == true;
   }
 }
 

+ 6 - 1
lib/module/store/discount/discount_controller.dart

@@ -3,6 +3,7 @@ import 'package:clean/base/base_controller.dart';
 import 'package:clean/data/bean/payment_way.dart';
 import 'package:clean/data/bean/store_item.dart';
 import 'package:clean/data/consts/constants.dart';
+import 'package:clean/data/repositories/config_repository.dart';
 import 'package:clean/data/repositories/store_repository.dart';
 import 'package:clean/data/repositories/user_repository.dart';
 import 'package:clean/dialog/loading_dialog.dart';
@@ -26,12 +27,15 @@ class DiscountController extends BaseController
 
   final Rxn<PaymentWay> currentSelectedPaymentWay = Rxn<PaymentWay>();
 
+  final isShowBackButton = configRepository.showDiscountClose;
+
   RxBool canUseFreeTrailPlan = isUserCanStartFreeTrial().obs;
 
   @override
   Future<void> onInit() async {
     super.onInit();
     initStoreIndexData();
+    configRepository.refreshConfig();
   }
 
   @override
@@ -43,7 +47,8 @@ class DiscountController extends BaseController
 
   void initStoreIndexData() {
     LoadingDialog.showLoading();
-    storeRepository.storeIndex().timeout(Duration(seconds: 60)).then((indexData) async {
+    storeRepository.storeIndex().timeout(Duration(seconds: 60)).then(
+        (indexData) async {
       storeItems.clear();
       storeItems.addAll(indexData.items);
       currentSelectedStoreItem.value =

+ 146 - 101
lib/module/store/discount/discount_view.dart

@@ -1,15 +1,17 @@
 import 'dart:async';
-import 'package:intl/intl.dart';
-import 'package:clean/data/bean/store_item.dart';
+
 import 'package:clean/base/base_page.dart';
+import 'package:clean/data/bean/store_item.dart';
+import 'package:clean/data/consts/constants.dart';
+import 'package:clean/module/browser/browser_view.dart';
 import 'package:clean/module/store/discount/discount_controller.dart';
 import 'package:clean/utils/expand.dart';
+import 'package:collection/collection.dart';
 import 'package:flutter/Material.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:get/get.dart';
-import 'package:clean/module/browser/browser_view.dart';
-import 'package:collection/collection.dart';
-import 'package:clean/data/consts/constants.dart';
+import 'package:intl/intl.dart';
+
 import '../../../resource/assets.gen.dart';
 import 'count_down_timer.dart';
 import 'func_page_view.dart';
@@ -28,10 +30,13 @@ class DiscountPage extends BasePage<DiscountController> {
   @override
   Widget buildBody(BuildContext context) {
     return Obx(() {
-      bool isSelectFreeItem = controller.currentSelectedStoreItem.value?.freeTrialName != null;
+      bool isSelectFreeItem =
+          controller.currentSelectedStoreItem.value?.freeTrialName != null;
       // 如果有免费试用,则使用免费试用,否则使用第一个
       bool canUseFreeTrailPlan = controller.canUseFreeTrailPlan.value;
-      StoreItem? freeItem = controller.storeItems.firstWhereOrNull((element) => element.freeTrialName != null) ?? controller.storeItems.firstOrNull;
+      StoreItem? freeItem = controller.storeItems
+              .firstWhereOrNull((element) => element.freeTrialName != null) ??
+          controller.storeItems.firstOrNull;
       return Scaffold(
         backgroundColor: "#05050D".color,
         body: Stack(
@@ -51,7 +56,9 @@ class DiscountPage extends BasePage<DiscountController> {
                       _DiscountFreeTrialSpecialRow(
                         item: freeItem,
                         canUseFreeTrailPlan: canUseFreeTrailPlan,
-                        isSelected: controller.currentSelectedStoreItem.value?.id == freeItem.id,
+                        isSelected:
+                            controller.currentSelectedStoreItem.value?.id ==
+                                freeItem.id,
                         onSelect: (title) {
                           controller.currentSelectedStoreItem.value = freeItem;
                         },
@@ -61,7 +68,11 @@ class DiscountPage extends BasePage<DiscountController> {
                     SizedBox(height: 40.h),
                     _MorePlansSection(),
                     SizedBox(height: 5.h),
-                    _OtherPlansSection(items: controller.storeItems.where((element) => element.id != freeItem?.id).toList(), controller: controller),
+                    _OtherPlansSection(
+                        items: controller.storeItems
+                            .where((element) => element.id != freeItem?.id)
+                            .toList(),
+                        controller: controller),
                     SizedBox(height: 100.h),
                   ],
                 ),
@@ -97,16 +108,21 @@ class _AppBar extends StatelessWidget {
   Widget build(BuildContext context) {
     return Row(
       children: [
-        Container(
-          margin: EdgeInsets.only(left: 16.w, top: 14.h),
-          child: GestureDetector(
-            onTap: () {
-              Get.back();
-            },
-            child: Assets.images.iconStoreClose
-                .image(width: 28.w, height: 28.w),
-          ),
-        ),
+        Obx(() {
+          return Visibility(
+            visible: controller.isShowBackButton.value,
+            child: Container(
+              margin: EdgeInsets.only(left: 16.w, top: 14.h),
+              child: GestureDetector(
+                onTap: () {
+                  Get.back();
+                },
+                child: Assets.images.iconStoreClose
+                    .image(width: 28.w, height: 28.w),
+              ),
+            ),
+          );
+        })
       ],
     );
   }
@@ -119,11 +135,9 @@ class _DiscountHeader extends StatelessWidget {
   Widget build(BuildContext context) {
     return Column(
       children: [
-        Assets.images.iconDiscountTitle
-            .image(width: 259.w, height: 55.h),
+        Assets.images.iconDiscountTitle.image(width: 259.w, height: 55.h),
         SizedBox(height: 20.h),
-        Assets.images.iconDiscountPercent
-            .image(width: 195.w, height: 86.h),
+        Assets.images.iconDiscountPercent.image(width: 195.w, height: 86.h),
         SizedBox(height: 13.h),
         Container(
           width: 197.w,
@@ -220,9 +234,7 @@ class _PurchaseSection extends StatelessWidget {
       child: Column(
         children: [
           Text(
-            isSelectFreeItem
-                ?  ""
-                : "Auto-renewalable.Cancel anytime",
+            isSelectFreeItem ? "" : "Auto-renewalable.Cancel anytime",
             style: TextStyle(
               color: Colors.white.withOpacity(0.8),
               fontSize: 12.sp,
@@ -255,39 +267,51 @@ class _PurchaseSection extends StatelessWidget {
             ),
           ),
           SizedBox(height: 5.h),
-          isSelectFreeItem ?
-          Text("No payment now!",
-            style: TextStyle(
-              color: "#57C87A".color,
-              fontSize: 12.sp,
-              fontWeight: FontWeight.w500,
-            ),
-          )
-              :
-          Container(
-            alignment: Alignment.center,
-            width: double.infinity,
-            child: Row(
-              mainAxisAlignment: MainAxisAlignment.center,
-              children: [
-                GestureDetector(
-                  onTap: () {
-                    BrowserPage.start(Constants.privacyPolicy);
-                  },
-                  child: Text("Privacy Policy", style: TextStyle(color: Colors.white.withOpacity(0.8), fontSize: 12.sp, fontWeight: FontWeight.w400)),
-                ),
-                SizedBox(width: 8.w),
-                Text("|", style: TextStyle(color: Colors.white.withOpacity(0.8), fontSize: 12.sp, fontWeight: FontWeight.w400)),
-                SizedBox(width: 8.w),
-                GestureDetector(
-                  onTap: () {
-                    BrowserPage.start(Constants.userAgreement);
-                  },
-                  child: Text("Terms of Service", style: TextStyle(color: Colors.white.withOpacity(0.8), fontSize: 12.sp, fontWeight: FontWeight.w400)),
-                ),
-              ],
-            ),
-          )
+          isSelectFreeItem
+              ? Text(
+                  "No payment now!",
+                  style: TextStyle(
+                    color: "#57C87A".color,
+                    fontSize: 12.sp,
+                    fontWeight: FontWeight.w500,
+                  ),
+                )
+              : Container(
+                  alignment: Alignment.center,
+                  width: double.infinity,
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      GestureDetector(
+                        onTap: () {
+                          BrowserPage.start(Constants.privacyPolicy);
+                        },
+                        child: Text("Privacy Policy",
+                            style: TextStyle(
+                                color: Colors.white.withOpacity(0.8),
+                                fontSize: 12.sp,
+                                fontWeight: FontWeight.w400)),
+                      ),
+                      SizedBox(width: 8.w),
+                      Text("|",
+                          style: TextStyle(
+                              color: Colors.white.withOpacity(0.8),
+                              fontSize: 12.sp,
+                              fontWeight: FontWeight.w400)),
+                      SizedBox(width: 8.w),
+                      GestureDetector(
+                        onTap: () {
+                          BrowserPage.start(Constants.userAgreement);
+                        },
+                        child: Text("Terms of Service",
+                            style: TextStyle(
+                                color: Colors.white.withOpacity(0.8),
+                                fontSize: 12.sp,
+                                fontWeight: FontWeight.w400)),
+                      ),
+                    ],
+                  ),
+                )
         ],
       ),
     );
@@ -306,7 +330,11 @@ class _MorePlansSection extends StatelessWidget {
         children: [
           Assets.images.iconStoreMoreArrow.image(width: 8.w, height: 8.w),
           SizedBox(width: 5.w),
-          Text("More Plans", style: TextStyle(color: 'ffffff'.color.withOpacity(0.7), fontSize: 12.sp, fontWeight: FontWeight.w400)),
+          Text("More Plans",
+              style: TextStyle(
+                  color: 'ffffff'.color.withOpacity(0.7),
+                  fontSize: 12.sp,
+                  fontWeight: FontWeight.w400)),
           SizedBox(width: 5.w),
           Assets.images.iconStoreMoreArrow.image(width: 8.w, height: 8.w),
         ],
@@ -318,7 +346,10 @@ class _MorePlansSection extends StatelessWidget {
 class _OtherPlansSection extends StatelessWidget {
   final List<StoreItem> items;
   final DiscountController controller;
-  const _OtherPlansSection({Key? key, required this.items, required this.controller}) : super(key: key);
+
+  const _OtherPlansSection(
+      {Key? key, required this.items, required this.controller})
+      : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -326,14 +357,13 @@ class _OtherPlansSection extends StatelessWidget {
       return Column(
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
-          ...items.map((item) =>
-              Padding(
+          ...items.map((item) => Padding(
                 padding: EdgeInsets.only(bottom: 12.h),
                 child: _DiscountFreeTrialSpecialRow(
                   item: item,
                   canUseFreeTrailPlan: controller.canUseFreeTrailPlan.value,
-                  isSelected: controller.currentSelectedStoreItem.value?.id ==
-                      item.id,
+                  isSelected:
+                      controller.currentSelectedStoreItem.value?.id == item.id,
                   onSelect: (item) {
                     controller.currentSelectedStoreItem.value = item;
                   },
@@ -355,7 +385,13 @@ class _DiscountFreeTrialSpecialRow extends StatelessWidget {
     return item.freeTrialName != null;
   }
 
-  const _DiscountFreeTrialSpecialRow({Key? key, required this.item, required this.canUseFreeTrailPlan, required this.isSelected, required this.onSelect}) : super(key: key);
+  const _DiscountFreeTrialSpecialRow(
+      {Key? key,
+      required this.item,
+      required this.canUseFreeTrailPlan,
+      required this.isSelected,
+      required this.onSelect})
+      : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -371,17 +407,14 @@ class _DiscountFreeTrialSpecialRow extends StatelessWidget {
               borderRadius: BorderRadius.circular(12.r),
             ),
             child: Padding(
-              padding: EdgeInsets.only(top: 14.h, left: 7.w, right: 9.w, bottom: 2.h),
-              child: Text(
-                  item.freeTrialPriceDesc ?? item.priceDesc ?? "",
+              padding: EdgeInsets.only(
+                  top: 14.h, left: 7.w, right: 9.w, bottom: 2.h),
+              child: Text(item.freeTrialPriceDesc ?? item.priceDesc ?? "",
                   style: TextStyle(
                       color: '#ffffff'.color.withOpacity(0.7),
                       fontSize: 12,
-                      fontWeight: FontWeight.w400
-                  )
-              ),
-            )
-        ),
+                      fontWeight: FontWeight.w400)),
+            )),
       );
     }
 
@@ -424,15 +457,26 @@ class _DiscountFreeTrialSpecialRow extends StatelessWidget {
                 crossAxisAlignment: CrossAxisAlignment.start,
                 mainAxisAlignment: MainAxisAlignment.center,
                 children: [
-                  Text(item.name, style: TextStyle(color: '#ffffff'.color, fontSize: 16.sp, fontWeight: FontWeight.w700)),
-                  Text(item.priceDesc ?? "", style: TextStyle(color: '#ffffff'.color.withOpacity(0.6), fontSize: 12.sp, fontWeight: FontWeight.w400)),
+                  Text(item.name,
+                      style: TextStyle(
+                          color: '#ffffff'.color,
+                          fontSize: 16.sp,
+                          fontWeight: FontWeight.w700)),
+                  Text(item.priceDesc ?? "",
+                      style: TextStyle(
+                          color: '#ffffff'.color.withOpacity(0.6),
+                          fontSize: 12.sp,
+                          fontWeight: FontWeight.w400)),
                 ],
               ),
               Spacer(),
-              Text(amount, style: TextStyle(color: '#ffffff'.color, fontSize: 16.sp, fontWeight: FontWeight.w700)),
+              Text(amount,
+                  style: TextStyle(
+                      color: '#ffffff'.color,
+                      fontSize: 16.sp,
+                      fontWeight: FontWeight.w700)),
             ],
-          )
-      );
+          ));
     }
 
     // 免费标签的容器
@@ -448,8 +492,7 @@ class _DiscountFreeTrialSpecialRow extends StatelessWidget {
                 '#0279FB'.color,
               ],
             ),
-            borderRadius: BorderRadius.all(Radius.circular(20.w))
-        ),
+            borderRadius: BorderRadius.all(Radius.circular(20.w))),
         child: Text(
           'No payment now!',
           style: TextStyle(
@@ -465,8 +508,7 @@ class _DiscountFreeTrialSpecialRow extends StatelessWidget {
     Widget buildBadgeIcon() {
       return Positioned(
           left: -22,
-          child: Assets.images.iconStoreFree.image(width: 30.w, height: 30.w)
-      );
+          child: Assets.images.iconStoreFree.image(width: 30.w, height: 30.w));
     }
 
     // 免费试用标签
@@ -481,29 +523,29 @@ class _DiscountFreeTrialSpecialRow extends StatelessWidget {
               buildBadgeContainer(),
               buildBadgeIcon(),
             ],
-          )
-      );
+          ));
     }
 
     // 主容器
     Widget buildMainContainer() {
       return Container(
         padding: EdgeInsets.all(2),
-        decoration: isSelected ? BoxDecoration(
-          gradient: LinearGradient(
-              begin: Alignment.topLeft,
-              end: Alignment.bottomRight,
-              colors: [
-                '#D2A3FF'.color,
-                '#419CFF'.color,
-                '#01D0FF'.color,
-              ]
-          ),
-          borderRadius: BorderRadius.circular(20.r),
-        ) : BoxDecoration(
-          color: '#ffffff'.color.withOpacity(0.2),
-          borderRadius: BorderRadius.circular(20.r),
-        ),
+        decoration: isSelected
+            ? BoxDecoration(
+                gradient: LinearGradient(
+                    begin: Alignment.topLeft,
+                    end: Alignment.bottomRight,
+                    colors: [
+                      '#D2A3FF'.color,
+                      '#419CFF'.color,
+                      '#01D0FF'.color,
+                    ]),
+                borderRadius: BorderRadius.circular(20.r),
+              )
+            : BoxDecoration(
+                color: '#ffffff'.color.withOpacity(0.2),
+                borderRadius: BorderRadius.circular(20.r),
+              ),
         child: Container(
           height: 74.w,
           decoration: BoxDecoration(
@@ -513,7 +555,10 @@ class _DiscountFreeTrialSpecialRow extends StatelessWidget {
           child: Stack(
             clipBehavior: Clip.none,
             children: [
-              if (canStarFreeTrail) buildTrialNameContent() else buildNormalProductContent(),
+              if (canStarFreeTrail)
+                buildTrialNameContent()
+              else
+                buildNormalProductContent(),
               // 右上角FREE标签
               if (canStarFreeTrail) buildFreeTrialBadge(),
             ],

+ 1 - 1
lib/module/store/store_controller.dart

@@ -56,7 +56,7 @@ class StoreController extends BaseController implements PaymentStatusCallback {
     super.onClose();
     if (isFirstIntoStore() &&
         !userRepository.isVip() &&
-        configRepository.enable.value) {
+        configRepository.discountShowAfterStore.value) {
       Get.toNamed(RoutePath.discount);
       setFirstIntoStore(false);
     }