23 Commits d5f9cdd859 ... 89b5a37140

Author SHA1 Message Date
  glglove 89b5a37140 fix bug 3 months ago
  glglove cd83b20f29 update 3 months ago
  glglove c3fa282dfa update 3 months ago
  glglove e32651aa81 add repair get a quote dialog 3 months ago
  glglove c32dee82b1 update 3 months ago
  glglove e0fb53711f update 3 months ago
  “shanwenxin” 9ef796d00f update service 3 months ago
  liukai f676595c50 Merge remote-tracking branch 'origin/dev_services' into dev_services 3 months ago
  liukai fe36b275fa 合并代码 json生成-2 3 months ago
  glglove ba2d99a680 Merge branch 'dev_services' of http://git.wmzhubo.com/guadoutech/YYHome into dev_services 3 months ago
  glglove 04b439392e update 3 months ago
  liukai f5ef3381b5 Merge remote-tracking branch 'origin/dev_services' into dev_services 3 months ago
  “shanwenxin” 045247c40c Merge branch 'dev_services' of http://git.wmzhubo.com/guadoutech/YYHome into dev_services 3 months ago
  “shanwenxin” 5591935d6b update 3 months ago
  liukai 6eea39072b Merge remote-tracking branch 'origin/dev_services' into dev_services 3 months ago
  glglove b1a96249d4 update service 3 months ago
  liukai da5a00fb0e Merge remote-tracking branch 'origin/dev_services' into dev_services 3 months ago
  liukai b2e404e2bc 拨打电话完善,取消订单之后的通知完善 3 months ago
  glglove 12be05b8aa 修改了int serviceTypeCode 变为 String cleanServiceType 3 months ago
  glglove 4ef1af0a3e update service 3 months ago
  “shanwenxin” f2f9249a8f Merge branch 'dev_services' of http://git.wmzhubo.com/guadoutech/YYHome into dev_services 3 months ago
  “shanwenxin” e978f8e383 评价列表提交,资讯服务详情提交 3 months ago
  liukai 7b3e5726dd inporgress列表 3 months ago
100 changed files with 4639 additions and 3794 deletions
  1. 106 103
      packages/cpt_community/lib/components/garage_card.dart
  2. 16 13
      packages/cpt_community/lib/modules/garage/garagesale_detail/garagesale_detail_vm.dart
  3. 1 0
      packages/cpt_community/lib/modules/my_posts/components/my_posts_sale_rent_item.dart
  4. 3 0
      packages/cpt_profile/lib/modules/setting/setting_view_model.dart
  5. 12 5
      packages/cpt_services/lib/components/chooseAirConditionContent.dart
  6. 9 2
      packages/cpt_services/lib/components/chooseAirConditionContent_state.dart
  7. 60 37
      packages/cpt_services/lib/components/chooseAirConditionContent_vm.dart
  8. 1 1
      packages/cpt_services/lib/components/chooseAirConditionContent_vm.g.dart
  9. 12 4
      packages/cpt_services/lib/components/chooseAirConditionTitle.dart
  10. 25 24
      packages/cpt_services/lib/components/chooseHouseCleanContent.dart
  11. 15 7
      packages/cpt_services/lib/components/chooseHouseCleanContent_state.dart
  12. 86 68
      packages/cpt_services/lib/components/chooseHouseCleanContent_vm.dart
  13. 1 1
      packages/cpt_services/lib/components/chooseHouseCleanContent_vm.g.dart
  14. 6 5
      packages/cpt_services/lib/components/chooseHouseCleanTitle.dart
  15. 12 4
      packages/cpt_services/lib/components/chooseVisitTimeBottomFooter.dart
  16. 25 4
      packages/cpt_services/lib/components/chooseVisitTimeBottomFooter_vm.dart
  17. 1 1
      packages/cpt_services/lib/components/chooseVisitTimeBottomFooter_vm.g.dart
  18. 89 34
      packages/cpt_services/lib/components/chooseVisitTimeContent.dart
  19. 54 22
      packages/cpt_services/lib/components/chooseVisitTimeContent_state.dart
  20. 118 241
      packages/cpt_services/lib/components/chooseVisitTimeContent_vm.dart
  21. 1 1
      packages/cpt_services/lib/components/chooseVisitTimeContent_vm.g.dart
  22. 3 11
      packages/cpt_services/lib/components/chooseVisitTimeTitle.dart
  23. 13 8
      packages/cpt_services/lib/components/chooseVisitTimeTitle_state.dart
  24. 41 18
      packages/cpt_services/lib/components/chooseVisitTimeTitle_vm.dart
  25. 1 1
      packages/cpt_services/lib/components/chooseVisitTimeTitle_vm.g.dart
  26. 3 3
      packages/cpt_services/lib/components/repair_status_card_item.dart
  27. 152 167
      packages/cpt_services/lib/components/status_card_item.dart
  28. 4 4
      packages/cpt_services/lib/components/status_card_item_vm.dart
  29. 1 1
      packages/cpt_services/lib/components/status_card_item_vm.g.dart
  30. 4 3
      packages/cpt_services/lib/components/user_evaluate_card_item.dart
  31. 10 10
      packages/cpt_services/lib/constants_services.dart
  32. 3 3
      packages/cpt_services/lib/modules/services/clean_order_cancel_success/clean_order_cancel_success_page.dart
  33. 58 57
      packages/cpt_services/lib/modules/services/clean_order_detail/cancelOrderDialogContent.dart
  34. 126 127
      packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_page.dart
  35. 4 2
      packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_state.dart
  36. 103 224
      packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_vm.dart
  37. 1 1
      packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_vm.g.dart
  38. 22 28
      packages/cpt_services/lib/modules/services/history/history_page.dart
  39. 3 2
      packages/cpt_services/lib/modules/services/history/history_state.dart
  40. 62 165
      packages/cpt_services/lib/modules/services/history/history_vm.dart
  41. 1 1
      packages/cpt_services/lib/modules/services/history/history_vm.g.dart
  42. 16 12
      packages/cpt_services/lib/modules/services/homeService/home_service_page.dart
  43. 5 4
      packages/cpt_services/lib/modules/services/homeService/home_service_state.dart
  44. 136 122
      packages/cpt_services/lib/modules/services/homeService/home_service_vm.dart
  45. 1 1
      packages/cpt_services/lib/modules/services/homeService/home_service_vm.g.dart
  46. 107 126
      packages/cpt_services/lib/modules/services/homeService/service_card_item.dart
  47. 22 33
      packages/cpt_services/lib/modules/services/inProgress/in_progress_page.dart
  48. 3 2
      packages/cpt_services/lib/modules/services/inProgress/in_progress_state.dart
  49. 61 165
      packages/cpt_services/lib/modules/services/inProgress/in_progress_vm.dart
  50. 1 1
      packages/cpt_services/lib/modules/services/inProgress/in_progress_vm.g.dart
  51. 14 11
      packages/cpt_services/lib/modules/services/repair/repair_page.dart
  52. 87 35
      packages/cpt_services/lib/modules/services/repair_history/history_page.dart
  53. 5 4
      packages/cpt_services/lib/modules/services/repair_history/history_state.dart
  54. 40 164
      packages/cpt_services/lib/modules/services/repair_history/history_vm.dart
  55. 1 1
      packages/cpt_services/lib/modules/services/repair_history/history_vm.g.dart
  56. 15 8
      packages/cpt_services/lib/modules/services/repair_homeService/home_service_page.dart
  57. 3 2
      packages/cpt_services/lib/modules/services/repair_homeService/home_service_state.dart
  58. 81 83
      packages/cpt_services/lib/modules/services/repair_homeService/home_service_vm.dart
  59. 1 1
      packages/cpt_services/lib/modules/services/repair_homeService/home_service_vm.g.dart
  60. 105 124
      packages/cpt_services/lib/modules/services/repair_homeService/service_card_item.dart
  61. 91 35
      packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_page.dart
  62. 5 3
      packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_state.dart
  63. 40 165
      packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_vm.dart
  64. 1 1
      packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_vm.g.dart
  65. 152 142
      packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_page.dart
  66. 12 5
      packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_state.dart
  67. 107 93
      packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_vm.dart
  68. 1 1
      packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_vm.g.dart
  69. 7 6
      packages/cpt_services/lib/modules/services/service_evaluate_create/service_evaluate_create_page.dart
  70. 36 8
      packages/cpt_services/lib/modules/services/service_evaluate_create/service_evaluate_create_vm.dart
  71. 1 1
      packages/cpt_services/lib/modules/services/service_evaluate_create/service_evaluate_create_vm.g.dart
  72. 13 14
      packages/cpt_services/lib/modules/services/service_evaluate_list/service_evaluate_list_page.dart
  73. 111 125
      packages/cpt_services/lib/modules/services/service_evaluate_list/service_evaluate_list_vm.dart
  74. 1 1
      packages/cpt_services/lib/modules/services/service_evaluate_list/service_evaluate_list_vm.g.dart
  75. 188 98
      packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_page.dart
  76. 24 9
      packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_state.dart
  77. 203 129
      packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_vm.dart
  78. 1 1
      packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_vm.g.dart
  79. 5 10
      packages/cpt_services/lib/modules/services/service_pay_success/service_pay_success_page.dart
  80. 110 0
      packages/cpt_services/lib/modules/services/service_repair_detail/getQuoteDialogContent.dart
  81. 163 146
      packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_page.dart
  82. 22 3
      packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_state.dart
  83. 195 82
      packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_vm.dart
  84. 1 1
      packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_vm.g.dart
  85. 94 49
      packages/cpt_services/lib/modules/services/services_main_page.dart
  86. 35 0
      packages/cpt_services/lib/modules/services/services_main_state.dart
  87. 163 0
      packages/cpt_services/lib/modules/services/services_main_vm.dart
  88. 26 0
      packages/cpt_services/lib/modules/services/services_main_vm.g.dart
  89. 17 11
      packages/cpt_services/lib/modules/services/services_page.dart
  90. 5 1
      packages/cpt_services/lib/modules/services/services_state.dart
  91. 18 1
      packages/cpt_services/lib/modules/services/services_vm.dart
  92. 1 1
      packages/cpt_services/lib/modules/services/services_vm.g.dart
  93. 210 194
      packages/cpt_services/lib/respository/services_respository.dart
  94. 93 99
      packages/cpt_services/lib/router/page/services_page_router.gr.dart
  95. 75 0
      packages/cs_domain/lib/entity/garage_sale_history_entity.dart
  96. 47 47
      packages/cs_domain/lib/entity/garage_sale_rent_detail_entity.dart
  97. 139 0
      packages/cs_domain/lib/entity/paid_service_detail_entity.dart
  98. 85 0
      packages/cs_domain/lib/entity/paid_service_entity.dart
  99. 169 0
      packages/cs_domain/lib/entity/paid_service_pay_success_info_entity.dart
  100. 0 0
      packages/cs_domain/lib/entity/repair_service_entity.dart

+ 106 - 103
packages/cpt_community/lib/components/garage_card.dart

@@ -63,129 +63,132 @@ class GarageCard extends StatelessWidget {
     String card_publish_name = card_account?['name']?? "";
     bool card_liked = itemObj.getValue("liked", false);
     int card_likes_count = itemObj.getValue("likes_count", 0);
-    return Column(
-      children: [
-        // 图片
-        Row(
-          mainAxisAlignment: MainAxisAlignment.center,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            Expanded(
-              child: ClipRRect(
-                borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8),),
-                child: MyLoadImage(
-                  card_img,
-                  width: 166.5,
-                  height: 102.5.ap,
-                  isCircle: false,
-                  fit: BoxFit.cover,
-                ),
-              ),
-            ),
-          ],
-        ),
-        // 标题
-        Padding(
-          padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
-          child: Row(
+    return SizedBox(
+      height: cardHeight!,
+      child: Column(
+        children: [
+          // 图片
+          Row(
             mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               Expanded(
-                child: MyTextView(
-                  card_title,
-                  maxLines: 1,
-                  isTextEllipsis: true,
-                  textAlign: TextAlign.left,
-                  textColor: context.appColors.textBlack,
-                  fontSize: 16,
-                  isFontRegular: true,
+                child: ClipRRect(
+                  borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8),),
+                  child: MyLoadImage(
+                    card_img,
+                    width: 166.5,
+                    height: 102.5.ap,
+                    isCircle: false,
+                    fit: BoxFit.cover,
+                  ),
                 ),
               ),
             ],
           ),
-        ),
-        // 价格 及 收藏
-        Padding(
-          padding: const EdgeInsets.only(left: 10, right: 10,top: 0, bottom: 0),
-          child: Row(
-            mainAxisAlignment: MainAxisAlignment.spaceAround,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              Expanded(
-                child: MyTextView(
-                  '$card_price',
-                  maxLines: 1,
-                  isTextEllipsis: true,
-                  textAlign: TextAlign.start,
-                  textColor: ColorUtils.string2Color('#4161D0'),
-                  fontSize: 18,
-                  isFontMedium: true,
+          // 标题
+          Padding(
+            padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: [
+                Expanded(
+                  child: MyTextView(
+                    card_title,
+                    maxLines: 1,
+                    isTextEllipsis: true,
+                    textAlign: TextAlign.left,
+                    textColor: context.appColors.textBlack,
+                    fontSize: 16,
+                    isFontRegular: true,
+                  ),
                 ),
-              ),
-              // 动态的 收藏数
-              CollectionWidget(
-                  collectionNum: card_likes_count,
-                  isCollection: card_liked,
-                  onClickColleciotn: onClickColleciotn,
-              ),
-            ],
+              ],
+            ),
           ),
-        ),
-        // 发布人信息
-        Expanded(
-          child: Padding(
-            padding: EdgeInsets.only(left: (useType == GarageCardUseType.forSale || useType == GarageCardUseType.forRent)?10:0, right: 10, bottom: 17.5),
+          // 价格 及 收藏
+          Padding(
+            padding: const EdgeInsets.only(left: 10, right: 10,top: 0, bottom: 0),
             child: Row(
               mainAxisAlignment: MainAxisAlignment.spaceAround,
               crossAxisAlignment: CrossAxisAlignment.center,
               children: [
-                if (useType == GarageCardUseType.forSale || useType == GarageCardUseType.forRent)
-                  MyLoadImage(
-                    card_avatar,
-                    width: 30,
-                    height: 30,
-                    isCircle: true,
-                  )
-                else
-                  const SizedBox.shrink(),
                 Expanded(
-                  child: Column(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    crossAxisAlignment: CrossAxisAlignment.start,
-                    mainAxisSize: MainAxisSize.max,
-                    children: [
-                      if (useType == GarageCardUseType.forSale || useType == GarageCardUseType.forRent)
+                  child: MyTextView(
+                    '$card_price',
+                    maxLines: 1,
+                    isTextEllipsis: true,
+                    textAlign: TextAlign.start,
+                    textColor: ColorUtils.string2Color('#4161D0'),
+                    fontSize: 18,
+                    isFontMedium: true,
+                  ),
+                ),
+                // 动态的 收藏数
+                CollectionWidget(
+                    collectionNum: card_likes_count,
+                    isCollection: card_liked,
+                    onClickColleciotn: onClickColleciotn,
+                ),
+              ],
+            ),
+          ),
+          // 发布人信息
+          Expanded(
+            child: Padding(
+              padding: EdgeInsets.only(left: (useType == GarageCardUseType.forSale || useType == GarageCardUseType.forRent)?10:0, right: 10, bottom: 17.5),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceAround,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  if (useType == GarageCardUseType.forSale || useType == GarageCardUseType.forRent)
+                    MyLoadImage(
+                      card_avatar,
+                      width: 30,
+                      height: 30,
+                      isCircle: true,
+                    )
+                  else
+                    const SizedBox.shrink(),
+                  Expanded(
+                    child: Column(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      crossAxisAlignment: CrossAxisAlignment.start,
+                      mainAxisSize: MainAxisSize.max,
+                      children: [
+                        if (useType == GarageCardUseType.forSale || useType == GarageCardUseType.forRent)
+                          MyTextView(
+                            card_publish_name,
+                            maxLines: 1,
+                            isTextEllipsis: true,
+                            textAlign: TextAlign.start,
+                            marginLeft: 13,
+                            fontSize: 12,
+                            textColor: ColorUtils.string2Color('#2956B7'),
+                            isFontRegular: true,
+                          )
+                        else
+                          const SizedBox.shrink(),
                         MyTextView(
-                          card_publish_name,
+                          card_created_at,
                           maxLines: 1,
                           isTextEllipsis: true,
                           textAlign: TextAlign.start,
                           marginLeft: 13,
-                          fontSize: 12,
-                          textColor: ColorUtils.string2Color('#2956B7'),
+                          marginTop: 5,
+                          fontSize: 10,
+                          textColor: context.appColors.textBlack,
                           isFontRegular: true,
-                        )
-                      else
-                        const SizedBox.shrink(),
-                      MyTextView(
-                        card_created_at,
-                        maxLines: 1,
-                        isTextEllipsis: true,
-                        textAlign: TextAlign.start,
-                        marginLeft: 13,
-                        marginTop: 5,
-                        fontSize: 10,
-                        textColor: context.appColors.textBlack,
-                        isFontRegular: true,
-                      ),
-                    ]
-                  )
-                ),
-              ]
-            )
-          ),
-        )
-      ],
+                        ).expanded(),
+                      ]
+                    )
+                  ),
+                ]
+              )
+            ),
+          )
+        ],
+      ),
     );
   }
 }

+ 16 - 13
packages/cpt_community/lib/modules/garage/garagesale_detail/garagesale_detail_vm.dart

@@ -5,6 +5,7 @@ import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:plugin_basic/basic_export.dart';
+import 'package:plugin_platform/engine/permission/permission_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
@@ -208,8 +209,8 @@ class GaragesaleDetailVm extends _$GaragesaleDetailVm {
   }
   // 点击 whatsapp
   handlerClickWhatsapp(BuildContext? context,String contactType, String title, int price){
-    // 假设你有一个获取 WhatsApp 号码的方法
-    String whatsappNumber = getContactNumber(contactType); // 你需要实现这个方法
+    // 获取 WhatsApp 号码
+    String whatsappNumber = getContactNumber(contactType); 
     // 构建消息并进行编码
     String message = Uri.encodeComponent("Hello, I am interested in your listing: $title for $price.");
     // 打开WhatsApp
@@ -236,16 +237,18 @@ class GaragesaleDetailVm extends _$GaragesaleDetailVm {
 
   // 拨打电话
   Future<void> makePhoneCall(String phoneNumber) async {
-    final Uri launchUri = Uri(
-      scheme: 'tel',
-      path: phoneNumber,
-    );
-
-    if (await canLaunchUrl(launchUri)) {
-      await launchUrl(launchUri);
-    } else {
-      ToastEngine.show("Could not launch $launchUri");
-      throw 'Could not launch $launchUri';
-    }
+    PermissionEngine().requestCallPhonePermission(() async {
+      final Uri launchUri = Uri(
+        scheme: 'tel',
+        path: phoneNumber,
+      );
+
+      if (await canLaunchUrl(launchUri)) {
+        await launchUrl(launchUri);
+      } else {
+        ToastEngine.show("Could not launch $launchUri");
+        throw 'Could not launch $launchUri';
+      }
+    });
   }
 }

+ 1 - 0
packages/cpt_community/lib/modules/my_posts/components/my_posts_sale_rent_item.dart

@@ -1,5 +1,6 @@
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:shared/utils/color_utils.dart';
 import 'package:shared/utils/log_utils.dart';

+ 3 - 0
packages/cpt_profile/lib/modules/setting/setting_view_model.dart

@@ -44,6 +44,9 @@ class SettingViewModel extends _$SettingViewModel {
         UserConfigService.getInstance().handleLogoutParams();
         // 清除 garagesale category 缓存
         SPUtil.remove(AppConstant.storageGarageCategoryList);
+        // 清除 servives category 缓存
+        SPUtil.remove(AppConstant.storagePaidServiceCategoryList);
+        SPUtil.remove(AppConstant.storageRepairServiceCategoryList);
         //清除全部页面栈去登录页面
         ComponentServiceManager().authService.startAndPopAllLoginPage();
       },

+ 12 - 5
packages/cpt_services/lib/components/chooseAirConditionContent.dart

@@ -2,6 +2,7 @@
 import 'package:cpt_services/components/chooseAirConditionContent_vm.dart';
 import 'package:cpt_services/components/status_card_item.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
@@ -15,18 +16,24 @@ import 'chooseAirConditionContent_vm.dart';
 
 class ChooseAirConditionContent extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
+  final List<PaidServiceDetailProducts> products;
 
-  const ChooseAirConditionContent({Key? key,required this.id, required this.serviceTypeCode}) : super(key: key);
+  const ChooseAirConditionContent({Key? key,required this.id, required this.cleanServiceType, required this.products}) : super(key: key);
   
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(chooseAirConditionContentVmProvider.notifier);
     final state = ref.watch(chooseAirConditionContentVmProvider);
 
-    final totalPrice = ref.watch(chooseAirConditionContentVmProvider.select((state)=>state.totalPrice));
+    // final totalPrice = ref.watch(chooseAirConditionContentVmProvider.select((state)=>state.totalPrice));
 
     useEffect((){
+      vm.setInitPageData(context, {
+        'id': id,
+        'cleanServiceType': cleanServiceType,
+        'products': products,
+      });
       // 组件挂载时执行 - 执行接口请求
       // Future.microtask(() => vm.initPageData());
       return () {
@@ -38,12 +45,12 @@ class ChooseAirConditionContent extends HookConsumerWidget {
         mainAxisAlignment: MainAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.start,
         children: List.generate(state.airConditionList.length, (index){
-          return _buildItem(context, state.airConditionList[index], index, vm, totalPrice);
+          return _buildItem(context, state.airConditionList[index], index, vm,);
         }),
     );
   }
 
-  Widget _buildItem(BuildContext context, AirConditionContentItem airConditionItem, int index, ChooseAirConditionContentVm vm,double totalPrice){
+  Widget _buildItem(BuildContext context, AirConditionContentItem airConditionItem, int index, ChooseAirConditionContentVm vm){
     final title = airConditionItem.name??'';
     final num = airConditionItem.num?? 1;
     final price = airConditionItem.price?? 0;

+ 9 - 2
packages/cpt_services/lib/components/chooseAirConditionContent_state.dart

@@ -1,6 +1,13 @@
 class ChooseAirConditionContentState{
-  // 设置一个get  totalPrice
-  get totalPrice => airConditionList.map((item) => (item.num??0) * (item.price??0)).reduce((before, current) => before + current);
+  //  totalPrice
+  get totalPrice {
+    final prices = checkedServiceList?.map((item) => (item.num ?? 0) * (item.price ?? 0)).toList();
+    return prices?.isNotEmpty == true ? prices?.reduce((before, current) => before + current) : 0;
+  }
+  get checkedServiceList => airConditionList?.where((item) => ((item.num??0)>0? true:false))?.toList() ?? [];
+  // hasCheckdService
+  get hasCheckdService => checkedServiceList?.any((item) => ((item.num??0)>0? true:false)) ?? false;
+
   List<AirConditionContentItem> airConditionList = [];
 
   ChooseAirConditionContentState({

+ 60 - 37
packages/cpt_services/lib/components/chooseAirConditionContent_vm.dart

@@ -1,4 +1,5 @@
 
+import 'package:domain/entity/paid_service_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -13,48 +14,40 @@ import 'chooseAirConditionContent_state.dart';
 part 'chooseAirConditionContent_vm.g.dart';
 
 
-List<Map<String, dynamic>> airConditionList = [
-  {
-    "name": "Hanging air conditioner (unit)",
-    "id": 1,
-    "price": 40.0,
-  },
-  {
-    "name": "Cabinet air conditioner (unit)",
-    "id": 2,
-    "price": 50.0,
-  },
-  {
-    "name": "Cylindrical air conditioner (unit)",
-    "id": 3,
-    "price": 60.0,
-  },
-  {
-    "name": "Central air conditioning (group)",
-    "id": 4,
-    "price": 70.0,
-  },
-];
-
-
-
-
-ChooseAirConditionContentState initState(){
-  Log.d("--------------------------initState---------------------");
-  List<AirConditionContentItem> airConditionListNew = [];
-  airConditionList.forEach((item) {
-    AirConditionContentItem newItem = AirConditionContentItem()..id = item['id']..price = item['price'] as double..name = item['name']..num = 1;
-    airConditionListNew.add(newItem);
-  });
-  return ChooseAirConditionContentState(
-    airConditionList: airConditionListNew,
-  );
-}
 
 @riverpod
 class ChooseAirConditionContentVm extends _$ChooseAirConditionContentVm {
   late ServicesRespository serviceRespositoryInstance;
 
+  List<PaidServiceDetailProducts> _products = [];
+
+  List<Map<String, dynamic>> airConditionList = [];
+
+
+
+  ChooseAirConditionContentState initState(){
+    Log.d("--------------------------initState---------------------");
+    if(airConditionList.isNotEmpty){
+      List<AirConditionContentItem> airConditionListNew = [];
+      airConditionList.forEach((item) {
+        AirConditionContentItem newItem = AirConditionContentItem()
+          ..id = item['id']
+          ..price = double.tryParse(item['price'] ?? '')
+          ..name = item['name']
+          ..num = 0;
+        airConditionListNew.add(newItem);
+      });
+      return ChooseAirConditionContentState(
+        airConditionList: airConditionListNew,
+      );
+    }else {
+      return ChooseAirConditionContentState(
+        airConditionList: [],
+      );
+    }
+
+  }
+
   @override
   ChooseAirConditionContentState build(){
     // 引入数据仓库
@@ -66,6 +59,36 @@ class ChooseAirConditionContentVm extends _$ChooseAirConditionContentVm {
   }
 
 
+
+  setInitPageData(BuildContext context, Map<String, dynamic>? params){
+    Log.d("--------------------------setInitPageData----------$params-----------");
+    _products = params?['products']??[];
+
+    // 渲染一帧后
+    WidgetsBinding.instance.addPostFrameCallback((_){
+      // 修改 state 中 HouseCleanList
+      if(_products != null){
+        if(_products != null && _products.isNotEmpty){
+          List<PaidServiceDetailProducts> products = _products;
+          List<AirConditionContentItem> airConditionListNew = [];
+          products.forEach((item) {
+            AirConditionContentItem newItem = AirConditionContentItem()
+              ..id = item.id
+              ..price = (item.price ?? 0.0).toDouble()
+              ..name = item.name
+              ..num = 0;
+            airConditionListNew.add(newItem);
+          });
+
+          state = state.copyWith(
+            airConditionList: airConditionListNew,
+          );
+        }
+      }
+    });
+  }
+
+
   handlerChangeNum(BuildContext context, int num, int index){
     state.airConditionList[index].num = num;
     state = state.copyWith(

+ 1 - 1
packages/cpt_services/lib/components/chooseAirConditionContent_vm.g.dart

@@ -7,7 +7,7 @@ part of 'chooseAirConditionContent_vm.dart';
 // **************************************************************************
 
 String _$chooseAirConditionContentVmHash() =>
-    r'fa5791b94a90ea6ee0aeab7895adf8b7e4ecb61a';
+    r'54d8f91a4ffe39cc789fd1500b4a8e37b4e0a5b0';
 
 /// See also [ChooseAirConditionContentVm].
 @ProviderFor(ChooseAirConditionContentVm)

+ 12 - 4
packages/cpt_services/lib/components/chooseAirConditionTitle.dart

@@ -15,14 +15,22 @@ import 'chooseAirConditionContent_vm.dart';
 
 class ChooseAirConditionTitle extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
   const ChooseAirConditionTitle(
-      {Key? key,required this.id, required this.serviceTypeCode,}) : super(key: key);
+      {Key? key,required this.id, required this.cleanServiceType,}) : super(key: key);
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final totalPrice = ref.watch(chooseAirConditionContentVmProvider.select((state)=>state.totalPrice));
+    final totalPrice = useState<double>(0.0);
+    ref.listen(
+      chooseAirConditionContentVmProvider.select((state) => state.totalPrice ?? 0.0),
+          (previous, next) {
+          // 处理 totalPrice 变化
+          // print('Total Price: $next');
+          totalPrice.value = next.toDouble();
+      },
+    );
 
     useEffect((){
       // 组件挂载时执行 - 执行接口请求
@@ -50,7 +58,7 @@ class ChooseAirConditionTitle extends HookConsumerWidget {
                   // maxLines: 5,
                 ),
                 MyTextView(
-                  "\$$totalPrice",
+                  "\$${totalPrice.value}",
                   textColor: context.appColors.textPrimary,
                   textAlign: TextAlign.left,
                   isFontMedium: true,

+ 25 - 24
packages/cpt_services/lib/components/chooseHouseCleanContent.dart

@@ -1,10 +1,12 @@
 
 import 'package:cpt_services/components/status_card_item.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:shared/utils/color_utils.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/my_button.dart';
@@ -16,22 +18,21 @@ import 'chooseHouseCleanContent_vm.dart';
 
 class ChooseHouseCleanContent extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
   final String? useScence;
+  final List<PaidServiceDetailProducts> products;
 
-  const ChooseHouseCleanContent({Key? key,required this.id, required this.serviceTypeCode, this.useScence}) : super(key: key);
+  const ChooseHouseCleanContent({Key? key,required this.id, required this.cleanServiceType, required this.products, this.useScence}) : super(key: key);
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(chooseHouseCleanContentVmProvider.notifier);
-    final state = ref.watch(chooseHouseCleanContentVmProvider);
-
-    final totalPrice = ref.watch(chooseHouseCleanContentVmProvider.select((state)=>state.totalPrice));
-
+    List<HouseCleanContentItem>? houseCleanList = ref.watch(chooseHouseCleanContentVmProvider.select((state) => state.houseCleanList));
     useEffect((){
       vm.setInitPageData(context, {
         'id': id,
-        'serviceTypeCode': serviceTypeCode,
+        'cleanServiceType': cleanServiceType,
+        'products': products,
         'useScence': useScence,
       });
       // 组件挂载时执行 - 执行接口请求
@@ -46,30 +47,32 @@ class ChooseHouseCleanContent extends HookConsumerWidget {
       child: Column(
         mainAxisAlignment: MainAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.start,
-        children: List.generate(state.HouseCleanList.length, (index){
-          return _buildItem(context, state.HouseCleanList[index], index, vm);
-        }),
+        children:  houseCleanList != null && houseCleanList.isNotEmpty? List.generate(houseCleanList!.length, (index){
+          HouseCleanContentItem currentItem = houseCleanList![index];
+          // 如何用ref  去watch  state中的 houseCleanList中的第index 变化
+          return _buildItem(context, currentItem, index, vm, ref);
+        }): [],
       ),
     );
   }
 
 
-  Widget _buildItem(BuildContext context, HouseCleanContentItem HouseCleanItem, int index, ChooseHouseCleanContentVm vm){
+  Widget _buildItem(BuildContext context, HouseCleanContentItem HouseCleanItem, int index, ChooseHouseCleanContentVm vm, WidgetRef ref){
     final title = HouseCleanItem.name??'';
     final areaSizeRange = HouseCleanItem.areaSizeRange??'';
     final num = HouseCleanItem.num?? 1;
     final price = HouseCleanItem.price?? 0;
 
-    Log.d("6666  ${HouseCleanItem.isDisable}");
+    // bool isMultileSelect = ref.watch(chooseHouseCleanContentVmProvider.select((state) => state.isMultileSelect))?? false;
     bool isChecked = HouseCleanItem.isChecked??false;
-
-    bool disabled = HouseCleanItem.isDisable??false;
+    bool isDisable = HouseCleanItem.isDisable??false;
     if(useScence !=null){
-      disabled = true;
+      isDisable = true;
     }else {
-      disabled = false;
+      isDisable = false;
     }
-    final isDisable = useState<bool>(disabled);
+    // final isCheckedState = useState<bool>(isChecked);
+    // final isDisable = useState<bool>(disabled);
 
     return Container(
       padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
@@ -116,19 +119,17 @@ class ChooseHouseCleanContent extends HookConsumerWidget {
                 child: MyButton(
                   text: '\$$price',
                   onPressed: (){
-                    Log.d("$isChecked  $isDisable");
-                    if(!isDisable.value){
-                      isChecked = !isChecked;
-                      vm.handlerChangeNum(context, isChecked, index);
+                    if(!isDisable){
+                      vm.handlerChangeItemChecked(context, index);
                     }
                   },
                   minWidth: 80,
                   minHeight: 40,
                   fontSize: 19,
                   fontWeight: FontWeight.w500,
-                  // enable: !isDisable.value,
-                  textColor:  isChecked? context.appColors.textWhite: context.appColors.textPrimary,
-                  backgroundColor: isChecked? context.appColors.textPrimary:context.appColors.textWhite,
+                  enable: !isDisable,
+                  textColor:  !isChecked? context.appColors.textPrimary : context.appColors.textWhite,
+                  backgroundColor: !isChecked ? context.appColors.textWhite : context.appColors.textPrimary,
                   disabledBackgroundColor: context.appColors.disEnableGray,
                   disabledTextColor: context.appColors.textWhite,
                 ),

+ 15 - 7
packages/cpt_services/lib/components/chooseHouseCleanContent_state.dart

@@ -1,18 +1,26 @@
 class ChooseHouseCleanContentState{
-  // 设置一个get  totalPrice
-  // 设置一个get totalPrice
-  get totalPrice => HouseCleanList.map((item) => (item.isChecked ?? false) ? (item.num ?? 1) * (item.price ?? 0) : 0).reduce((before, current) => before + current);
-  List<HouseCleanContentItem> HouseCleanList = [];
+  // totalPrice
+  get totalPrice => houseCleanList?.map((item) => (item.isChecked ?? false) ? (item.num ?? 1) * (item.price ?? 0) : 0).reduce((before, current) => before + current)?? 0;
+  // hasCheckdService
+  get hasCheckdService => houseCleanList?.any((item) => (item.isChecked ?? false)) ?? false;
+  // 选取的服务项目
+  get checkedServiceList => houseCleanList?.where((item) => (item.isChecked ?? false))?.toList() ?? [];
+  List<HouseCleanContentItem>? houseCleanList;
+
+  bool? isMultileSelect;
 
   ChooseHouseCleanContentState({
-    required this.HouseCleanList,
+    this.isMultileSelect = false,
+    required this.houseCleanList,
   });
 
   ChooseHouseCleanContentState copyWith({
-    List<HouseCleanContentItem>? HouseCleanList,
+    bool? isMultileSelect,
+    List<HouseCleanContentItem>? houseCleanList,
   }){
     return ChooseHouseCleanContentState(
-      HouseCleanList: HouseCleanList??this.HouseCleanList,
+      isMultileSelect: isMultileSelect??this.isMultileSelect,
+      houseCleanList: houseCleanList??this.houseCleanList,
     );
   }
 }

+ 86 - 68
packages/cpt_services/lib/components/chooseHouseCleanContent_vm.dart

@@ -1,6 +1,8 @@
 
+import 'package:domain/entity/paid_service_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -13,73 +15,39 @@ import 'chooseHouseCleanContent_state.dart';
 part 'chooseHouseCleanContent_vm.g.dart';
 
 
-List<Map<String, dynamic>> HouseCleanList = [
-  {
-    "name": "House Clean 1(unit)",
-    "id": 1,
-    "price": 40.0,
-    "num":1,
-    "areaSizeRange": "≤600 sqft",
-    "isChecked": false,
-    "isDisable": false,
-  },
-  {
-    "name": "House Clean 2(unit)",
-    "id": 2,
-    "price": 57.0,
-    "num":1,
-    "areaSizeRange": "601-800 sqft",
-    "isChecked": false,
-    "isDisable": false,
-  },
-  {
-    "name": "House Clean 3(unit)",
-    "id": 3,
-    "price": 72.0,
-    "num":1,
-    "areaSizeRange": "801-1000 sqft",
-    "isChecked": false,
-    "isDisable": false,
-  },
-  {
-    "name": "House Clean 3(unit)",
-    "id": 4,
-    "price": 85.0,
-    "num":1,
-    "areaSizeRange": "1001-1200 sqft",
-    "isChecked": false,
-    "isDisable": false,
-  },
-];
-
-
-
-
-
 @riverpod
 class ChooseHouseCleanContentVm extends _$ChooseHouseCleanContentVm {
   late ServicesRespository serviceRespositoryInstance;
 
-  late BuildContext _context;
-  late Map<String, dynamic>? _initProps;
+
+  List<PaidServiceDetailProducts> _products = [];
+
+  List<Map<String, dynamic>> houseCleanList = [];
+
 
   ChooseHouseCleanContentState initState(){
     Log.d("--------------------------initState---------------------");
-    List<HouseCleanContentItem> HouseCleanListNew = [];
-    HouseCleanList.forEach((item) {
-      HouseCleanContentItem newItem = HouseCleanContentItem()
-        ..id = item['id']
-        ..price = item['price'] as double
-        ..name = item['name']
-        ..num = 1
-        ..areaSizeRange = item['areaSizeRange']
-        ..isChecked = item['isChecked']
-        ..isDisable = item['isDisable'];
-        HouseCleanListNew.add(newItem);
-    });
-    return ChooseHouseCleanContentState(
-      HouseCleanList: HouseCleanListNew,
-    );
+    if(houseCleanList.isNotEmpty){
+      List<HouseCleanContentItem> houseCleanListNew = [];
+      houseCleanList.forEach((item) {
+        HouseCleanContentItem newItem = HouseCleanContentItem()
+          ..id = item['id']
+          ..price = item['price'] as double
+          ..name = item['name']
+          ..num = 1
+          ..areaSizeRange = item['areaSizeRange']
+          ..isChecked = item['isChecked']
+          ..isDisable = item['isDisable'];
+        houseCleanListNew.add(newItem);
+      });
+      return ChooseHouseCleanContentState(
+        houseCleanList: houseCleanListNew,
+      );
+    }else {
+      return ChooseHouseCleanContentState(
+        houseCleanList: null,
+      );
+    }
   }
 
   @override
@@ -92,16 +60,66 @@ class ChooseHouseCleanContentVm extends _$ChooseHouseCleanContentVm {
   }
 
   setInitPageData(BuildContext context, Map<String, dynamic>? params){
-    _context = context;
     Log.d("--------------------------setInitPageData----------$params-----------");
-    _initProps = params;
-
+    _products = params?['products']??[];
+
+    // 渲染一帧后
+    WidgetsBinding.instance.addPostFrameCallback((_){
+      // 修改 state 中 HouseCleanList
+      if(_products != null){
+        if(_products != null && _products.isNotEmpty){
+          List<PaidServiceDetailProducts> products = _products;
+          List<HouseCleanContentItem> houseCleanListNew = [];
+          products.forEach((item) {
+            HouseCleanContentItem newItem = HouseCleanContentItem()
+              ..id = item.id
+              ..price = (item.price ?? 0.0).toDouble()
+              ..name = item.name
+              ..num = 1
+              ..areaSizeRange = item.shortDescription
+              ..isChecked = false
+              ..isDisable = false;
+            houseCleanListNew.add(newItem);
+          });
+
+          state = state.copyWith(
+            houseCleanList: houseCleanListNew,
+          );
+        }
+      }
+    });
   }
 
-  handlerChangeNum(BuildContext context, bool isChecked, int index){
-    state.HouseCleanList[index].isChecked = isChecked;
-    state = state.copyWith(
-      HouseCleanList: state.HouseCleanList,
-    );
+  // 修改 item 的选中状态
+  handlerChangeItemChecked(BuildContext context, int index){
+    bool isMultileSelect = state.isMultileSelect?? false;
+    if(isMultileSelect == true){
+      // 允许多选
+      List<HouseCleanContentItem> newHouseCleanList = state.houseCleanList!;
+      bool isChecked = newHouseCleanList?[index]?.isChecked??false;
+      newHouseCleanList?[index].isChecked = !isChecked;
+      state = state.copyWith(
+        houseCleanList: newHouseCleanList,
+      );
+    }else {
+      // 只允许单选  需要重置其他item的选择状态
+      List<HouseCleanContentItem> newHouseCleanList = List.from(state.houseCleanList!);
+      bool isChecked = newHouseCleanList?[index]?.isChecked??false;
+      for (int i = 0; i < newHouseCleanList.length; i++) {
+        if(i == index){
+          if(isChecked){
+            newHouseCleanList[i].isChecked = false;
+          }else{
+            newHouseCleanList[i].isChecked = true;
+          }
+        }else {
+          newHouseCleanList[i].isChecked = false;
+        }
+      }
+      state = state.copyWith(
+        houseCleanList: newHouseCleanList,
+      );
+      Log.d("3433: ${state.houseCleanList}");
+    }
   }
 }

+ 1 - 1
packages/cpt_services/lib/components/chooseHouseCleanContent_vm.g.dart

@@ -7,7 +7,7 @@ part of 'chooseHouseCleanContent_vm.dart';
 // **************************************************************************
 
 String _$chooseHouseCleanContentVmHash() =>
-    r'2f810b6f7f58c4f52a4f0c97e23d837511d3d3e7';
+    r'acb10c35766b4580f8f01dd53555e24817941f1e';
 
 /// See also [ChooseHouseCleanContentVm].
 @ProviderFor(ChooseHouseCleanContentVm)

+ 6 - 5
packages/cpt_services/lib/components/chooseHouseCleanTitle.dart

@@ -1,6 +1,9 @@
 
 import 'package:cpt_services/components/chooseHouseCleanContent_vm.dart';
+import 'package:cpt_services/components/chooseVisitTimeContent_vm.dart';
+import 'package:cpt_services/components/chooseVisitTimeTitle_vm.dart';
 import 'package:cpt_services/modules/services/service_clean_detail/service_clean_detail_vm.dart';
+import 'package:cpt_services/modules/services/service_order_confirm/service_order_confirm_vm.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
@@ -15,18 +18,16 @@ import 'package:widgets/widget_export.dart';
 
 class ChooseHouseCleanTitle extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
   const ChooseHouseCleanTitle(
-      {Key? key,required this.id, required this.serviceTypeCode,}) : super(key: key);
+      {Key? key,required this.id, required this.cleanServiceType,}) : super(key: key);
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final totalPrice = ref.watch(chooseHouseCleanContentVmProvider.select((state)=>state.totalPrice));
-
+    num totalPrice = ref.watch(chooseHouseCleanContentVmProvider.select((state) => state.totalPrice??0.0));
     useEffect((){
       // 组件挂载时执行 - 执行接口请求
-      // Future.microtask(() => vm.initPageData());
       return () {
         // 组件卸载时执行
       };

+ 12 - 4
packages/cpt_services/lib/components/chooseVisitTimeBottomFooter.dart

@@ -13,18 +13,26 @@ import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
 import 'package:widgets/my_cart_num.dart';
 
+import '../modules/services/service_order_confirm/service_order_confirm_vm.dart';
+
 class ChooseVisitTimeBottomFooter extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
-  const ChooseVisitTimeBottomFooter({Key? key,required this.id, required this.serviceTypeCode}) : super(key: key);
+  const ChooseVisitTimeBottomFooter({Key? key,required this.id, required this.cleanServiceType}) : super(key: key);
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(chooseVisitTimeBottomFooterVmProvider.notifier);
     final state = ref.watch(chooseVisitTimeBottomFooterVmProvider);
 
-    final totalPrice = ref.watch(chooseVisitTimeContentVmProvider.select((state) => state.totalPrice));
+    num cleanServiceToast = ref.watch(serviceOrderConfirmVmProvider.select((state) => state.cleanServiceToTalCost??0.0));
+
+    num extraPrice = ref.watch(chooseVisitTimeContentVmProvider.select((state) => state.extraTotalCost??0.0));
+
+    num totalPrice = cleanServiceToast + extraPrice;
+
+
 
     useEffect((){
       // 组件挂载时执行 - 执行接口请求
@@ -86,7 +94,7 @@ class ChooseVisitTimeBottomFooter extends HookConsumerWidget {
                 ),
               ),
             ).onTap((){
-              vm.handlerClickVisitTimeConfirm(context, id: id , serviceTypeCode: serviceTypeCode);
+              vm.handlerClickVisitTimeConfirm(context, id: id , cleanServiceType: cleanServiceType);
             }),
           ),
         ],

+ 25 - 4
packages/cpt_services/lib/components/chooseVisitTimeBottomFooter_vm.dart

@@ -1,7 +1,9 @@
 
+import 'package:cpt_services/components/chooseVisitTimeTitle_vm.dart';
 import 'package:cpt_services/modules/services/service_order_confirm/service_order_confirm_vm.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -9,6 +11,7 @@ import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/dialog/dialog_content_wrap.dart';
 
 import '../../../respository/services_respository.dart';
+import 'chooseVisitTimeContent_vm.dart';
 
 part 'chooseVisitTimeBottomFooter_vm.g.dart';
 
@@ -62,10 +65,28 @@ class ChooseVisitTimeBottomFooterVm extends _$ChooseVisitTimeBottomFooterVm {
     // );
   }
 
-  handlerClickVisitTimeConfirm(BuildContext context,{required int id, required int serviceTypeCode} ){
+  // 预约时间点击了confirm
+  handlerClickVisitTimeConfirm(BuildContext context,{required int id, required String cleanServiceType} ){
     Log.d("handlerClickVisitTimeConfirm");
-    // 关闭 visitTime 弹框
-    final serviceOrderConfrimVm = ref.read(serviceOrderConfirmVmProvider.notifier);
-    serviceOrderConfrimVm.handlerHideVisitTimeDialog();
+    final visitTimeContentVm = ref.read(chooseVisitTimeContentVmProvider.notifier);
+    if(visitTimeContentVm.state.allSelectedTimeList !=null && visitTimeContentVm.state.allSelectedTimeList!.isNotEmpty ){
+      // 有选中的时间
+      // 关闭 visitTime 弹框
+      // 需要更新 serviceOrderConfrimVm 的 visitTime
+      final serviceOrderConfrimVm = ref.read(serviceOrderConfirmVmProvider.notifier);
+      final visitTimeTitleVm = ref.read(chooseVisitTimeTitleVmProvider.notifier);
+      final visitTimeContentVm = ref.read(chooseVisitTimeContentVmProvider.notifier);
+
+      // String visitTime = visitTimeTitleVm.state.currentSelectDayInfoItem.date! + ' ' + visitTimeContentVm.state.allSelectedTimeList!.first?.time!;
+      String visitTime = visitTimeContentVm.state.allSelectedTimeList!.first?.time!??'';
+      serviceOrderConfrimVm.handlerHideVisitTimeDialog();
+      serviceOrderConfrimVm.handlerUpdateVisitTime(visitTime);
+
+      // 需要更新订单页面 serviceOrderConfrimVm 的 cleanServiceToTalCost  和 extraCost
+      serviceOrderConfrimVm?.setConfirmOrderTotalPrice(context);
+    }else {
+      // 没有选中预约时间
+      ToastEngine.show("Please Choose Visit Time");
+    }
   }
 }

+ 1 - 1
packages/cpt_services/lib/components/chooseVisitTimeBottomFooter_vm.g.dart

@@ -7,7 +7,7 @@ part of 'chooseVisitTimeBottomFooter_vm.dart';
 // **************************************************************************
 
 String _$chooseVisitTimeBottomFooterVmHash() =>
-    r'7ef89e7901bf6761ee066d4ef93bbdf7a6ce59c5';
+    r'717bedb19b618d4a8c0e84f05dc27874943b2233';
 
 /// See also [ChooseVisitTimeBottomFooterVm].
 @ProviderFor(ChooseVisitTimeBottomFooterVm)

+ 89 - 34
packages/cpt_services/lib/components/chooseVisitTimeContent.dart

@@ -4,6 +4,7 @@ import 'package:cpt_services/components/chooseVisitTimeBottomFooter.dart';
 import 'package:cpt_services/components/chooseVisitTimeBottomFooter_vm.dart';
 import 'package:cpt_services/components/chooseVisitTimeContent_vm.dart';
 import 'package:cpt_services/components/status_card_item.dart';
+import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
@@ -15,6 +16,7 @@ import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
 import 'package:widgets/my_cart_num.dart';
@@ -25,7 +27,7 @@ import 'chooseVisitTimeContent_state.dart';
 
 class ChooseVisitTimeContent extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
   final double contentTopSectionHeight;
   final double contentMaxHeight;
   final double bottomBtnSectionHeight;
@@ -33,7 +35,7 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
   const ChooseVisitTimeContent({
     Key? key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
     this.contentTopSectionHeight = 150,
     this.contentMaxHeight = 480,
     this.bottomBtnSectionHeight = 50,
@@ -45,6 +47,7 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
     final state = ref.watch(chooseVisitTimeContentVmProvider);
 
     useEffect((){
+      vm.setInitPageData(context, id, cleanServiceType);
       // 组件挂载时执行 - 执行接口请求
       Future.microtask(() => vm.initPageData(context));
       return () {
@@ -58,7 +61,7 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
         // final minHeight = constraints.minHeight;
         // final maxWidth = constraints.maxWidth;
         // Log.d("---maxHeight-----$maxHeight-- $minHeight  $maxWidth--");
-        double scrollMaxHeight = contentMaxHeight - contentTopSectionHeight - bottomBtnSectionHeight ;
+        // double scrollMaxHeight = contentMaxHeight - contentTopSectionHeight - bottomBtnSectionHeight ;
         // Log.d("scrollMaxHeight  $scrollMaxHeight");
         return Container(
           width: double.infinity,
@@ -71,11 +74,11 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
           ),
           child: LoadStateLayout(
             state: state.loadingState,
-            successSliverWidget: [
+            successSliverWidget: state.visitTimeList!=null && state.visitTimeList.isNotEmpty?[
               SliverGrid(
                 gridDelegate:  const SliverGridDelegateWithFixedCrossAxisCount(
                 crossAxisCount: 4,
-                mainAxisSpacing: 5,
+                mainAxisSpacing: 15,
                 crossAxisSpacing: 5,
                 childAspectRatio: 80 / 38,
                   // childAspectRatio:  166.5/214 * ScreenUtil.getAdapterSizeCtx(context, 166.5/214), // 宽高比
@@ -87,21 +90,19 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
                   },
                   childCount: state.visitTimeList.length,
                 ),
-
-                // GridView.builder(
-                //   gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
-                //     crossAxisCount: 4,
-                //     mainAxisSpacing: 5,
-                //     crossAxisSpacing: 5,
-                //     childAspectRatio: 80 / 38,
-                //   ),
-                //   itemCount: state.visitTimeList.length,
-                //   itemBuilder: (context, index) {
-                //     final item = state.visitTimeList[index];
-                //     return _buildTimeItem(context, index, item, ref, vm);
-                //   },
-                // )
               )
+            ]: [
+              SliverList( delegate: SliverChildBuilderDelegate(
+                      (context, index){
+                    return  const Center(
+                        child: SizedBox(
+                          height: 250,
+                          child: MyAssetImage(Assets.baseServicePageNoData, width: 123.5, height: 115.5, fit: BoxFit.contain),
+                        ),
+                      );
+                  },
+                  childCount: 1
+              ),)
             ],
           ),
         );
@@ -111,17 +112,27 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
 
 
   Widget _buildTimeItem(BuildContext context,int index, VisitTimeContentItem item, WidgetRef ref, vm){
-    final name = item.name;
+    final state = ref.watch(chooseVisitTimeContentVmProvider);
+
+    final itemIsChecked = ref.watch(chooseVisitTimeContentVmProvider.select((state) =>
+       state.visitTimeList[index].isChecked ?? false
+    ));
+    final timeText = item.timeText;
     return HookBuilder(
       builder: (context) {
-        final isChecked = useState<bool>(item.isChecked??false);
+        final isMultiSelect = useState<bool>(state.isMultiSelect??false);
+        // final isChecked = useState<bool>(itemIsChecked??false);
+        final enable = useState<bool>(item.enable??false);
+        final urgent = useState<bool>(item.urgent??false); // 是否加急
+        final holiday = useState<bool>(item.holiday??false); // 是否节假日
+        final night = useState<bool>(item.night??false); // 是否晚上
         return SizedBox(
           width: 80,
           child: Stack(
             children: [
               Container(
                 decoration: BoxDecoration(
-                  color: isChecked.value? ColorUtils.string2Color("#D9DFF6"):context.appColors.whiteBG,
+                  color: itemIsChecked? ColorUtils.string2Color("#D9DFF6"):context.appColors.whiteBG,
                   borderRadius: BorderRadius.circular(8),
                   boxShadow: [
                     BoxShadow(
@@ -133,18 +144,26 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
                 ),
                 child:  MyButton(
                   onPressed: (){
-                    isChecked.value = !isChecked.value;
-                    vm.handlerTimeItemClick(context, index, isChecked.value);
+                    if(enable.value){
+                      // 可选  - 点击时间
+                      vm.handlerTimeItemClick(context, index,!itemIsChecked);
+                    }
                   },
-                  text: '$name',
-                  minHeight: 38,
-                  textColor: isChecked.value?context.appColors.textPrimary: context.appColors.textDarkGray999,
-                  fontSize: 12,
+                  text: '$timeText',
+                  padding: const EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
+                  textColor: itemIsChecked ?context.appColors.textPrimary: context.appColors.textDarkGray999,
+                  enable: enable.value,
+                  disabledBackgroundColor: context.appColors.disEnableGray,
+                  disabledTextColor: context.appColors.textWhite,
+                  fontSize: 11,
                   fontWeight: FontWeight.w400,
                 )
               ),
+              // 加急
               Positioned(
-                child: MyTextView(
+                left: 0,
+                top: 0,
+                child: urgent.value? MyTextView(
                   'Extreme speed',
                   textColor: ColorUtils.string2Color("#DD6800"),
                   fontSize: 8,
@@ -155,11 +174,47 @@ class ChooseVisitTimeContent extends HookConsumerWidget {
                   paddingLeft: 5,
                   paddingRight: 5,
                 ).clipRRect(
-                  topLeft: 10,
-                  bottomRight: 10
-                ).onTap((){
-
-                }),
+                  topLeft: 8,
+                  bottomRight: 8
+                ): const SizedBox.shrink(),
+              ),
+              // 夜间
+              Positioned(
+                left: 0,
+                bottom: 0,
+                child: night.value? MyTextView(
+                  'Night',
+                  textColor: ColorUtils.string2Color("#FE4066"),
+                  fontSize: 8,
+                  isFontRegular: true,
+                  backgroundColor: ColorUtils.string2Color("#FE4066").withOpacity(0.2),
+                  paddingTop: 2,
+                  paddingBottom: 2,
+                  paddingLeft: 5,
+                  paddingRight: 5,
+                ).clipRRect(
+                    topRight: 8,
+                    bottomLeft: 8
+                ): const SizedBox.shrink(),
+              ),
+              // 节假日
+              Positioned(
+                right: 0,
+                bottom: 0,
+                child: holiday.value? MyTextView(
+                  'Holiday',
+                  textColor: ColorUtils.string2Color("#37d7cc"),
+                  fontSize: 8,
+                  isFontRegular: true,
+                  backgroundColor:ColorUtils.string2Color("#68f1e7").withOpacity(0.2),
+                  paddingTop: 2,
+                  paddingBottom: 2,
+                  paddingLeft: 5,
+                  paddingRight: 5,
+                ).clipRRect(
+                    topLeft: 8,
+                    bottomRight: 8
+                ): const SizedBox.shrink(),
               ),
             ],
           ),

+ 54 - 22
packages/cpt_services/lib/components/chooseVisitTimeContent_state.dart

@@ -1,67 +1,99 @@
+import 'package:shared/utils/date_time_utils.dart';
 import 'package:widgets/load_state_layout.dart';
 
 import 'visitTimeType.dart';
 
 class ChooseVisitTimeContentState{
-  // 设置一个get  totalPrice
-  get totalPrice => visitTimeList.map((item) => (item.isChecked??false) ? item.price??0 : 0 ).reduce((before, current) => before + current);
+  // 当前所选中的所有时间段集合
+  List<VisitTimeContentItem> get allSelectedTimeList => visitTimeList.where((item) => item.isChecked??false).toList()??[];
+
+  // extraTotalCost 总预约费用
+  double get extraTotalCost {
+    if(extraCostList?.isNotEmpty == true){
+      return extraCostList?.fold(0.0, (previousValue, current) => previousValue! + current??0.0)??0.0;
+    }else {
+      return 0.0;
+    }
+  }
 
   //页面 LoadView 状态的展示
   LoadState loadingState;
   String? errorMessage;
 
+  // 是否可多选
+  bool? isMultiSelect;
   List<VisitTimeContentItem> visitTimeList = [];
+  List<double>? extraCostList = [];  // 预约费用(节假日/加急/夜间 费用的集合)
+  String currentDate = DateTimeUtils.formatDate(DateTime.now(), format: "yyyy-MM-dd");
+
 
   ChooseVisitTimeContentState({
     this.loadingState = LoadState.State_Loading,
     this.errorMessage,
-    required this.visitTimeList,
-  });
+    this.isMultiSelect = false,
+    required this.currentDate,
+    this.extraCostList,
+    List<VisitTimeContentItem>? visitTimeList,
+  }) {
+    this.visitTimeList = visitTimeList ?? [];
+  }
 
   ChooseVisitTimeContentState copyWith({
     LoadState? loadingState,
     String? errorMessage,
+    bool? isMultiSelect,
     List<VisitTimeContentItem>? visitTimeList,
-  }){
+    List<double>? extraCostList,
+    String? currentDate,
+  }) {
     return ChooseVisitTimeContentState(
-      loadingState: loadingState??this.loadingState,
-      errorMessage: errorMessage??this.errorMessage,
-      visitTimeList: visitTimeList??this.visitTimeList,
+      loadingState: loadingState ?? this.loadingState,
+      errorMessage: errorMessage ?? this.errorMessage,
+      isMultiSelect: isMultiSelect ?? this.isMultiSelect,
+      visitTimeList: visitTimeList ?? this.visitTimeList,
+      extraCostList: extraCostList ?? this.extraCostList,
+      currentDate: currentDate ?? this.currentDate,
     );
   }
 }
 
+
 class VisitTimeContentItem{
-  String? name;
   int? id;
-  double? price;
-  Map<String, dynamic>? type;
+  String? timeText;
+  String? time;
+  bool? urgent;
+  bool? holiday;
+  bool? night;
   bool? isChecked;
-  bool? isDisable;
+  bool? enable;
   VisitTimeContentItem({
-    this.name,
     this.id,
-    this.price,
-    this.type,
+    this.timeText,
+    this.time,
+    this.urgent,
+    this.holiday,
+    this.night,
     this.isChecked = false,
-    this.isDisable = false,
+    this.enable = false,
   });
 
   VisitTimeContentItem copyWith({
     String? name,
     int? id,
-    double? price,
     Map<String, dynamic>? type,
     bool? isChecked,
-    bool? isDisable,
+    bool? enable,
   }){
     return VisitTimeContentItem(
-        name: name??this.name,
         id: id??this.id,
-        price: price??this.price,
-        type: type ?? this.type, // 在这里设置默认值
+        timeText: timeText??this.timeText,
+        time: time??this.time,
+        urgent: urgent??this.urgent,
+        holiday: holiday??this.holiday,
+        night: night??this.night,
         isChecked: isChecked??this.isChecked,
-        isDisable: isDisable??this.isDisable,
+        enable: enable??this.enable,
     );
   }
 }

+ 118 - 241
packages/cpt_services/lib/components/chooseVisitTimeContent_vm.dart

@@ -1,158 +1,64 @@
 
 import 'package:cpt_services/modules/services/service_order_confirm/service_order_confirm_vm.dart';
+import 'package:domain/entity/service_time_period_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/log_utils.dart';
 
 import 'package:widgets/dialog/dialog_content_wrap.dart';
 import 'package:widgets/load_state_layout.dart';
 
 import '../../../respository/services_respository.dart';
+import '../modules/services/service_clean_detail/service_clean_detail_vm.dart';
 import 'chooseVisitTimeContent_state.dart';
 
 part 'chooseVisitTimeContent_vm.g.dart';
 
 
 List<Map<String, dynamic>> visitTimeList = [
-  {
-    "name": "08:00 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "08:30 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "09:00 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "09:30 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "10:00 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "10:30 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "11:00 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "11:30 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "12:00 AM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "12:30 PM",
-    "id": 1,
-    "price": 40.0,
-    "type": null
-  },
-  {
-    "name": "13:00 PM",
-    "id": 1,
-    "price": 50.0,
-    "type": {
-      "text": "Extreme speed",
-      "type": "extremeSpeed",
-      'code': 1,
-    }
-  },
-  {
-    "name": "13:30 PM",
-    "id": 1,
-    "price": 50.0,
-    "type": {
-      "text": "Extreme speed",
-      "type": "extremeSpeed",
-      'code': 1,
-    }
-  },
-  {
-    "name": "14:00 PM",
-    "id": 1,
-    "price": 50.0,
-    "type": {
-      "text": "Extreme speed",
-      "type": "extremeSpeed",
-      'code': 1,
-    }
-  },
-  {
-    "name": "14:30 PM",
-    "id": 1,
-    "price": 50.0,
-    "type": {
-      "text": "Extreme speed",
-      "type": "extremeSpeed",
-      'code': 1,
-    }
-  },
-  {
-    "name": "15:00 PM",
-    "id": 1,
-    "price": 50.0,
-    "type": {
-      "text": "Extreme speed",
-      "type": "extremeSpeed",
-      'code': 1,
-    }
-  },
+  // {
+  //   "time_text": "07:00 AM",
+  //   "time": "2025-01-16 07:00:00",
+  //   "urgent": false,
+  //   "holiday": false,
+  //   "night": false,
+  //   "enable": false
+  // },
 ];
 
 
 
-
-
-
 @riverpod
 class ChooseVisitTimeContentVm extends _$ChooseVisitTimeContentVm {
   late ServicesRespository serviceRespositoryInstance;
 
+  late BuildContext _context;
+  late int _id;
+  late String _cleanServiceType;
+
   ChooseVisitTimeContentState initState(){
     Log.d("--------------------------initState---------------------");
     List<VisitTimeContentItem> visitTimeListNew = [];
     visitTimeList.forEach((item) {
       VisitTimeContentItem newItem = VisitTimeContentItem()
-        ..id = item['id']
-        ..price = item['price'] as double
-        ..name = item['name']
-        ..type = null
-        ..isDisable = false
+        ..id = null
+        ..urgent = item['urgent']
+        ..holiday = item['holiday']
+        ..night = item['night']
+        ..time = item['time']
+        ..timeText = item['time_text']
+        ..enable = item['enable']
         ..isChecked = false;
       visitTimeListNew.add(newItem);
     });
 
     return ChooseVisitTimeContentState(
       visitTimeList: visitTimeListNew,
+      currentDate: DateTimeUtils.formatDate(DateTime.now(), format: "yyyy-MM-dd"),
     );
   }
 
@@ -160,9 +66,7 @@ class ChooseVisitTimeContentVm extends _$ChooseVisitTimeContentVm {
   ChooseVisitTimeContentState build(){
     // 引入数据仓库
     serviceRespositoryInstance = ref.read(servicesRespositoryProvider);
-     state = initState();
-    Log.d("--------------------------build---------------------");
-
+    state = initState();
     return state;
   }
 
@@ -171,134 +75,72 @@ class ChooseVisitTimeContentVm extends _$ChooseVisitTimeContentVm {
         loadingState: loadState,
         errorMessage: errorMsg
     );
+    // Log.d("87338  ${state.currentDate}");
+    Log.d("87338  ${state.visitTimeList}");
+  }
+
+  setInitPageData(BuildContext context, int id, String cleanServiceType){
+    _context = context;
+    _id = id;
+    _cleanServiceType = cleanServiceType;
   }
 
   initPageData(BuildContext context){
-    changeLoadingState(LoadState.State_Success, null);
+    // changeLoadingState(LoadState.State_Success, null);
+    getVisitTimeList(context, DateTimeUtils.formatDate(DateTime.now(), format: "yyyy-MM-dd"));
   }
 
-  Future<ChooseVisitTimeContentState> getVisitTimeList(BuildContext context) async{
+  // 获取指定 日期下面的所有 时间段
+  Future getVisitTimeList(BuildContext context, String date) async{
     Log.d("--------------------------getVisitTimeList---------------------");
     // 获取数据
-    // state.visitTimeList = serviceRespositoryInstance.getVisitTimeList();
-    // state = state.copyWith(
-    //   visitTimeList: state.visitTimeList,
-    // );
-
     changeLoadingState(LoadState.State_Loading, null);
+    try {
+      //请求网络
+      Map<String, dynamic>  params = {
+        "id": _id,
+        "date": date,
+      };
+      Log.d("请求参数------$params");
+      final result = await serviceRespositoryInstance.fetchPaidServiceTimePeriod(params);
+      //校验成功失败
+      if (result.isSuccess) {
+        List<ServiceTimePeriodEntity>? resultEntityList = result.list as List<ServiceTimePeriodEntity>;
+        handlerResultList(resultEntityList);
+      } else {
+        String errorMessage = result.errorMsg!;
+        changeLoadingState(LoadState.State_Error, errorMessage);
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
 
-    List<Map<String, dynamic>> visitTimeList = [
-      {
-        "name": "10:00 AM",
-        "id": 1,
-        "price": 40.0,
-        "type": null
-      },
-      {
-        "name": "10:30 AM",
-        "id": 1,
-        "price": 40.0,
-        "type": null
-      },
-      {
-        "name": "11:00 AM",
-        "id": 1,
-        "price": 40.0,
-        "type": null
-      },
-      {
-        "name": "11:30 AM",
-        "id": 1,
-        "price": 40.0,
-        "type": null
-      },
-      {
-        "name": "12:00 AM",
-        "id": 1,
-        "price": 40.0,
-        "type": null
-      },
-      {
-        "name": "12:30 PM",
-        "id": 1,
-        "price": 40.0,
-        "type": null
-      },
-      {
-        "name": "13:00 PM",
-        "id": 1,
-        "price": 50.0,
-        "type": {
-          "text": "Extreme speed",
-          "type": "extremeSpeed",
-          'code': 1,
-        }
-      },
-      {
-        "name": "13:30 PM",
-        "id": 1,
-        "price": 50.0,
-        "type": {
-          "text": "Extreme speed",
-          "type": "extremeSpeed",
-          'code': 1,
-        }
-      },
-      {
-        "name": "14:00 PM",
-        "id": 1,
-        "price": 50.0,
-        "type": {
-          "text": "Extreme speed",
-          "type": "extremeSpeed",
-          'code': 1,
-        }
-      },
-      {
-        "name": "14:30 PM",
-        "id": 1,
-        "price": 50.0,
-        "type": {
-          "text": "Extreme speed",
-          "type": "extremeSpeed",
-          'code': 1,
-        }
-      },
-      {
-        "name": "15:00 PM",
-        "id": 1,
-        "price": 50.0,
-        "type": {
-          "text": "Extreme speed",
-          "type": "extremeSpeed",
-          'code': 1,
-        }
-      },
-    ];
-    await Future.delayed(Duration(seconds: 1), (){});
-
-    List<VisitTimeContentItem> visitTimeListNew = [];
-    visitTimeList.forEach((item) {
-      VisitTimeContentItem newItem = VisitTimeContentItem()
-        ..id = item['id']
-        ..price = item['price'] as double
-        ..name = item['name']
-        ..type = null
-        ..isDisable = false
-        ..isChecked = false;
-      visitTimeListNew.add(newItem);
-    });
-
-    state = state.copyWith(
-      visitTimeList: visitTimeListNew,
-    );
-    Log.d("--------------------------getVisitTimeList END   ${state.visitTimeList}---------------------");
+  }
 
-    changeLoadingState(LoadState.State_Success, null);
 
-    return ChooseVisitTimeContentState(
-      visitTimeList: visitTimeListNew,
-    );
+  void handlerResultList(List<ServiceTimePeriodEntity>? list) {
+    if(list != null && list.isNotEmpty){
+      // 需要模型转换 将 ServiceTimePeriodEntity 转换为 VisitTimeContentItem
+      List<VisitTimeContentItem> newList = [];
+      list.asMap().forEach((index,item) {
+        VisitTimeContentItem newVisitTimeContentItem = VisitTimeContentItem()
+          ..id = index
+          ..urgent = item.urgent
+          ..holiday = item.holiday
+          ..night = item.night
+          ..time = item.time
+          ..timeText = item.timeText
+          ..enable = item.enable
+          ..isChecked = false;
+        newList.add(newVisitTimeContentItem);
+      });
+
+      state.visitTimeList!.clear();
+      state.visitTimeList!.addAll(newList);
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    }
   }
 
 
@@ -309,13 +151,48 @@ class ChooseVisitTimeContentVm extends _$ChooseVisitTimeContentVm {
     // );
   }
 
-  handlerTimeItemClick(BuildContext context, int index, bool isSelected){
+  // 点击 时间段
+  handlerTimeItemClick(BuildContext context, int index, bool changetoValue){
+    Log.d("index:${index} 的 isChecked属性  变换成: $changetoValue");
     // 修改 状态
-    state.visitTimeList[index].isChecked = isSelected;
+    if(state.isMultiSelect??false){
+      // 可多选
+      state.visitTimeList[index].isChecked = changetoValue;
+    }else {
+      // 不可多选
+      state.visitTimeList.asMap().forEach((i,item) {
+        if(i == index){
+          item.isChecked = changetoValue;
+        }else {
+          item.isChecked = false;
+        }
+      });
+    }
+
+    final cleanDetailVm = ref.read(serviceCleanDetailVmProvider.notifier);
+    // 结算当前所 预约的价格 (加急/节假日/夜间 等)所有选中的时间段 如果有 紧急、节假日、夜间 则需要加上相应价格
+    // 注意: 如果一个时间段同时设置了多种 预约类型(加急、节假日、夜间) 目前仅算了其中一个的费用 选择的顺序为 加急、节假日、夜间
+    final extraCostItemList = state.allSelectedTimeList?.map((item) {
+      if (item.urgent ?? false) {
+        return cleanDetailVm?.state.urgentPrice ?? 0.0;
+      } else if (item.holiday ?? false) {
+        return cleanDetailVm?.state.holidayPrice ?? 0.0;
+      } else if (item.night ?? false) {
+        return cleanDetailVm?.state.nightPrice ?? 0.0;
+      } else {
+        return 0.0;
+      }
+    }).toList();
+
+    state.extraCostList = extraCostItemList;
+    Log.d("chooseVisitTimeContent中选择了预约的时间段后 state.extraCostList: ${state.extraCostList}");
     state = state.copyWith(
       visitTimeList: state.visitTimeList,
+      extraCostList: extraCostItemList,
     );
 
-    ref.read(serviceOrderConfirmVmProvider.notifier).setConfirmOrderTotalPrice(context);
+    // 设置 订单确认页面的 总价格 (当点击了 Confirm 按钮后再去设置 订单页面的总价格)
+    // final serviceOrderConfirmVm = ref.read(serviceOrderConfirmVmProvider.notifier);
+    // serviceOrderConfirmVm?.setConfirmOrderTotalPrice(context);
   }
 }

+ 1 - 1
packages/cpt_services/lib/components/chooseVisitTimeContent_vm.g.dart

@@ -7,7 +7,7 @@ part of 'chooseVisitTimeContent_vm.dart';
 // **************************************************************************
 
 String _$chooseVisitTimeContentVmHash() =>
-    r'f7465ee5636aac140e046ba07c02e64117890fe4';
+    r'6d59a67cf0b38046893035e796921b6e1bd6bd0f';
 
 /// See also [ChooseVisitTimeContentVm].
 @ProviderFor(ChooseVisitTimeContentVm)

+ 3 - 11
packages/cpt_services/lib/components/chooseVisitTimeTitle.dart

@@ -1,4 +1,5 @@
 
+import 'package:cpt_services/components/chooseHouseCleanContent_vm.dart';
 import 'package:cpt_services/components/chooseVisitTimeBottomFooter.dart';
 import 'package:cpt_services/components/chooseVisitTimeTitle_vm.dart';
 import 'package:cpt_services/modules/services/service_clean_detail/service_clean_detail_vm.dart';
@@ -18,10 +19,10 @@ import 'chooseVisitTimeTitle_vm.dart';
 
 class ChooseVisitTimeTitle extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
   const ChooseVisitTimeTitle(
-      {Key? key,required this.id, required this.serviceTypeCode,}) : super(key: key);
+      {Key? key,required this.id, required this.cleanServiceType,}) : super(key: key);
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
@@ -54,15 +55,6 @@ class ChooseVisitTimeTitle extends HookConsumerWidget {
                   boxWidth: double.infinity,
                   // maxLines: 5,
                 ),
-                MyTextView(
-                  '30 minutes before the start of the service, free time modification is available',
-                  textColor: context.appColors.textDarkGray999,
-                  textAlign: TextAlign.left,
-                  isFontRegular: true,
-                  fontSize: 14,
-                  // maxLines: 5,
-                  boxWidth: double.infinity,
-                ),
               ],
             ),
           ),

+ 13 - 8
packages/cpt_services/lib/components/chooseVisitTimeTitle_state.dart

@@ -1,18 +1,19 @@
 class ChooseVisitTimeTitleState {
   int? currentSelectIndex;
+  get currentSelectDayInfoItem => dayInfoList![currentSelectIndex!];
   List<DayInfoItem>? dayInfoList;
 
   ChooseVisitTimeTitleState({
     this.currentSelectIndex = 0,
     dayInfoList,
   }): dayInfoList = dayInfoList ?? [
-    DayInfoItem(day: 'Tody', date: '2022-01-01', isSelected: true, isIntrady: true,),
-    DayInfoItem(day: 'Tomorrow', date: '2022-01-02', isSelected: false, isIntrady: false,),
-    DayInfoItem(day: 'Wendnesday', date: '2022-01-03', isSelected: false, isIntrady: false,),
-    DayInfoItem(day: 'Thursdy', date: '2022-01-04', isSelected: false, isIntrady: false,),
-    DayInfoItem(day: 'Friday', date: '2022-01-05', isSelected: false, isIntrady: false,),
-    DayInfoItem(day: 'Saturday', date: '2022-01-06', isSelected: false, isIntrady: false,),
-    DayInfoItem(day: 'Sunday', date: '2022-01-07', isSelected: false, isIntrady: false,),
+    DayInfoItem(day: 'Tody', date: '2022-01-01', isSelected: true, isIntrady: true, holiday:false, enable: true),
+    DayInfoItem(day: 'Tomorrow', date: '2022-01-02', isSelected: false, isIntrady: false,holiday:false, enable: true),
+    DayInfoItem(day: 'Wendnesday', date: '2022-01-03', isSelected: false, isIntrady: false,holiday:false, enable: true),
+    DayInfoItem(day: 'Thursdy', date: '2022-01-04', isSelected: false, isIntrady: false,holiday:false, enable: true),
+    DayInfoItem(day: 'Friday', date: '2022-01-05', isSelected: false, isIntrady: false,holiday:false, enable: true),
+    DayInfoItem(day: 'Saturday', date: '2022-01-06', isSelected: false, isIntrady: false,holiday:false, enable: true),
+    DayInfoItem(day: 'Sunday', date: '2022-01-07', isSelected: false, isIntrady: false,holiday:false, enable: true),
   ];
 
   ChooseVisitTimeTitleState copyWith({
@@ -32,13 +33,17 @@ class DayInfoItem {
   String? day;
   String? date;
   bool isSelected;
-  bool isIntrady;
+  bool? isIntrady;
+  bool? holiday;
+  bool? enable;
   DayInfoItem({
     this.id = 0,
     this.day,
     this.date,
     this.isSelected = false,
     this.isIntrady = false,
+    this.holiday = false,
+    this.enable = true,
   });
 }
 

+ 41 - 18
packages/cpt_services/lib/components/chooseVisitTimeTitle_vm.dart

@@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/log_utils.dart';
 
 import 'package:widgets/dialog/dialog_content_wrap.dart';
@@ -70,27 +71,49 @@ List<Map<String, dynamic>> dayInfoList = [
 
 
 
-ChooseVisitTimeTitleState initState(){
-  Log.d("--------------------------initState---------------------");
-  List<DayInfoItem> dayInfoListNew = [];
-  dayInfoList.forEach((item) {
-    DayInfoItem newItem = DayInfoItem()
-      ..id = item['id']
-      ..day = item['day']
-      ..date = item['date']
-      ..isSelected = item['isSelected']
-      ..isIntrady = item['isIntrady'];
-    dayInfoListNew.add(newItem);
-  });
-  return ChooseVisitTimeTitleState(
-    dayInfoList: dayInfoListNew,
-  );
-}
-
 @riverpod
 class ChooseVisitTimeTitleVm extends _$ChooseVisitTimeTitleVm {
   late ServicesRespository serviceRespositoryInstance;
 
+  int _rencentDays = 7;
+
+  formatWeekday(int index, String day){
+    switch (index) {
+      case 0:
+        return 'Today';
+      case 1:
+        return 'Tomorrow';
+      default:
+        return day;
+    }
+  }
+
+  ChooseVisitTimeTitleState initState(){
+    Log.d("--------------------------initState---------------------");
+    List<DayInfoItem> dayInfoListNew = [];
+    // 从当前天开始 生成一份最近一个星期的 DayInfoItem
+    DateTime now = DateTime.now();
+    for(int i = 0; i < _rencentDays; i++){
+      DateTime date = now.add(Duration(days: i));
+      String day = DateTimeUtils.getWeekday(date, languageCode: 'en');
+      String dateStr = date.toString().substring(0, 10);
+      DayInfoItem newItem = DayInfoItem()
+        ..id = i
+        ..day = day = formatWeekday(i, day)
+        ..date = dateStr
+        ..isSelected = i == 0
+        ..isIntrady = i == 0
+        ..holiday = false
+        ..enable = true;
+      dayInfoListNew.add(newItem);
+    }
+
+    return ChooseVisitTimeTitleState(
+      dayInfoList: dayInfoListNew,
+    );
+  }
+
+
   @override
   ChooseVisitTimeTitleState build(){
     // 引入数据仓库
@@ -128,7 +151,7 @@ class ChooseVisitTimeTitleVm extends _$ChooseVisitTimeTitleVm {
 
     // 触发 chooseVisitTimeContent 的刷新
     final chooseVisitTimeContentVm = ref.read(chooseVisitTimeContentVmProvider.notifier);
-    chooseVisitTimeContentVm?.getVisitTimeList(context);
+    chooseVisitTimeContentVm?.getVisitTimeList(context, dayInfoItem.date!);
   }
 
   // 点击某一时间段

+ 1 - 1
packages/cpt_services/lib/components/chooseVisitTimeTitle_vm.g.dart

@@ -7,7 +7,7 @@ part of 'chooseVisitTimeTitle_vm.dart';
 // **************************************************************************
 
 String _$chooseVisitTimeTitleVmHash() =>
-    r'8d58fc35095631b1692ff9a6d2da997b85a4793f';
+    r'23d4d176e8ec0de5f38d7802b1686dc7c77763c6';
 
 /// See also [ChooseVisitTimeTitleVm].
 @ProviderFor(ChooseVisitTimeTitleVm)

+ 3 - 3
packages/cpt_services/lib/components/repair_status_card_item.dart

@@ -16,7 +16,7 @@ import '../constants_services.dart';
 
 class RepairStausCardItem extends HookConsumerWidget {
   int serviceId;
-  int serviceTypeCode;
+  String cleanServiceType;
   int serviceStatusCode;
   Map<String, dynamic> itemObj;
   double? cardHeight ;
@@ -25,7 +25,7 @@ class RepairStausCardItem extends HookConsumerWidget {
   RepairStausCardItem({
     Key? key,
     required this.serviceId,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
     required this.serviceStatusCode,
     required this.itemObj,
     this.onClickCard,
@@ -52,7 +52,7 @@ class RepairStausCardItem extends HookConsumerWidget {
     // Log.d("actionBtnList   $actionBtnList");
 
     useEffect((){
-      vm.setInitData(context, serviceId, serviceTypeCode, serviceStatusCode);
+      vm.setInitData(context, serviceId, cleanServiceType, serviceStatusCode);
       return () {
       };
     },[]);

+ 152 - 167
packages/cpt_services/lib/components/status_card_item.dart

@@ -1,6 +1,7 @@
 import 'package:cpt_services/components/status_card_item_vm.dart';
 import 'package:cpt_services/modules/services/homeService/home_service_page.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
@@ -15,168 +16,155 @@ import 'package:widgets/my_text_view.dart';
 import '../constants_services.dart';
 
 class StausCardItem extends HookConsumerWidget {
-  int serviceId;
-  int serviceTypeCode;
-  int serviceStatusCode;
-  Map<String, dynamic> itemObj;
-  double? cardHeight ;
+  GarageSaleHistoryList? item;
+  double? cardHeight;
+
   final Function(dynamic)? onClickCard;
 
   StausCardItem({
     Key? key,
-    required this.serviceId,
-    required this.serviceTypeCode,
-    required this.serviceStatusCode,
-    required this.itemObj,
+    required this.item,
     this.onClickCard,
     cardHeight,
-  }): super(key: key) {
+  }) : super(key: key) {
     this.cardHeight = cardHeight ?? 180.0;
   }
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final vm = ref.read(statusCardItemVmProvider.notifier);
-
-    final title = itemObj.getValue("title", "House Cleaning Services");
-    final companyName = itemObj.getValue("company_name", "HONG YE GROUP PTE LTD");
-    final duration = itemObj.getValue("duration", "Daily cleaning for 2 hours");
-    final totalPrice = itemObj.getValue("totalPrice", '40');
-    final visit_time = itemObj.getValue("visit_time", '14 0ct 2024 15:00');
-    final order_time = itemObj.getValue("order_time", '13 0ct 2024 12:00');
-
-    Log.d("serviceStatusCode $serviceStatusCode");
-    String status_text = servicesConstants.servicesStatus['$serviceStatusCode']['text'];
-
-    // final status_text = itemObj.getValue("status_text", "");
+    // final vm = ref.read(statusCardItemVmProvider.notifier);
 
-    List<Map<String, dynamic>>? actionBtnList = servicesConstants.servicesStatusActionBtnList[serviceStatusCode];
+    // List<Map<String, dynamic>>? actionBtnList = servicesConstants.servicesStatusActionBtnList[serviceStatusCode];
     // Log.d("actionBtnList   $actionBtnList");
 
-    useEffect((){
-      vm.setInitData(context, serviceId, serviceTypeCode, serviceStatusCode);
-      return () {
-      };
-    },[]);
+    // useEffect((){
+    //   vm.setInitData(context, serviceId, serviceTypeCode, serviceStatusCode);
+    //   return () {
+    //   };
+    // },[]);
+
     return Container(
       width: double.infinity,
-      height: cardHeight!,
+      height: cardHeight!.ap,
       child: Padding(
-        padding: const EdgeInsets.only(left: 18.0, right: 18.0, top: 22.0, bottom: 22.0),
+        padding: EdgeInsets.only(left: 18.0, right: 18.0, top: 10.0.ap, bottom: 10.0.ap),
         child: Column(
           crossAxisAlignment: CrossAxisAlignment.start,
           children: [
             Expanded(
-              child: Column(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  // 标题 和状态
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      // 标题
-                      Expanded(
-                        child: MyTextView(
-                          title,
-                          fontSize: 16,
-                          maxLines: 1,
-                          isFontMedium: true,
-                          textAlign: TextAlign.left,
-                        ),
-                      ),
-                      // 状态
-                      MyTextView(
-                        status_text,
-                        fontSize: 14,
+                child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                // 标题 和状态
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    // 标题
+                    Expanded(
+                      child: MyTextView(
+                        item?.service?.name ?? "-",
+                        fontSize: 16,
                         maxLines: 1,
-                        isFontRegular: true,
+                        isFontMedium: true,
                         textAlign: TextAlign.left,
-                        textColor: context.appColors.textPrimary,
                       ),
-                    ],
-                  ),
-                  // 公司名称
-                  MyTextView(
-                    companyName,
-                    fontSize: 14,
-                    maxLines: 1,
-                    isFontRegular: true,
-                    textAlign: TextAlign.left,
-                    marginTop: 6,
-                  ),
-                  // 价格
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      // 公司名称
-                      MyTextView(
-                        duration,
-                        fontSize: 14,
-                        maxLines: 1,
-                        isFontRegular: true,
-                        textAlign: TextAlign.left,
-                      ),
-                      // 公司名称
-                      MyTextView(
-                        '\$$totalPrice',
-                        fontSize: 17,
-                        maxLines: 1,
-                        isFontBold: true,
-                        textAlign: TextAlign.left,
-                        textColor: context.appColors.textPrimary,
-                      ),
-                    ],
-                  ),
-                  SizedBox(height: 7.5,),
-                  // visit time
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      MyTextView(
-                        'Visit Time',
-                        fontSize: 14,
-                        maxLines: 1,
-                        isFontRegular: true,
-                        textAlign: TextAlign.left,
-                      ),
-                      MyTextView(
-                        visit_time,
-                        fontSize: 14,
-                        maxLines: 1,
-                        isFontRegular: true,
-                        textAlign: TextAlign.left,
-                        textColor: context.appColors.textBlack,
-                      ),
-                    ],
-                  ),
-                  SizedBox(height: 7.5,),
-                  // order time
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      MyTextView(
-                        'Order Time',
-                        fontSize: 14,
-                        maxLines: 1,
-                        isFontRegular: true,
-                        textAlign: TextAlign.left,
-                      ),
-                      MyTextView(
-                        order_time,
-                        fontSize: 14,
-                        maxLines: 1,
-                        isFontRegular: true,
-                        textAlign: TextAlign.left,
-                        textColor: context.appColors.textBlack,
-                      ),
-                    ],
-                  ),
-                ],
-              )
-            ),
+                    ),
+                    // 状态
+                    MyTextView(
+                      item?.orderStatus??"-",
+                      fontSize: 14,
+                      maxLines: 1,
+                      isFontRegular: true,
+                      textAlign: TextAlign.left,
+                      textColor: context.appColors.textPrimary,
+                    ),
+                  ],
+                ),
+                // 公司名称
+                MyTextView(
+                  item?.merchant?.name ?? "-",
+                  fontSize: 14,
+                  maxLines: 1,
+                  isFontRegular: true,
+                  textAlign: TextAlign.left,
+                  marginTop: 5,
+                ),
+                // 价格
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    // 商品/服务名称
+                    MyTextView(
+                      item?.orderProducts[0].productName ?? "-",
+                      fontSize: 14,
+                      maxLines: 1,
+                      isFontRegular: true,
+                      textAlign: TextAlign.left,
+                    ),
+                    // 公司名称
+                    MyTextView(
+                      '\$${item?.orderProducts[0].totalAmount ?? "-"}',
+                      fontSize: 17,
+                      maxLines: 1,
+                      isFontBold: true,
+                      textAlign: TextAlign.left,
+                      textColor: context.appColors.textPrimary,
+                    ),
+                  ],
+                ),
+                const SizedBox(
+                  height: 5,
+                ),
+                // visit time
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    MyTextView(
+                      'Visit Time',
+                      fontSize: 14,
+                      maxLines: 1,
+                      isFontRegular: true,
+                      textAlign: TextAlign.left,
+                    ),
+                    MyTextView(
+                      item?.orderProducts[0].plannedServiceAt ?? "-",
+                      fontSize: 14,
+                      maxLines: 1,
+                      isFontRegular: true,
+                      textAlign: TextAlign.left,
+                      textColor: context.appColors.textBlack,
+                    ),
+                  ],
+                ),
+                const SizedBox(
+                  height: 5,
+                ),
+                // order time
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    MyTextView(
+                      'Order Time',
+                      fontSize: 14,
+                      maxLines: 1,
+                      isFontRegular: true,
+                      textAlign: TextAlign.left,
+                    ),
+                    MyTextView(
+                      item?.createdAt ?? "-",
+                      fontSize: 14,
+                      maxLines: 1,
+                      isFontRegular: true,
+                      textAlign: TextAlign.left,
+                      textColor: context.appColors.textBlack,
+                    ),
+                  ],
+                ),
+              ],
+            )),
             // Container(
-              // margin: EdgeInsets.only(top: 15),
-              // child: _buildActionSection(context,actionBtnList!, vm, ref),
+            // margin: EdgeInsets.only(top: 15),
+            // child: _buildActionSection(context,actionBtnList!, vm, ref),
             // ),
           ],
         ),
@@ -184,40 +172,37 @@ class StausCardItem extends HookConsumerWidget {
     );
   }
 
-  Widget _buildActionSection(BuildContext context,List<Map<String, dynamic>> actionBtnList, StatusCardItemVm vm, WidgetRef ref ) {
-    return LayoutBuilder(
-        builder: (BuildContext context, BoxConstraints constraints) {
-          final maxHeight = constraints.maxHeight;
-          final minHeight = constraints.minHeight;
-          final maxWidth = constraints.maxWidth;
-          // Log.d("---maxHeight-----$maxHeight-- $minHeight  $maxWidth--");
-          return Container(
-            height: 50,
-            // color: Colors.red,
-            width: maxWidth,
-            child: Row(
-              mainAxisAlignment: MainAxisAlignment.end,
-              mainAxisSize: MainAxisSize.max,
-              children: List.generate(actionBtnList.length, (index){
-                var item = actionBtnList[index];
-                // return Expanded(
-                //   child: _buildBtn(context, item),
-                // );
-                return _buildBtn(context, item, vm, ref);
-              })
-            ),
-          ).scrollable(
-            scrollDirection: Axis.horizontal,
-            physics: BouncingScrollPhysics(),
-          );
-      }
-    );
+  Widget _buildActionSection(BuildContext context, List<Map<String, dynamic>> actionBtnList, StatusCardItemVm vm, WidgetRef ref) {
+    return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
+      final maxHeight = constraints.maxHeight;
+      final minHeight = constraints.minHeight;
+      final maxWidth = constraints.maxWidth;
+      // Log.d("---maxHeight-----$maxHeight-- $minHeight  $maxWidth--");
+      return Container(
+        height: 50,
+        // color: Colors.red,
+        width: maxWidth,
+        child: Row(
+            mainAxisAlignment: MainAxisAlignment.end,
+            mainAxisSize: MainAxisSize.max,
+            children: List.generate(actionBtnList.length, (index) {
+              var item = actionBtnList[index];
+              // return Expanded(
+              //   child: _buildBtn(context, item),
+              // );
+              return _buildBtn(context, item, vm, ref);
+            })),
+      ).scrollable(
+        scrollDirection: Axis.horizontal,
+        physics: BouncingScrollPhysics(),
+      );
+    });
   }
 
   Widget _buildBtn(BuildContext context, Map<String, dynamic> btnItem, StatusCardItemVm vm, WidgetRef ref) {
     // final btnCode = btnItem['code'];
     return MyButton(
-      onPressed: (){
+      onPressed: () {
         vm.handlerClickActionBtn(context, btnItem);
       },
       text: btnItem['text'],
@@ -230,4 +215,4 @@ class StausCardItem extends HookConsumerWidget {
       minHeight: btnItem['btnHeight']?.toDouble() + 5,
     ).marginOnly(left: 5);
   }
-}
+}

+ 4 - 4
packages/cpt_services/lib/components/status_card_item_vm.dart

@@ -18,7 +18,7 @@ class StatusCardItemVm extends _$StatusCardItemVm {
   late ServicesRespository serviceRespositoryInstance;
 
   late int _serviceId;
-  late int _serviceTypeCode;
+  late String _cleanServiceType;
   late int _serviceStatusCode;
 
 
@@ -44,9 +44,9 @@ class StatusCardItemVm extends _$StatusCardItemVm {
   //   );
   // }
 
-  setInitData(BuildContext context,int serviceId, int serviceTypeCode, int serviceStatusCode){
+  setInitData(BuildContext context,int serviceId, String cleanServiceType, int serviceStatusCode){
     _serviceId = serviceId;
-    _serviceTypeCode = serviceTypeCode;
+    _cleanServiceType = cleanServiceType;
     _serviceStatusCode = serviceStatusCode;
   }
 
@@ -68,7 +68,7 @@ class StatusCardItemVm extends _$StatusCardItemVm {
       case '4':
         // 去评价
         // context.router.pushNamed('/detail');
-        ServiceEvaluateCreatePage.startInstance(id: _serviceId, serviceTypeCode: _serviceTypeCode,);
+        ServiceEvaluateCreatePage.startInstance(id: _serviceId, cleanServiceType: _cleanServiceType,);
         break;
       default:
         break;

+ 1 - 1
packages/cpt_services/lib/components/status_card_item_vm.g.dart

@@ -6,7 +6,7 @@ part of 'status_card_item_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$statusCardItemVmHash() => r'41c489c1bdf10cb0588de229c4d4bf2b5440d204';
+String _$statusCardItemVmHash() => r'b4fb97b72135c637c44971bb6be4f2adad536023';
 
 /// See also [StatusCardItemVm].
 @ProviderFor(StatusCardItemVm)

+ 4 - 3
packages/cpt_services/lib/components/user_evaluate_card_item.dart

@@ -89,7 +89,7 @@ class UserEvaluateCardItem extends StatelessWidget {
                 Expanded(
                   child: Container(
                     // color: Colors.yellow,
-                    margin: const EdgeInsets.only(left: 10),
+                    margin: const EdgeInsets.only(left: 5),
                     child: Column(
                       mainAxisAlignment: MainAxisAlignment.start,
                       crossAxisAlignment: CrossAxisAlignment.start,
@@ -128,7 +128,7 @@ class UserEvaluateCardItem extends StatelessWidget {
                                 ),
                                 MyTextView(
                                   '${score!}',
-                                  isFontRegular: true,
+                                  isFontMedium: true,
                                   fontSize: 12,
                                   textColor: ColorUtils.string2Color('#767676'),
                                   maxLines: 1,
@@ -143,7 +143,8 @@ class UserEvaluateCardItem extends StatelessWidget {
                               textColor: ColorUtils.string2Color('#767676'),
                               maxLines: 1,
                               isTextEllipsis: true,
-                            ),
+                              marginLeft: 5,
+                            ).expanded(),
                           ],
                         ),
                       ],

+ 10 - 10
packages/cpt_services/lib/constants_services.dart

@@ -1,19 +1,19 @@
 class servicesConstants {
    static Map<String, Map<String, dynamic>> servicesType = {
      "houseCleaning": {
-       "text": "houseCleaning",
-       "type": "houseCleaning",
-       'code': 0,
+       "text": "House Cleaning",
+       "type": "paid",
+       'code': "House Cleaning",  // 业务做 标识 字段
      },
      "airConditioner": {
-       "text": "airConditioner",
-       "type": "airConditioner",
-       'code': 1,
+       "text": "Air Conditioning Cleaning",
+       "type": "paid",
+       'code': "Air Conditioning Cleaning", // 业务做 标识 字段
      },
-     "repaire": {
-       "text": "维修",
-       "type": "repaire",
-       'code': 2,
+     "repairAirConditioner": {
+       "text": "Maintenance",
+       "type": "inquiry",
+       'code': "Repair air Conditioner",  // 业务做 标识 字段
      }
   };
 

+ 3 - 3
packages/cpt_services/lib/modules/services/clean_order_cancel_success/clean_order_cancel_success_page.dart

@@ -33,9 +33,9 @@ class CleanOrderCancelSuccessPage extends HookConsumerWidget {
   //启动当前页面
   static void startInstance({BuildContext? context}) {
     if (context != null) {
-      context.router.push(const CleanOrderCancelSuccessPageRoute());
+      context.router.replace(const CleanOrderCancelSuccessPageRoute());
     } else {
-      appRouter.push(const CleanOrderCancelSuccessPageRoute());
+      appRouter.replace(const CleanOrderCancelSuccessPageRoute());
     }
   }
 
@@ -82,7 +82,7 @@ class CleanOrderCancelSuccessPage extends HookConsumerWidget {
                   text: "Back Home",
                   onPressed: (){
                     // 回到首页
-                    ComponentServiceManager().mainService.startMainPage();
+                    context.router.maybePop();
                   },
                   fontSize: 15,
                   fontWeight: FontWeight.w500,

+ 58 - 57
packages/cpt_services/lib/modules/services/clean_order_detail/cancelOrderDialogContent.dart

@@ -9,13 +9,16 @@ import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 
 class CancelOrderDialogContent extends HookConsumerWidget {
+
   const CancelOrderDialogContent({
     Key? key,
   }) : super(key: key);
@@ -28,6 +31,7 @@ class CancelOrderDialogContent extends HookConsumerWidget {
       width: double.infinity,
       child: Column(
         mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
         children: [
           MyTextView(
             "Reason for canceling the order:",
@@ -60,66 +64,63 @@ class CancelOrderDialogContent extends HookConsumerWidget {
     );
   }
 
-
   /// 多行输入框
-  Widget _buildTextAreaLayout(BuildContext context, CleanOrderDetailVm vm, WidgetRef ref,String key){
+  Widget _buildTextAreaLayout(BuildContext context, CleanOrderDetailVm vm, WidgetRef ref, String key) {
     final state = ref.watch(cleanOrderDetailVmProvider);
     final noteCount = useState(0);
-    return Stack(
-        children: [
-          Container(
-            color: ColorUtils.string2Color("#F2F3F6"),
-            margin: const EdgeInsets.only(top: 15, bottom: 28.5),
-            padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
-            child: TextField(
-              cursorColor: context.appColors.authFiledText,
-              cursorWidth: 1.5,
-              autofocus: false,
-              enabled: true,
-              maxLines: null,
-              focusNode: state.cancelFormData![key]!['focusNode'],
-              controller: state.cancelFormData![key]!['controller'],
-              decoration: InputDecoration(
-                isDense: true,
-                isCollapsed: true,
-                border: InputBorder.none,
-                hintText: state.cancelFormData![key]!['hintText'],
-                hintStyle: TextStyle(
-                  color: context.appColors.authFiledHint,
-                  fontSize: 16.0,
-                  fontWeight: FontWeight.w400,
-                ),
-              ),
-              style: TextStyle(
-                color: context.appColors.authFiledText,
-                fontSize: 16.0,
-                fontWeight: FontWeight.w400,
-              ),
-              textInputAction: TextInputAction.done,
-              onSubmitted: (value) {
-                FocusScope.of(context).unfocus();
-              },
-              expands: true,
-              onChanged: (text) {
-                // 当文本改变时,更新字符数量
-                noteCount.value = text.length;
-                final cleanOrderDetailVm = ref.read(cleanOrderDetailVmProvider.notifier);
-                cleanOrderDetailVm.changeCancelFormData(context, text);
-              },
+    return Stack(children: [
+      Container(
+        color: ColorUtils.string2Color("#F2F3F6"),
+        margin: const EdgeInsets.only(top: 15, bottom: 28.5),
+        padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
+        child: TextField(
+          cursorColor: context.appColors.authFiledText,
+          cursorWidth: 1.5,
+          autofocus: false,
+          enabled: true,
+          maxLines: null,
+          focusNode: state.cancelFormData![key]!['focusNode'],
+          controller: state.cancelFormData![key]!['controller'],
+          decoration: InputDecoration(
+            isDense: true,
+            isCollapsed: true,
+            border: InputBorder.none,
+            hintText: state.cancelFormData![key]!['hintText'],
+            hintStyle: TextStyle(
+              color: context.appColors.authFiledHint,
+              fontSize: 16.0,
+              fontWeight: FontWeight.w400,
             ),
           ),
-          // Positioned(
-          //   bottom: 0.0,
-          //   right: 0.0,
-          //   child: Text(
-          //     S.current.characters(noteCount.value),
-          //     style: TextStyle(
-          //       color: context.appColors.textBlack,
-          //       fontSize: 15.0,
-          //     ),
-          //   ),
-          // ),
-        ]
-    );
+          style: TextStyle(
+            color: context.appColors.authFiledText,
+            fontSize: 16.0,
+            fontWeight: FontWeight.w400,
+          ),
+          textInputAction: TextInputAction.done,
+          onSubmitted: (value) {
+            FocusScope.of(context).unfocus();
+          },
+          expands: true,
+          onChanged: (text) {
+            // 当文本改变时,更新字符数量
+            noteCount.value = text.length;
+            final cleanOrderDetailVm = ref.read(cleanOrderDetailVmProvider.notifier);
+            cleanOrderDetailVm.changeCancelFormData(context, text);
+          },
+        ),
+      ),
+      // Positioned(
+      //   bottom: 0.0,
+      //   right: 0.0,
+      //   child: Text(
+      //     S.current.characters(noteCount.value),
+      //     style: TextStyle(
+      //       color: context.appColors.textBlack,
+      //       fontSize: 15.0,
+      //     ),
+      //   ),
+      // ),
+    ]);
   }
-}
+}

+ 126 - 127
packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_page.dart

@@ -3,6 +3,7 @@ import 'package:cpt_services/components/chooseAirConditionContent_vm.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/service_order_detail_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -35,25 +36,25 @@ import '../../../components/status_card_item.dart';
 @RoutePage()
 class CleanOrderDetailPage extends HookConsumerWidget {
   final int id; // 订单id
-  final int serviceTypeCode;  // 订单类型
+  final String cleanServiceType; // 订单类型
   final int serviesStatusCode; // 订单状态
+
   const CleanOrderDetailPage({
     Key? key,
     @PathParam('id') required this.id,
-    @PathParam('serviceTypeCode') required this.serviceTypeCode,
+    @PathParam('cleanServiceType') required this.cleanServiceType,
     @PathParam('serviesStatusCode') required this.serviesStatusCode,
   }) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context, required int id, required int serviceTypeCode, required int serviesStatusCode}) {
+  static void startInstance({BuildContext? context, required int id, required String cleanServiceType, required int serviesStatusCode}) {
     if (context != null) {
-      context.router.push(CleanOrderDetailPageRoute(id: id, serviceTypeCode: serviceTypeCode, serviesStatusCode: serviesStatusCode));
+      context.router.push(CleanOrderDetailPageRoute(id: id, cleanServiceType: cleanServiceType, serviesStatusCode: serviesStatusCode));
     } else {
-      appRouter.push(CleanOrderDetailPageRoute(id:id, serviceTypeCode: serviceTypeCode, serviesStatusCode: serviesStatusCode));
+      appRouter.push(CleanOrderDetailPageRoute(id: id, cleanServiceType: cleanServiceType, serviesStatusCode: serviesStatusCode));
     }
   }
 
-
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(cleanOrderDetailVmProvider.notifier);
@@ -64,9 +65,9 @@ class CleanOrderDetailPage extends HookConsumerWidget {
     Log.d("actionBtnList   $actionBtnList");
 
     useEffect(() {
-      vm.setInitPageData(id: id, serviceTypeCode: serviceTypeCode, serviceStatusCode: serviesStatusCode);
+      vm.setInitPageData(id: id, cleanServiceType: cleanServiceType, serviceStatusCode: serviesStatusCode);
       // 组件挂载时执行 - 执行接口请求
-      Future.microtask(() => vm.initPageData());
+      Future.microtask(() => vm.fetchOrderDetailData(id));
       return () {
         // 组件卸载时执行
       };
@@ -93,27 +94,26 @@ class CleanOrderDetailPage extends HookConsumerWidget {
               state: state.loadingState,
               errorMessage: state.errorMessage,
               errorRetry: () {
-                vm.retryRequest();
+                vm.retryRequest(id);
               },
               successWidget: Column(
                 children: [
                   Expanded(
                     child: Padding(
                       padding: const EdgeInsets.only(bottom: 10),
-                      child: _buildBody(state, vm, context,ref),
+                      child: _buildBody(state, vm, context, ref),
                     ),
                   ),
                   // 底部联系信息
                   Visibility(
                     visible: state.loadingState == LoadState.State_Success,
-                    child: state.datas !=null ? _buildActionSection(context, state, vm, ref, id, serviceTypeCode,serviesStatusCode, actionBtnList): Container(),
+                    child:
+                        state.datas != null ? _buildActionSection(context, state, vm, ref, id, cleanServiceType, serviesStatusCode, actionBtnList) : Container(),
                   )
-
                 ],
               ),
             ),
-          ).marginOnly(left: 0,right: 0,top: 0,bottom: 0)
-      ),
+          ).marginOnly(left: 0, right: 0, top: 0, bottom: 0)),
     );
   }
 
@@ -193,7 +193,6 @@ class CleanOrderDetailPage extends HookConsumerWidget {
   }
 
   Widget _buildOrderScore(CleanOrderDetailState state, CleanOrderDetailVm vm, BuildContext context) {
-    double score = 5.0;
     //  评分
     return Column(
       children: [
@@ -204,7 +203,7 @@ class CleanOrderDetailPage extends HookConsumerWidget {
             crossAxisAlignment: CrossAxisAlignment.start,
             children: [
               MyTextView(
-                "House Cleaning Services",
+                state.datas?.orderService?.name ?? "-",
                 textColor: context.appColors.textBlack,
                 fontSize: 18,
                 isFontBold: true,
@@ -215,12 +214,13 @@ class CleanOrderDetailPage extends HookConsumerWidget {
                 crossAxisAlignment: CrossAxisAlignment.center,
                 children: [
                   AnimatedRatingStars(
-                    initialRating: score,
-                    onChanged: (rating) {
-                    },
+                    initialRating: state.datas?.orderService?.evaluationsAvgScore ?? 0.0,
+                    onChanged: (rating) {},
                     readOnly: true,
-                    displayRatingValue: true, // Display the rating value
-                    interactiveTooltips: true, // Allow toggling half-star state
+                    displayRatingValue: true,
+                    // Display the rating value
+                    interactiveTooltips: true,
+                    // Allow toggling half-star state
                     customFilledIcon: Icons.star,
                     customHalfFilledIcon: Icons.star_half,
                     customEmptyIcon: Icons.star_border,
@@ -230,7 +230,7 @@ class CleanOrderDetailPage extends HookConsumerWidget {
                     animationCurve: Curves.easeInOut,
                   ),
                   MyTextView(
-                    "${score}",
+                    "${state.datas?.orderService?.evaluationsAvgScore ?? 0.0}",
                     textColor: context.appColors.textBlack,
                     fontSize: 16,
                     isFontMedium: true,
@@ -239,7 +239,7 @@ class CleanOrderDetailPage extends HookConsumerWidget {
                 ],
               ),
               MyTextView(
-                "HONG YE GROUP PTE LTD",
+                state.datas?.merchant?.name ?? "-",
                 textColor: context.appColors.textDarkGray999,
                 fontSize: 12,
                 isFontRegular: true,
@@ -272,7 +272,7 @@ class CleanOrderDetailPage extends HookConsumerWidget {
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
                 MyTextView(
-                  '705 Qiming Huijin Building',
+                  state.datas?.estateUnit?.address ?? "-",
                   fontSize: 17,
                   isFontBold: true,
                   textColor: context.appColors.textBlack,
@@ -282,13 +282,13 @@ class CleanOrderDetailPage extends HookConsumerWidget {
                   mainAxisAlignment: MainAxisAlignment.start,
                   children: [
                     MyTextView(
-                      'Sundy',
+                      state.datas?.account?.name ?? "-",
                       fontSize: 14,
                       textColor: context.appColors.textDarkGray999,
                       isFontRegular: true,
                     ),
                     MyTextView(
-                      '+6588991122',
+                      "+${state.datas?.account?.phone ?? "-"}",
                       fontSize: 14,
                       textColor: context.appColors.textDarkGray999,
                       isFontRegular: true,
@@ -328,30 +328,40 @@ class CleanOrderDetailPage extends HookConsumerWidget {
             ),
           ],
         ),
-        if (serviceTypeCode == servicesConstants.servicesType['houseCleaning']!['code'])
-        // 室内清理
-          _buildCleanContent(context, state)
-        else if (serviceTypeCode == servicesConstants.servicesType['airConditioner']!['code'])
-        // 空调清理
-          _buildCleanContent(context, state)
+        
+        // if (cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code'])
+        //   // 室内清理
+        //   _buildCleanContent(context, state)
+        // else if (cleanServiceType == servicesConstants.servicesType['airConditioner']!['code'])
+        //   // 空调清理
+        //   _buildCleanContent(context, state)
+        // else
+        //   const SizedBox.shrink()
+
+        // 根据 orderProducts 数组生成对应的 Widgets
+        if (state.datas?.orderProducts != null && state.datas!.orderProducts!.isNotEmpty)
+          ...state.datas!.orderProducts!.map((product) {
+            return _buildCleanContent(product, context);
+          }).toList()
         else
-          const SizedBox.shrink()
+          const SizedBox.shrink(), //空
+        
       ],
     );
   }
 
-  Widget _buildCleanContent(BuildContext context, state) {
-    final title = 'House Cleaning Services';
-    final areaSizeRange = '1 Bedroom';
-    final num =  1;
-    final price = 0;
-    bool isChecked = false;
-    bool disabled = true;
-    final isDisable = useState<bool>(disabled);
+  Widget _buildCleanContent(ServiceOrderDetailOrderProducts item ,BuildContext context) {
+    // final title = 'House Cleaning Services';
+    // final areaSizeRange = '1 Bedroom';
+    // final num = 1;
+    // final price = 0;
+    // bool isChecked = false;
+    // bool disabled = true;
+    // final isDisable = useState<bool>(disabled);
 
     return Container(
-      padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
-      margin: EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 0),
+      padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 0),
       color: ColorUtils.string2Color('#F8F8F8'),
       child: Column(
         children: [
@@ -364,13 +374,13 @@ class CleanOrderDetailPage extends HookConsumerWidget {
                   crossAxisAlignment: CrossAxisAlignment.start,
                   children: [
                     MyTextView(
-                      title,
+                      item.productName?? '-',
                       fontSize: 16,
                       isFontMedium: true,
                       textColor: context.appColors.textBlack,
                     ),
                     MyTextView(
-                      areaSizeRange,
+                      "x${item.quantity}",
                       fontSize: 15,
                       isFontRegular: true,
                       textColor: context.appColors.textDarkGray999,
@@ -392,14 +402,14 @@ class CleanOrderDetailPage extends HookConsumerWidget {
               // )
               Container(
                 child: MyButton(
-                  text: '\$$price',
+                  text: '\$${item.totalAmount??""}',
                   onPressed: null,
                   minWidth: 80,
                   minHeight: 40,
                   fontSize: 19,
                   fontWeight: FontWeight.w500,
                   // enable: !isDisable.value,
-                  textColor:  context.appColors.textPrimary,
+                  textColor: context.appColors.textPrimary,
                   backgroundColor: context.appColors.textWhite,
                   disabledBackgroundColor: context.appColors.disEnableGray,
                   disabledTextColor: context.appColors.textWhite,
@@ -413,41 +423,33 @@ class CleanOrderDetailPage extends HookConsumerWidget {
     );
   }
 
-
   Widget _buildOrderTotalAmount(CleanOrderDetailState state, CleanOrderDetailVm vm, BuildContext context) {
-    return Column(
-      children: [
-        Row(
-          mainAxisAlignment: MainAxisAlignment.start,
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            const MyAssetImage(
-              Assets.serviceMoneyIcon,
-              width: 15,
-              height: 17.5,
-            ),
-            const SizedBox(
-             width: 10,
-            ),
-            MyTextView(
-              'Total Amount',
-              fontSize: 17,
-              isFontBold: true,
-              textColor: context.appColors.textBlack,
-            ),
-
-            MyTextView(
-              '\$200',
-              fontSize: 15,
-              textColor: context.appColors.textBlack,
-              isFontBold: true,
-              textAlign: TextAlign.end,
-              marginRight: 17,
-            ).expanded(),
-          ]
-        )
-      ]
-    );
+    return Column(children: [
+      Row(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
+        const MyAssetImage(
+          Assets.serviceMoneyIcon,
+          width: 15,
+          height: 17.5,
+        ),
+        const SizedBox(
+          width: 10,
+        ),
+        MyTextView(
+          'Total Amount',
+          fontSize: 17,
+          isFontBold: true,
+          textColor: context.appColors.textBlack,
+        ),
+        MyTextView(
+          '\$${state.datas?.totalAmount ?? 0}',
+          fontSize: 15,
+          textColor: context.appColors.textBlack,
+          isFontBold: true,
+          textAlign: TextAlign.end,
+          marginRight: 17,
+        ).expanded(),
+      ])
+    ]);
   }
 
   Widget _buildOrderVisitTime(CleanOrderDetailState state, CleanOrderDetailVm vm, BuildContext context) {
@@ -481,7 +483,7 @@ class CleanOrderDetailPage extends HookConsumerWidget {
             mainAxisAlignment: MainAxisAlignment.end,
             children: [
               MyTextView(
-                '2021-01-01 12:00',
+                state.datas?.orderProducts?[0].plannedServiceAt ?? '',
                 fontSize: 15,
                 textColor: context.appColors.textDarkGray999,
                 isFontRegular: true,
@@ -537,7 +539,7 @@ class CleanOrderDetailPage extends HookConsumerWidget {
                 ],
               ),
               MyButton(
-                onPressed: (){
+                onPressed: () {
                   ComponentServiceManager().paymentService.startChooseCardPage();
                 },
                 text: 'Change',
@@ -582,23 +584,23 @@ class CleanOrderDetailPage extends HookConsumerWidget {
           ],
         ),
         Container(
-          margin: const EdgeInsets.only(left:10, right:10,top: 0),
+          margin: const EdgeInsets.only(left: 10, right: 10, top: 0),
           width: double.infinity,
           padding: const EdgeInsets.all(15),
           decoration: BoxDecoration(
-              color: ColorUtils.string2Color("#F8F8F8"),
-              borderRadius: BorderRadius.circular(5),
-              // boxShadow: [
-              //   BoxShadow(
-              //     color: Colors.grey.withOpacity(0.2),
-              //     spreadRadius:1,
-              //     blurRadius: 2,
-              //     offset: const Offset(0.5, 0.5), // changes position of shadow
-              //   ),
-              // ]
+            color: ColorUtils.string2Color("#F8F8F8"),
+            borderRadius: BorderRadius.circular(5),
+            // boxShadow: [
+            //   BoxShadow(
+            //     color: Colors.grey.withOpacity(0.2),
+            //     spreadRadius:1,
+            //     blurRadius: 2,
+            //     offset: const Offset(0.5, 0.5), // changes position of shadow
+            //   ),
+            // ]
           ),
           child: MyTextView(
-            'Hope to arrive as soon as possible',
+            state.datas?.notes ?? "",
             fontSize: 16,
             isFontRegular: true,
             textColor: context.appColors.textBlack,
@@ -609,7 +611,6 @@ class CleanOrderDetailPage extends HookConsumerWidget {
     );
   }
 
-
   Widget _buildOrderRules(CleanOrderDetailState state, CleanOrderDetailVm vm, BuildContext context) {
     return Column(
       crossAxisAlignment: CrossAxisAlignment.start,
@@ -643,41 +644,39 @@ class CleanOrderDetailPage extends HookConsumerWidget {
   }
 
   // 底部操作区域
-  Widget _buildActionSection(BuildContext context,state, vm ,WidgetRef ref, int id, int serviceTypeCode, int serviesStatusCode, List<Map<String, dynamic>> actionBtnList) {
-    return LayoutBuilder(
-        builder: (BuildContext context, BoxConstraints constraints) {
-          final maxHeight = constraints.maxHeight;
-          final minHeight = constraints.minHeight;
-          final maxWidth = constraints.maxWidth;
-          // Log.d("---maxHeight-----$maxHeight-- $minHeight  $maxWidth--");
-          return Container(
-            height: 71.5,
-            color: context.appColors.whiteBG,
-            width: maxWidth,
-            padding: const EdgeInsets.only(left: 10, right: 10),
-            child: Row(
-                mainAxisAlignment: MainAxisAlignment.center,
-                mainAxisSize: MainAxisSize.max,
-                children: List.generate(actionBtnList.length, (index){
-                  var item = actionBtnList[index];
-                  return Expanded(
-                    child: _buildBtn(context, item, vm, ref),
-                  );
-                  // return _buildBtn(context, item, vm, ref);
-                })
-            ),
-          ).scrollable(
-            scrollDirection: Axis.horizontal,
-            physics: BouncingScrollPhysics(),
-          );
-        }
-    );
+  Widget _buildActionSection(
+      BuildContext context, state, vm, WidgetRef ref, int id, String cleanServiceType, int serviesStatusCode, List<Map<String, dynamic>> actionBtnList) {
+    return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
+      final maxHeight = constraints.maxHeight;
+      final minHeight = constraints.minHeight;
+      final maxWidth = constraints.maxWidth;
+      // Log.d("---maxHeight-----$maxHeight-- $minHeight  $maxWidth--");
+      return Container(
+        height: 71.5,
+        color: context.appColors.whiteBG,
+        width: maxWidth,
+        padding: const EdgeInsets.only(left: 10, right: 10),
+        child: Row(
+            mainAxisAlignment: MainAxisAlignment.center,
+            mainAxisSize: MainAxisSize.max,
+            children: List.generate(actionBtnList.length, (index) {
+              var item = actionBtnList[index];
+              return Expanded(
+                child: _buildBtn(context, item, vm, ref),
+              );
+              // return _buildBtn(context, item, vm, ref);
+            })),
+      ).scrollable(
+        scrollDirection: Axis.horizontal,
+        physics: const BouncingScrollPhysics(),
+      );
+    });
   }
 
   Widget _buildBtn(BuildContext context, Map<String, dynamic> btnItem, vm, WidgetRef ref) {
     // final btnCode = btnItem['code'];
     return MyButton(
-      onPressed: (){
+      onPressed: () {
         vm.handlerClickActionBtn(context, btnItem);
       },
       text: btnItem['text'],
@@ -690,4 +689,4 @@ class CleanOrderDetailPage extends HookConsumerWidget {
       minHeight: btnItem['btnHeight']?.toDouble() + 5,
     ).marginOnly(left: 5);
   }
-}
+}

+ 4 - 2
packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/service_order_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:widgets/load_state_layout.dart';
 
@@ -6,7 +7,8 @@ class CleanOrderDetailState {
   LoadState loadingState;
   String? errorMessage;
   double? totalPrice;
-  Map<String, dynamic>? datas;
+
+  ServiceOrderDetailEntity? datas;
 
   String? cancelReason;  // 取消的文字
 
@@ -36,7 +38,7 @@ class CleanOrderDetailState {
     double? totalPrice,
     String? cancelReason,
     Map<String, Map<String, dynamic>>? cancelFormData,
-    Map<String, dynamic>? datas,
+    ServiceOrderDetailEntity? datas,
   }) {
     return CleanOrderDetailState(
       loadingState: loadingState ?? this.loadingState,

+ 103 - 224
packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_vm.dart

@@ -1,4 +1,3 @@
-
 import 'package:cpt_services/components/chooseAirConditionContent_vm.dart';
 import 'package:cpt_services/components/chooseHouseCleanContent_vm.dart';
 import 'package:cpt_services/components/chooseVisitTimeContent.dart';
@@ -10,12 +9,18 @@ import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/permission/permission_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/event_bus.dart';
 import 'package:shared/utils/ext_dart.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/dialog/app_custom_dialog.dart';
 import 'package:widgets/dialog/app_default_dialog.dart';
 import 'package:widgets/dialog/dialog_content_wrap.dart';
@@ -36,40 +41,33 @@ import 'clean_order_detail_state.dart';
 
 part 'clean_order_detail_vm.g.dart';
 
-
-final _chooseVisitTimeDialogGlobalKey = GlobalKey<DialogContentWrapState>();
-
 @riverpod
-class CleanOrderDetailVm extends _$CleanOrderDetailVm {
+class CleanOrderDetailVm extends _$CleanOrderDetailVm with DioCancelableMixin {
   late ServicesRespository servicesRespositoryInstance;
   bool _needShowPlaceholder = false; //是否展示LoadingView
-  int _page = 1;  // 当前页
-  int _limit = 10; // 每页数量
-  int _count = 0; // 总条数
 
   late int _detailId;
-  late int _detailServiceTypeCode;
+  late String _cleanServiceType;
   late int _detailServiceStatusCode;
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   CleanOrderDetailState initState() {
     return CleanOrderDetailState(
-        datas: {}
+      datas: null,
     );
   }
 
   @override
-  CleanOrderDetailState build(){
-    // 引入数据仓库
-    // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
+  CleanOrderDetailState build() {
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     final state = initState();
     Log.d("--------------------------build---------------------");
-    // 处理 remarkInfo 数据的回显
+    registerCancellation();
     this.onInit();
     return state;
   }
@@ -80,198 +78,42 @@ class CleanOrderDetailVm extends _$CleanOrderDetailVm {
 
   //刷新页面状态
   void changeLoadingState(LoadState loadState, String? errorMsg) {
-    state = state.copyWith(
-        loadingState: loadState,
-        errorMessage: errorMsg
-    );
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
   }
 
-  setInitPageData({required int id, required int serviceTypeCode, required int serviceStatusCode}){
+  setInitPageData({required int id, required String cleanServiceType, required int serviceStatusCode}) {
     _detailId = id;
-    _detailServiceTypeCode = serviceTypeCode;
+    _cleanServiceType = cleanServiceType;
     _detailServiceStatusCode = serviceStatusCode;
   }
 
   // 初始化页面数据
-  initPageData({detailId, detailServiceTypeCode, detailServiceStatusCode}) {
-    _detailId = detailId??_detailId;
-    _detailServiceTypeCode = detailServiceTypeCode??_detailServiceTypeCode;
-    _detailServiceStatusCode = detailServiceStatusCode??_detailServiceStatusCode;
-    Log.d("--------------------------initPageData---------------------");
-    changeLoadingState(LoadState.State_Success, null);
-  }
-
-  // 上拉加载 更多
-  Future loadMore() async {
-    Log.d("----home_service_vm-----loadMore");
-    _page++;
-    getListData();
-  }
-
-  // 下拉刷新
-  Future onRefresh() async {
-    // 当前pageView 页面正处于显示状态
-    Log.d("----forsale_vm-----onRefresh ");
-    // await Future.delayed(const Duration(seconds: 2));
-    _page = 1;
-    getListData();
-  }
-
-
-  // 手动进行刷新
-  Future triggerRefresh() async {
-    Log.d("trggerRefresh");
-    refreshController.callRefresh();
-  }
-
-  // 手动进行刷新
-  Future directRefresh() async {
-    state = state.copyWith(datas:null);
-    // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
-    // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
-    refreshController.callRefresh();
-    refreshController.resetFooter();
-    _page = 1;
-    _needShowPlaceholder = true;
-    getListData();
-  }
-
+  // initPageData({detailId, detailcleanServiceType, detailServiceStatusCode}) {
+  //   _detailId = detailId??_detailId;
+  //   _cleanServiceType = detailcleanServiceType??_cleanServiceType;
+  //   _detailServiceStatusCode = detailServiceStatusCode??_detailServiceStatusCode;
+  //   Log.d("--------------------------initPageData---------------------");
+  //   changeLoadingState(LoadState.State_Success, null);
+  // }
 
   // 重试请求
-  Future retryRequest() async {
-    _page = 1;
+  Future retryRequest(int id) async {
     _needShowPlaceholder = true;
-    getListData();
+    fetchOrderDetailData(id);
   }
 
-
-  // 获取list 列表数据
-  Future getListData<T>({bool? isLoadMore}) async {
-    if (_needShowPlaceholder) {
-      changeLoadingState(LoadState.State_Loading, null);
-    }
-
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 0,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
-
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
-
-    // 最后赋值
-    _needShowPlaceholder = false;
-
-  }
-
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
-    Future.delayed(const Duration(seconds: 1)).then((value) {
-      if(isList){
-        // list 数据模式
-        // if(list != null && list.isNotEmpty){
-        //   if(_page == 1){
-        //     state.list.clear();
-        //     state.list!.addAll(list);
-        //     refreshController.finishRefresh();
-        //     changeLoadingState(LoadState.State_Success, null);
-        //   }else {
-        //     final allList = state.list;
-        //     allList!.addAll(list);
-        //     state = state.copyWith(list: allList);
-        //     refreshController.finishLoad();
-        //   }
-        // }else {
-        //   if(_page == 1){
-        //     state.list.clear();
-        //     changeLoadingState(LoadState.State_Empty, null);
-        //     refreshController.finishRefresh();
-        //   }else {
-        //     refreshController.finishLoad(IndicatorResult.noMore);
-        //   }
-        // }
-      }else {
-        // 单个数据模式
-        if(data!=null){
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Success, null);
-        }else {
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Empty, null);
-        }
+  void _callPhone(String? phone) {
+    PermissionEngine().requestCallPhonePermission(() async {
+      final Uri launchUri = Uri(scheme: 'tel', path: phone);
+      if (await canLaunchUrl(launchUri)) {
+        await launchUrl(launchUri);
+      } else {
+        ToastEngine.show("Can not Call Phone");
       }
     });
   }
 
-  handlerClickActionBtn(BuildContext context, Map<String, dynamic> actionBtn){
+  handlerClickActionBtn(BuildContext context, Map<String, dynamic> actionBtn) {
     final actionBtnCode = actionBtn['code']!.toString();
     switch (actionBtnCode) {
       case '0':
@@ -280,11 +122,15 @@ class CleanOrderDetailVm extends _$CleanOrderDetailVm {
         break;
       case '1':
         // Contact Merchant
-
+        _callPhone(state.datas?.merchant?.contactPhone);
         break;
       case '2':
         // Contact Service Personnel
-
+        if (Utils.isNotEmpty(state.datas?.staff?.phone)) {
+          _callPhone(state.datas?.staff?.phone);
+        } else {
+          ToastEngine.show("Currently, no staffs have been assigned");
+        }
         break;
       case '3':
         // Delete
@@ -292,28 +138,33 @@ class CleanOrderDetailVm extends _$CleanOrderDetailVm {
         break;
       case '4':
         // Evaluate 去评价
-        ServiceEvaluateCreatePage.startInstance(id: _detailId, serviceTypeCode: _detailServiceTypeCode,);
+        ServiceEvaluateCreatePage.startInstance(
+          id: _detailId,
+          cleanServiceType: _cleanServiceType,
+        );
         break;
       default:
         break;
     }
   }
 
-  handlerDeleteOrder(BuildContext context){
+  handlerDeleteOrder(BuildContext context) {
     DialogEngine.show(
-      widget: AppCustomDialog(
-        message: "Are you sure you want to delete?",
-        confirmAction: () {
-        },
-      )
-    );
+        widget: AppCustomDialog(
+      message: "Are you sure you want to delete?",
+      confirmAction: () {},
+    ));
   }
 
   // 取消订单
-  handlerCancelOrder(BuildContext context){
+  handlerCancelOrder(BuildContext context) {
     DialogEngine.show(
         tag: "cancelOrder",
         position: DialogPosition.center,
+        onDismiss: () {
+          // 清空备注信息
+          clearReasonInput();
+        },
         widget: DialogContentWrap(
           loadingState: LoadState.State_Success,
           maxHeight: 460.0,
@@ -328,13 +179,13 @@ class CleanOrderDetailVm extends _$CleanOrderDetailVm {
             color: context.appColors.textWhite,
           ),
           messageBuilder: (context) {
-            return CancelOrderDialogContent();
+            return const CancelOrderDialogContent();
           },
-          bottomFooterBuilder: (context){
+          bottomFooterBuilder: (context) {
             return Padding(
-              padding: const EdgeInsets.only( bottom: 40),
+              padding: const EdgeInsets.only(bottom: 40),
               child: MyButton(
-                onPressed: (){
+                onPressed: () {
                   // 提交取消订单
                   submitCancelOrder(context);
                 },
@@ -354,8 +205,8 @@ class CleanOrderDetailVm extends _$CleanOrderDetailVm {
           topRightRadius: 10.0,
           bottomLeftRadius: 10.0,
           bottomRightRadius: 10.0,
-          contentPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 20,top: 20),
-          bottomBtnSectionPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 20,top: 20),
+          contentPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 20),
+          bottomBtnSectionPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 20),
           cancelAction: () {
             DialogEngine.dismiss(tag: 'cancelOrder');
             clearReasonInput();
@@ -363,27 +214,55 @@ class CleanOrderDetailVm extends _$CleanOrderDetailVm {
           confirmAction: () {
             clearReasonInput();
           },
-        )
-    );
+        ));
   }
 
-  changeCancelFormData(BuildContext context,String cancelReason){
-    state.cancelReason = cancelReason;
-    // state = state.copyWith(
-    //   cancelReason: cancelReason
-    // );
+  changeCancelFormData(BuildContext context, String cancelReason) {
+    // state.cancelReason = cancelReason;
+    state = state.copyWith(cancelReason: cancelReason);
   }
 
-  submitCancelOrder(BuildContext context){
-    Log.d("cancelReason:  ${state.cancelReason}");
-    clearReasonInput();
-    DialogEngine.dismiss(tag: 'cancelOrder');
-    // 去成功页面
-    CleanOrderCancelSuccessPage.startInstance();
+  submitCancelOrder(BuildContext context) async {
+    Log.d("cancelReason: ${state.cancelReason}");
+
+    if (Utils.isNotEmpty(state.cancelReason)) {
+      //调用接口取消订单
+      DialogEngine.dismiss(tag: 'cancelOrder');
+
+      final result = await servicesRespositoryInstance.fetchCancelPaidServiceOrder(id: _detailId.toString(), reason: state.cancelReason);
+
+      if (result.isSuccess) {
+        bus.emit(AppConstant.eventServiceOrderRefresh, _detailId.toString());
+        clearReasonInput();
+        //去成功页面
+        CleanOrderCancelSuccessPage.startInstance();
+      } else {
+        ToastEngine.show(result.errorMsg ?? "UnKnow Error");
+      }
+    } else {
+      ToastEngine.show("Please enter the reason for cancellation");
+    }
   }
 
-  clearReasonInput(){
+  clearReasonInput() {
     state.cancelReason = "";
     state.cancelFormData!['reason']!["controller"].text = "";
+    state = state.copyWith(cancelReason: "", cancelFormData: state.cancelFormData);
+  }
+
+  //获取详情数据
+  fetchOrderDetailData(int id) async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    final result = await servicesRespositoryInstance.fetchPaidServiceCleanOrderDetail(id: id.toString(), cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+      state = state.copyWith(datas: result.data);
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      changeLoadingState(LoadState.State_Error, result.errorMsg ?? "UnKnow Error");
+    }
   }
-}
+}

+ 1 - 1
packages/cpt_services/lib/modules/services/clean_order_detail/clean_order_detail_vm.g.dart

@@ -7,7 +7,7 @@ part of 'clean_order_detail_vm.dart';
 // **************************************************************************
 
 String _$cleanOrderDetailVmHash() =>
-    r'068199d62a6545c1f8edff8736a13854a79042ab';
+    r'fcfa75c5fcdae98cdcc58d6b872100967a9a3c16';
 
 /// See also [CleanOrderDetailVm].
 @ProviderFor(CleanOrderDetailVm)

+ 22 - 28
packages/cpt_services/lib/modules/services/history/history_page.dart

@@ -1,4 +1,5 @@
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
@@ -38,17 +39,15 @@ class HistoryPage extends HookConsumerWidget {
     }
   }
 
-
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(historyVmProvider.notifier);
     final state = ref.watch(historyVmProvider);
     // final appConfigState = ref.watch(appConfigServiceProvider)
 
-    int serviceTypeCode = servicesConstants.servicesType['houseCleaning']?['code'];
+    String cleanServiceType = servicesConstants.servicesType['houseCleaning']?['code'];
     int serviceStatusCode = servicesConstants.servicesStatus['2']?['code'];
 
-
     useEffect(() {
       // 组件挂载时执行 - 执行接口请求
       Future.microtask(() => vm.initPageData());
@@ -72,12 +71,12 @@ class HistoryPage extends HookConsumerWidget {
             key: ValueKey('history'),
             controller: vm.refreshController,
             // 上拉加载
-            onLoad: () async{
+            onLoad: () async {
               Log.d("----onLoad");
               vm.loadMore();
             },
             // 下拉刷新
-            onRefresh: () async{
+            onRefresh: () async {
               Log.d("----onRefresh");
               vm.onRefresh();
             },
@@ -87,22 +86,22 @@ class HistoryPage extends HookConsumerWidget {
               errorRetry: () {
                 vm.retryRequest();
               },
-              successSliverWidget:[
+              successSliverWidget: [
                 SliverList(
                   delegate: SliverChildBuilderDelegate(
-                        (context, index) {
-                      return  _buildHistoryItem(
-                          context,
-                          ref,
-                          state.list[index],
-                          vm,
-                          serviceTypeCode,
-                          serviceStatusCode,
-                      ).onTap((){
+                    (context, index) {
+                      return _buildHistoryItem(
+                        context,
+                        ref,
+                        state.list[index],
+                        vm,
+                        cleanServiceType,
+                        serviceStatusCode,
+                      ).onTap(() {
                         vm.gotoCleanOrderDetailPage(
                           context,
-                          state.list?[index]['id'],
-                          serviceTypeCode,
+                          state.list[index].id != null ? int.tryParse(state.list[index].id!) ?? 0 : 0,
+                          cleanServiceType,
                           serviceStatusCode,
                         );
                       });
@@ -112,12 +111,11 @@ class HistoryPage extends HookConsumerWidget {
                 )
               ],
             ),
-          ).marginOnly(left: 15,right: 15,top: 0,bottom: 15)
-      ),
+          ).marginOnly(left: 15, right: 15, top: 0, bottom: 15)),
     );
   }
 
-  Widget _buildHistoryItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm, int serviceTypeCode, int serviceStatusCode){
+  Widget _buildHistoryItem(BuildContext context, WidgetRef ref, GarageSaleHistoryList item, vm, String cleanServiceType, int serviceStatusCode) {
     return Container(
       margin: const EdgeInsets.only(top: 9),
       width: double.infinity,
@@ -134,14 +132,10 @@ class HistoryPage extends HookConsumerWidget {
       ),
       child: StausCardItem(
         key: UniqueKey(),
-        cardHeight: 175.0,
-        serviceId: item['id'],
-        serviceTypeCode: serviceTypeCode,
-        serviceStatusCode: serviceStatusCode,
-        itemObj: item.cast<String, dynamic>(),
-        onClickCard: (dynamic value) async {
-        },
+        cardHeight: 125.5,
+        item: item,
+        onClickCard: (dynamic value) async {},
       ),
     );
   }
-}
+}

+ 3 - 2
packages/cpt_services/lib/modules/services/history/history_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class HistoryState {
@@ -7,7 +8,7 @@ class HistoryState {
 
   String? keyword;
   bool? isLiked;
-  List<Map<String, dynamic>> list;
+  List<GarageSaleHistoryList> list;
 
 
   HistoryState({
@@ -25,7 +26,7 @@ class HistoryState {
     bool? isLiked,
     Map<String, dynamic>? activeSortMap,
     List<Map<String, dynamic>>? activeCateGoryList,
-    List<Map<String, dynamic>>? list,
+    List<GarageSaleHistoryList>? list,
   }) {
     return HistoryState(
       loadingState: loadingState ?? this.loadingState,

+ 62 - 165
packages/cpt_services/lib/modules/services/history/history_vm.dart

@@ -1,11 +1,14 @@
-
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/event_bus.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
@@ -18,10 +21,10 @@ import 'history_state.dart';
 part 'history_vm.g.dart';
 
 @riverpod
-class HistoryVm extends _$HistoryVm {
+class HistoryVm extends _$HistoryVm with DioCancelableMixin {
   late ServicesRespository servicesRespositoryInstance;
   bool _needShowPlaceholder = false; //是否展示LoadingView
-  int _page = 1;  // 当前页
+  int _page = 1; // 当前页
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
 
@@ -33,33 +36,32 @@ class HistoryVm extends _$HistoryVm {
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   HistoryState initState() {
-    return HistoryState(
-        list: []
-    );
+    return HistoryState(list: []);
   }
 
   @override
-  HistoryState build(){
+  HistoryState build() {
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     // 引入数据仓库
     // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
     final state = initState();
+    registerEventBus();
     Log.d("--------------------------build---------------------");
+    registerCancellation(callback: () {
+      unregisterEventBus();
+    });
 
     return state;
   }
 
-
   //刷新页面状态
   void changeLoadingState(LoadState loadState, String? errorMsg) {
-    state = state.copyWith(
-        loadingState: loadState,
-        errorMessage: errorMsg
-    );
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
   }
 
   // 初始化页面数据
@@ -75,7 +77,6 @@ class HistoryVm extends _$HistoryVm {
     getListData();
   }
 
-
   // 下拉刷新
   Future onRefresh() async {
     // 当前pageView 页面正处于显示状态
@@ -85,7 +86,6 @@ class HistoryVm extends _$HistoryVm {
     getListData();
   }
 
-
   // 手动进行刷新
   Future triggerRefresh() async {
     Log.d("trggerRefresh");
@@ -94,7 +94,7 @@ class HistoryVm extends _$HistoryVm {
 
   // 手动进行刷新
   Future directRefresh() async {
-    state = state.copyWith(list:[]);
+    state = state.copyWith(list: []);
     // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
     // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
     refreshController.callRefresh();
@@ -104,7 +104,6 @@ class HistoryVm extends _$HistoryVm {
     getListData();
   }
 
-
   // 重试请求
   Future retryRequest() async {
     _page = 1;
@@ -112,195 +111,93 @@ class HistoryVm extends _$HistoryVm {
     getListData();
   }
 
-
   // 获取list 列表数据
   Future getListData<T>({bool? isLoadMore}) async {
     if (_needShowPlaceholder) {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 2,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 2,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 3,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
+    // 获取列表
+    var listResult = await servicesRespositoryInstance.fetchPaidServiceOrderList(
+      type: "history",
+      curPage: _page,
+      cancelToken: cancelToken,
+    );
 
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.list);
+    } else {
+      changeLoadingState(LoadState.State_Error, listResult.errorMsg);
+    }
 
     // 最后赋值
     _needShowPlaceholder = false;
-
-  }
-
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
-    Future.delayed(const Duration(seconds: 1)).then((value) {
-      if(isList){
-        // list 数据模式
-        if(list != null && list.isNotEmpty){
-          if(_page == 1){
-            state.list.clear();
-            state.list!.addAll(list);
-            refreshController.finishRefresh();
-            changeLoadingState(LoadState.State_Success, null);
-          }else {
-            final allList = state.list;
-            allList!.addAll(list);
-            state = state.copyWith(list: allList);
-            refreshController.finishLoad();
-          }
-        }else {
-          if(_page == 1){
-            state.list.clear();
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishRefresh();
-          }else {
-            refreshController.finishLoad(IndicatorResult.noMore);
-          }
-        }
-      }else {
-        // 单个数据模式
-        if(data!=null){
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Success, null);
-        }else {
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Empty, null);
-        }
-      }
-    });
   }
 
-  void handlerResultList(List<GarageSaleRentList>? list, bool isLoadMore) {
+  // 处理数据与展示的逻辑
+  void handleList(List<GarageSaleHistoryList>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_page == 1) {
         //刷新的方式
-        state.list!.clear();
-        state.list!.addAll(list.map((item) => item.toJson()).toList());
+        state = state.copyWith(list: list);
         refreshController.finishRefresh();
+
         //更新展示的状态
         changeLoadingState(LoadState.State_Success, null);
       } else {
         //加载更多
-        final allList = state.list;
-        allList!.addAll(list.map((item) => item.toJson()).toList());
-        state = state.copyWith(list: allList);
+        state.list.addAll(List<GarageSaleHistoryList>.from(state.list)..addAll(list));
         refreshController.finishLoad();
       }
     } else {
       if (_page == 1) {
         //展示无数据的布局
-        state.list!.clear();
+        state = state.copyWith(list: []);
         changeLoadingState(LoadState.State_Empty, null);
         refreshController.finishRefresh();
       } else {
         //展示加载完成,没有更多数据了
-        if (_page == 1) {
-          //展示无数据的布局
-          state.list!.clear();
-          changeLoadingState(LoadState.State_Empty, null);
-          refreshController.finishRefresh();
-        } else {
-          //展示加载完成,没有更多数据了
-          if(state.list!.length == 0){
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishLoad();
-          }else {
-            if(_needShowPlaceholder){
-              changeLoadingState(LoadState.State_Success, null);
-            }
-          }
-          //更新展示的状态
-          refreshController.finishLoad(IndicatorResult.noMore);
-        }
+        refreshController.finishLoad(IndicatorResult.noMore);
       }
     }
   }
 
   // 设置当前的 _queryParams
-  setCurrentQueryParams(Map<String, dynamic> params){
+  setCurrentQueryParams(Map<String, dynamic> params) {
     _queryParams.addAll(params);
   }
 
   // 获取当前的 _queryParams
-  Map<String, dynamic> getCurrentQueryParams(String? key){
-    if(key!=null && key!.isNotEmpty){
+  Map<String, dynamic> getCurrentQueryParams(String? key) {
+    if (key != null && key!.isNotEmpty) {
       return _queryParams[key];
     }
     return _queryParams;
   }
 
-  // 去详情页面
-  gotoCleanOrderDetailPage(BuildContext context, int id, int serviceTypeCode, int serviesStatusCode){
-    CleanOrderDetailPage.startInstance(id: id, serviceTypeCode: serviceTypeCode, serviesStatusCode: serviesStatusCode);
+  // EventBus 的事件接收
+  Subscription? subscribe;
+
+  void registerEventBus() {
+    subscribe = bus.on(AppConstant.eventServiceOrderRefresh, (arg) {
+      if (arg is String) {
+        final String id = arg;
+        Log.d("需要删除的订单id:$id");
+        //从页面列表中找到对应的id并删除对应的Item
+        final updatedList = state.list.where((element) => element.id != id).toList();
+        state = state.copyWith(list: updatedList);
+      }
+    });
+  }
+
+  void unregisterEventBus() {
+    bus.off(AppConstant.eventServiceOrderRefresh, subscribe);
+  }
+
+  //  去详情页面
+  gotoCleanOrderDetailPage(BuildContext context, int id, String cleanServiceType, int serviesStatusCode) {
+    CleanOrderDetailPage.startInstance(id: id, cleanServiceType: cleanServiceType, serviesStatusCode: serviesStatusCode);
   }
-}
+}

+ 1 - 1
packages/cpt_services/lib/modules/services/history/history_vm.g.dart

@@ -6,7 +6,7 @@ part of 'history_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$historyVmHash() => r'2a0c8e7434615d19ce6f2a71d8d4847ae570c1a1';
+String _$historyVmHash() => r'89aa7cc56fe2bb8cf7a7a2d7087f3ca431417819';
 
 /// See also [HistoryVm].
 @ProviderFor(HistoryVm)

+ 16 - 12
packages/cpt_services/lib/modules/services/homeService/home_service_page.dart

@@ -1,5 +1,6 @@
 import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/paid_service_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -91,18 +92,22 @@ class HomeServicePage extends HookConsumerWidget {
                     },
                     successSliverWidget:[
                       SliverGrid(
-                        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
+                        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                           crossAxisCount: 2, // 每行显示两个项目
                           mainAxisSpacing: 15,
                           crossAxisSpacing: 15,
-                          childAspectRatio: 172.5/170, // 宽高比
+                          // childAspectRatio: 172.5/170, // 宽高比
+                          // childAspectRatio: 180/220, // 宽高比
                           // childAspectRatio:  172.5/170 * ScreenUtil.getAdapterSizeCtx(context, 172.5/170), // 宽高比
-                          // childAspectRatio:  172.5/170 * ((172.5/170).ap), // 宽高比
+                          childAspectRatio:  172.5/180 * ((172.5/180).ap), // 宽高比
                         ),
                         delegate: SliverChildBuilderDelegate(
                               (context, index) {
-                            return  _buildHomeServiceItem(context, ref, state.list[index], vm).onTap((){
-                              vm.handlerGotoDetail(context: context, id: state.list[index]['id'], serviceTypeCode: state.list[index]['service_type']);
+                            return  _buildHomeServiceItem(context, ref, state.list[index] as PaidServiceList, vm).onTap((){
+                              // 去详情页面
+                              PaidServiceList paidServiceEntity = state.list[index] as PaidServiceList;
+                              PaidServiceListCategory paidServiceCategory = paidServiceEntity.category!;
+                              vm.handlerGotoDetail(context: context, id: paidServiceEntity.id!, paidServiceCategory: paidServiceCategory!, liked: paidServiceEntity.liked!, likesCount: paidServiceEntity.likesCount!);
                             });
                           },
                           childCount: state.list.length,
@@ -110,7 +115,7 @@ class HomeServicePage extends HookConsumerWidget {
                       ),
                     ],
                   ),
-                ).marginOnly(left: 15,right: 15,top: 0,bottom: 15),
+                ).marginOnly(left: 15,right: 15,top: 15,bottom: 15),
               ),
             ],
           )
@@ -118,10 +123,9 @@ class HomeServicePage extends HookConsumerWidget {
     );
   }
 
-  Widget _buildHomeServiceItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm){
+  Widget _buildHomeServiceItem(BuildContext context, WidgetRef ref, PaidServiceList item, vm){
     return SizedBox(
       width: double.infinity,
-      // height: 170,
       child: Container(
         decoration: BoxDecoration(
           color: context.appColors.whiteBG,
@@ -142,10 +146,11 @@ class HomeServicePage extends HookConsumerWidget {
               Expanded(
                 child: HomeServiceCard(
                     key: UniqueKey(),
-                    itemObj: item.cast<String, dynamic>(),
+                    itemEntity: item,
+                    cleanServiceType: item.category!.type,
                     onClickColleciotn: (dynamic collectionValue) async {
-                      Log.d("点击了喜欢按钮  --id:${item['id']}- $collectionValue");
-                      int id = item['id'];
+                      Log.d("点击了喜欢按钮  --id:${item.id}- $collectionValue");
+                      int id = item.id!;
                       return await vm.handlerClickCollection(id, collectionValue);
                     }
                 ),
@@ -207,7 +212,6 @@ class HomeServicePage extends HookConsumerWidget {
             Log.d("点击了sort");
             vm.handlerClickSortIcon(context);
             expandSortIcon.value = !expandSortIcon.value;
-
           }),
 
           // 排序

+ 5 - 4
packages/cpt_services/lib/modules/services/homeService/home_service_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/paid_service_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class HomeServiceState {
@@ -11,8 +12,8 @@ class HomeServiceState {
   final List<String> sortByOptionsList = ["Most Likes", "Most bookmarked", "View at Most"];
   String? sortBySelectedOption;
 
-  List<Map<String, dynamic>> activeCateGoryList;
-  List<Map<String, dynamic>> list;
+  List<PaidServiceList> activeCateGoryList;
+  List<PaidServiceList> list;
 
 
   HomeServiceState({
@@ -31,8 +32,8 @@ class HomeServiceState {
     String? keyword,
     bool? isLiked,
     String? sortBySelectedOption,
-    List<Map<String, dynamic>>? activeCateGoryList,
-    List<Map<String, dynamic>>? list,
+    List<PaidServiceList>? activeCateGoryList,
+    List<PaidServiceList>? list,
   }) {
     return HomeServiceState(
       loadingState: loadingState ?? this.loadingState,

+ 136 - 122
packages/cpt_services/lib/modules/services/homeService/home_service_vm.dart

@@ -3,9 +3,12 @@ import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
+import 'package:domain/entity/paid_service_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/sp/sp_util.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
@@ -16,8 +19,10 @@ import 'package:widgets/my_checkbox_group.dart';
 import 'package:widgets/picker/option_pick_util.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../../../constants_services.dart';
 import '../../../respository/services_respository.dart';
 import '../../../router/page/services_page_router.dart';
+import '../services_vm.dart';
 import 'home_service_state.dart';
 
 part 'home_service_vm.g.dart';
@@ -55,7 +60,7 @@ class HomeServiceVm extends _$HomeServiceVm {
   @override
   HomeServiceState build(){
     // 引入数据仓库
-    // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     final state = initState();
     Log.d("--------------------------build---------------------");
 
@@ -128,75 +133,76 @@ class HomeServiceVm extends _$HomeServiceVm {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'price': 30,
-        'unit': '/hr',
-        'liked': true,
-        'likes_count': 12,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 1,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'Air Conditioning Cleaning',
-        'price': 10,
-        'unit': '/unit',
-        'liked': false,
-        'likes_count': 10,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 1,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'Cleaning Services',
-        'price': 200,
-        'unit': '/hr',
-        'liked': true,
-        'likes_count': 1212,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
-
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
+    // List<Map<String, dynamic>> list = [
+    //   {
+    //     'id':1,
+    //     'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'House Cleaning Services',
+    //     'price': 30,
+    //     'unit': '/hr',
+    //     'liked': true,
+    //     'likes_count': 12,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    //   {
+    //     'id':2,
+    //     'service_type': 1,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'Air Conditioning Cleaning',
+    //     'price': 10,
+    //     'unit': '/unit',
+    //     'liked': false,
+    //     'likes_count': 10,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    //   {
+    //     'id':3,
+    //     'service_type': 1,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'Cleaning Services',
+    //     'price': 200,
+    //     'unit': '/hr',
+    //     'liked': true,
+    //     'likes_count': 1212,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    // ];
+    // handlerResultData(true, list:list);
+
+    try {
+      //请求网络
+      Map<String, dynamic>  params = {
+        "sort": null, // 排序(desc=降序,asc=升序)
+        "sort_by": null,  // 排序(likes_count=点赞量,orders_count=下单量,clicks_count=点击量)
+        "category_id": _queryParams['category_id'],
+        "keyword": _queryParams['keyword'],
+        "page": _page,
+        "limit": _limit,
+      };
+      Log.d("请求参数------$params");
+      final result = await servicesRespositoryInstance.fetchPaidServiceDataList(params);
+      //校验成功失败
+      if (result.isSuccess) {
+        handlerResultList((result.data as PaidServiceEntity)?.list as List<PaidServiceList>?, isLoadMore ?? false);
+      } else {
+        String errorMessage = result.errorMsg!;
+        changeLoadingState(LoadState.State_Error, errorMessage);
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
 
     // 最后赋值
     _needShowPlaceholder = false;
 
   }
 
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
+  handlerResultData(bool isList, {List<PaidServiceList>? list, dynamic? data}){
     Future.delayed(const Duration(seconds: 1)).then((value) {
       if(isList){
         // list 数据模式
@@ -242,20 +248,20 @@ class HomeServiceVm extends _$HomeServiceVm {
     });
   }
 
-  void handlerResultList(List<GarageSaleRentList>? list, bool isLoadMore) {
+  void handlerResultList(List<PaidServiceList>? list, bool isLoadMore) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_page == 1) {
         //刷新的方式
         state.list!.clear();
-        state.list!.addAll(list.map((item) => item.toJson()).toList());
+        state.list!.addAll(list);
         refreshController.finishRefresh();
         //更新展示的状态
         changeLoadingState(LoadState.State_Success, null);
       } else {
         //加载更多
         final allList = state.list;
-        allList!.addAll(list.map((item) => item.toJson()).toList());
+        allList!.addAll(list);
         state = state.copyWith(list: allList);
         refreshController.finishLoad();
       }
@@ -291,47 +297,50 @@ class HomeServiceVm extends _$HomeServiceVm {
 
   // 获取 homeservice 的分类选项
   Future<List<Map<String, dynamic>>> getHomeServiceCategoryOptions() async{
-    await Future.delayed(const Duration(milliseconds: 300));
-    ToastEngine.dismiss();
+    // await Future.delayed(const Duration(milliseconds: 300));
+    // ToastEngine.dismiss();
     List<Map<String, dynamic>> serviceCategoryList = [
-      {
-        'id': 1,
-        'name': 'House Cleaning Serivces',
-      },
-      {
-        'id': 2,
-        'name': 'Household Appliance Cleaning',
-      },
+    //   {
+    //     'id': 1,
+    //     'name': 'House Cleaning Serivces',
+    //   },
+    //   {
+    //     'id': 2,
+    //     'name': 'Household Appliance Cleaning',
+    //   },
     ];
 
     // 获取分类列表
-    // try {
-    //   // 加入有缓存 就取缓存
-    //   List<Map<String, dynamic>>? StorageCategoryList = SPUtil.getObjectList(
-    //       AppConstant.storageGarageCategoryList)?.cast<Map<String, dynamic>>();
-    //
-    //   if (StorageCategoryList != null && StorageCategoryList.isNotEmpty) {
-    //     Log.d("取StorageCategoryList 缓存: $StorageCategoryList ");
-    //     serviceCategoryList = StorageCategoryList;
-    //   } else {
-    //     Map<String, dynamic> params = {};
-    //     final result = await commonGarageRespositoryInstance
-    //         .fetchGarageCateGoryList(params);
-    //     if (result.isSuccess) {
-    //       final listJson = result.getListJson();
-    //       // 将 listJson 转换为 List<Map<String, dynamic>>
-    //       serviceCategoryList = (listJson as List?)
-    //           ?.map((item) => item as Map<String, dynamic>)
-    //           .toList() ?? [];
-    //       // 将 serviceCategoryList 存入缓存
-    //       Log.d("设置StorageCategoryList 缓存");
-    //       SPUtil.putObjectList(
-    //           AppConstant.storageGarageCategoryList, serviceCategoryList);
-    //     }
-    //   }
-    // } catch(error){
-    //
-    // }
+    try {
+      // 加入有缓存 就取缓存
+      List<Map<String, dynamic>>? StorageCategoryList = SPUtil.getObjectList(
+          AppConstant.storagePaidServiceCategoryList)?.cast<Map<String, dynamic>>();
+
+      if (StorageCategoryList != null && StorageCategoryList.isNotEmpty) {
+        Log.d("取StorageCategoryList 缓存: $StorageCategoryList ");
+        serviceCategoryList = StorageCategoryList;
+      } else {
+        final paidServiceLayoutVm = ref.watch(servicesVmProvider.notifier);
+        Map<String, dynamic> params = {
+          'parent_id': paidServiceLayoutVm?.state.parentCategoryId,
+        };
+        final result = await servicesRespositoryInstance.fetchServiceCateGoryList(params);
+        if (result.isSuccess) {
+
+          final listJson = result.getListJson();
+          // 将 listJson 转换为 List<Map<String, dynamic>>
+          serviceCategoryList = (listJson as List?)
+              ?.map((item) => item as Map<String, dynamic>)
+              .toList() ?? [];
+          // 将 serviceCategoryList 存入缓存
+          Log.d("设置StorageCategoryList 缓存");
+          SPUtil.putObjectList(
+              AppConstant.storagePaidServiceCategoryList, serviceCategoryList);
+        }
+      }
+    } catch(error){
+      Log.d("获取分类列表失败: $error");
+    }
     return serviceCategoryList;
   }
 
@@ -339,13 +348,13 @@ class HomeServiceVm extends _$HomeServiceVm {
   handlerClickFilterIcon(BuildContext context) async{
     List<Map<String, dynamic>> serviceCategoryList = await getHomeServiceCategoryOptions();
     // 显示弹框
-    handlerShowChooseGarageCategoryDialog(context, serviceCategoryList);
+    handlerShowChooseServiceCategoryDialog(context, serviceCategoryList);
 
   }
 
-  Future<void> handlerShowChooseGarageCategoryDialog(BuildContext context, List<Map<String, dynamic>> garageCategoryList) async{
+  Future<void> handlerShowChooseServiceCategoryDialog(BuildContext context, List<Map<String, dynamic>> categoryList) async{
     await DialogEngine.show(
-        tag: "chooseGarageSaleCategory",
+        tag: "chooseServiceCategory",
         position: DialogPosition.center,
         widget: AppCustomDialog(
           message: '',
@@ -353,7 +362,7 @@ class HomeServiceVm extends _$HomeServiceVm {
           dialogWidth: MediaQuery.of(context).size.width * 0.8,
           // contentBoxMaxHeight: 350,
           // contentBoxMinHeight: 300,
-          isShowConfirmBtn: garageCategoryList!.length > 0 ? true: false,
+          isShowConfirmBtn: categoryList!.length > 0 ? true: false,
           confirmTxt: "Ok",
           messageBuilder: (BuildContext context){
             return Container(
@@ -361,14 +370,14 @@ class HomeServiceVm extends _$HomeServiceVm {
               child: Column(
                 mainAxisAlignment: MainAxisAlignment.start,
                 crossAxisAlignment: CrossAxisAlignment.start,
-                children: garageCategoryList!.length > 0 ? [
+                children: categoryList!.length > 0 ? [
                   MyCheckboxGroup(
                       isSingleSelect: _isSingleSelect,
                       labelStyle: const TextStyle(
                         fontSize: 16,
                         fontWeight: FontWeight.w500,
                       ),
-                      items: garageCategoryList!,
+                      items: categoryList!,
                       defaultSelectedItems: [],
                       onChanged: (List<Map<String, dynamic>> selectedItems){
                         Log.d("----MyCheckboxGroup onChanged  $selectedItems");
@@ -413,22 +422,19 @@ class HomeServiceVm extends _$HomeServiceVm {
       //请求网络
       Map<String, dynamic>  params = {
         "id": id,
+        "type": 'paid', // 类型(paid=付费服务,inquiry=询价服务)
       };
       Log.d("请求参数------$params");
       final result = await servicesRespositoryInstance.fetchServiceLiked(params);
       //校验成功失败
       if (result.isSuccess) {
         // 修改 该id 的 liked 和 likes_count 字段
-        state.list!.forEach((Map<String, dynamic> element) {
-          GarageSaleRentList elementEntity = GarageSaleRentList.fromJson(element);
+        state.list!.forEach((PaidServiceList elementEntity) {
 
           if(elementEntity.id == id){
             elementEntity.liked = !elementEntity.liked!;
             elementEntity.likesCount = elementEntity.liked! ? (elementEntity.likesCount! + 1) : (elementEntity.likesCount! - 1);
           }
-
-          element = elementEntity.toJson();
-
         });
         return true;
       } else {
@@ -484,6 +490,7 @@ class HomeServiceVm extends _$HomeServiceVm {
       onPickerChanged: (_, index) {
         state = state.copyWith(sortBySelectedOption: state.sortByOptionsList?[index]);
         // 调用list 接口
+        directRefresh();
       },
     );
   }
@@ -506,14 +513,21 @@ class HomeServiceVm extends _$HomeServiceVm {
   }
 
   // 去详情页面
-  void handlerGotoDetail({BuildContext? context, required int id, int serviceTypeCode= 0 }){
-    Log.d("去详情页面  $id  $serviceTypeCode");
-    if(serviceTypeCode == 0 || serviceTypeCode == 1){
+  void handlerGotoDetail({
+    BuildContext? context,
+    required int id,
+    required PaidServiceListCategory paidServiceCategory,
+    liked,
+    likesCount,
+  }){
+    final cleanServiceType = paidServiceCategory.name!;
+    Log.d("去详情页面:  $id  $cleanServiceType");
+    if(cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code'] || cleanServiceType == servicesConstants.servicesType['airConditioner']!['code']){
       // clean service  跳转到 clean 详情页
-      appRouter.push(ServiceCleanDetailPageRoute(id: id, serviceTypeCode: serviceTypeCode));
-    }else if(serviceTypeCode == 2){
-      // repair service 跳转到 repair 详情页
-      appRouter.push(ServiceRepairDetailPageRoute(id: id, serviceTypeCode: serviceTypeCode));
+      appRouter.push(ServiceCleanDetailPageRoute(id: id, cleanServiceType: cleanServiceType,liked: liked,likesCount: likesCount));
+    }else {
+      // other service  跳转到 other 详情页
+      ToastEngine.show("${cleanServiceType} 类型的详情暂未开放");
     }
   }
 

+ 1 - 1
packages/cpt_services/lib/modules/services/homeService/home_service_vm.g.dart

@@ -6,7 +6,7 @@ part of 'home_service_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$homeServiceVmHash() => r'f797aaab5c87dfbcd175c7a68c483f501a518020';
+String _$homeServiceVmHash() => r'318c976134aacfdc5ed6c7c8a641351822c48b32';
 
 /// See also [HomeServiceVm].
 @ProviderFor(HomeServiceVm)

+ 107 - 126
packages/cpt_services/lib/modules/services/homeService/service_card_item.dart

@@ -1,176 +1,159 @@
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/paid_service_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:shared/utils/color_utils.dart';
 import 'package:shared/utils/ext_dart.dart';
-import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 
-import '../../../constants_services.dart';
-
-
-// 'id':1,
-// 'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-// 'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-// 'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-// 'title': 'House Cleaning Services',
-// 'price': 66,
-// 'unit': '/hr',
-// 'liked': true,
-// 'likes_count': 1212,
-// 'company_name': 'HONG YE GROUP PTE LTD',
-
-
 class HomeServiceCard extends StatelessWidget {
-  Map<String, dynamic>? serviceType = servicesConstants.servicesType['houseCleaning'];
-  Map<String, dynamic> itemObj;
+  String? cleanServiceType;
+  PaidServiceList itemEntity;
   double? cardHeight;
   final Function()? onTap;
   final Function(dynamic)? onClickColleciotn;
 
   HomeServiceCard({
     Key? key,
-    this.serviceType,
-    required this.itemObj,
+    this.cleanServiceType,
+    required this.itemEntity,
     this.onTap,
     this.onClickColleciotn,
     double? cardHeight,
   }) : super(key: key) {
-    this.cardHeight ??= 170;
+    this.cardHeight ??= 180;
   }
 
   @override
   Widget build(BuildContext context) {
-    List? card_resources = itemObj.getValue<List>("resources", [])?? [];
+    List? card_resources = itemEntity.resources?? [];
+    int card_id = itemEntity.id?? 0;
     String card_img = card_resources.length>0? card_resources[0]:"";
-    String card_title = itemObj.getValue("title", "");
-    final unit = itemObj.getValue("unit", "");
+    String card_name = itemEntity.name?? "";
 
-    int card_price = itemObj.getValue("price", "");
-    String card_created_at = itemObj.getValue("created_at", "");
-    bool card_liked = itemObj.getValue("liked", false);
-    int card_likes_count = itemObj.getValue("likes_count", 0);
-    final company_name = itemObj.getValue("company_name", "");
-    return Column(
-      children: [
-        // 图片
-        Row(
-          mainAxisAlignment: MainAxisAlignment.center,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            Expanded(
-              child: ClipRRect(
-                borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8),),
-                child: MyLoadImage(
-                  card_img,
-                  width: 172.5,
-                  height: 80.5.ap,
-                  isCircle: false,
-                  fit: BoxFit.cover,
-                ),
-              ),
-            ),
-          ],
-        ),
-        // 标题
-        Padding(
-          padding: const EdgeInsets.only(left: 10, right: 10, top: 10,),
-          child: Row(
+    int card_price = itemEntity.lowestPrice?? 0;
+    bool card_liked = itemEntity.liked??false;
+    int card_likes_count = itemEntity.likesCount?? 0;
+
+    final company_name = itemEntity.merchant?.name?? "";
+    return Container(
+      height: cardHeight!,
+      child: Column(
+        children: [
+          // 图片
+          Row(
             mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               Expanded(
-                child: SizedBox(
-                  height: 30.ap,
-                  child: MyTextView(
-                    card_title,
-                    maxLines: 2,
-                    isTextEllipsis: true,
-                    textAlign: TextAlign.left,
-                    textColor: context.appColors.textBlack,
-                    fontSize: 15,
-                    isFontRegular: true,
+                child: ClipRRect(
+                  borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8),),
+                  child: MyLoadImage(
+                    card_img,
+                    width: 172.5,
+                    height: 75,
+                    isCircle: false,
+                    fit: BoxFit.fitWidth,
                   ),
                 ),
               ),
             ],
           ),
-        ),
-        // 价格 及 收藏
-        Padding(
-          padding: const EdgeInsets.only(left: 10, right: 10,top: 0, bottom: 0),
-          child: Row(
-            mainAxisAlignment: MainAxisAlignment.spaceAround,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              Expanded(
-                child: Row(
-                  mainAxisAlignment: MainAxisAlignment.start,
-                  crossAxisAlignment: CrossAxisAlignment.center,
-                  children: [
-                    MyTextView(
-                      'from',
-                      maxLines: 1,
-                      isTextEllipsis: true,
-                      textAlign: TextAlign.start,
-                      textColor: ColorUtils.string2Color('#666666'),
-                      fontSize: 11,
-                      isFontMedium: true,
-                    ),
-                    MyTextView(
-                      '\$$card_price',
-                      maxLines: 1,
-                      isTextEllipsis: true,
-                      textAlign: TextAlign.start,
-                      textColor: ColorUtils.string2Color('#4161D0'),
-                      fontSize: 15,
-                      isFontMedium: true,
-                      marginLeft: 2,
-                    ),
-                    MyTextView(
-                      '$unit',
-                      maxLines: 1,
+          // 标题
+          Padding(
+            padding:  EdgeInsets.only(left: 10, right: 10, top: 5,),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: [
+                Expanded(
+                  child: SizedBox(
+                    child: MyTextView(
+                      '$card_name',
+                      maxLines: 2,
                       isTextEllipsis: true,
-                      textAlign: TextAlign.start,
-                      textColor: ColorUtils.string2Color('#666666'),
-                      fontSize: 11,
-                      isFontMedium: true,
+                      textAlign: TextAlign.left,
+                      textColor: context.appColors.textBlack,
+                      fontSize: 14,
+                      isFontRegular: true,
                     ),
-                  ],
+                  ),
                 ),
-              ),
-              // 动态的 收藏数
-              CollectionWidget(
-                collectionNum: card_likes_count,
-                isCollection: card_liked,
-                onClickColleciotn: onClickColleciotn,
-              ),
-            ],
+              ],
+            ),
           ),
-        ),
-        // 公司名称
-        Expanded(
-          child: Padding(
-            padding: const EdgeInsets.only(bottom: 5),
+          // 价格 及 收藏
+          Padding(
+            padding:  const EdgeInsets.only(left: 10, right: 10,top: 10),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                Expanded(
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.start,
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      MyTextView(
+                        'from',
+                        maxLines: 1,
+                        isTextEllipsis: true,
+                        textAlign: TextAlign.start,
+                        textColor: ColorUtils.string2Color('#666666'),
+                        fontSize: 11,
+                        isFontMedium: true,
+                      ),
+                      MyTextView(
+                        '\$$card_price',
+                        maxLines: 1,
+                        isTextEllipsis: true,
+                        textAlign: TextAlign.start,
+                        textColor: ColorUtils.string2Color('#4161D0'),
+                        fontSize: 15,
+                        isFontMedium: true,
+                        marginLeft: 2,
+                      ),
+                      // MyTextView(
+                      //   '$',
+                      //   maxLines: 1,
+                      //   isTextEllipsis: true,
+                      //   textAlign: TextAlign.start,
+                      //   textColor: ColorUtils.string2Color('#666666'),
+                      //   fontSize: 11,
+                      //   isFontMedium: true,
+                      // ),
+                    ],
+                  ),
+                ),
+                // 动态的 收藏数
+                CollectionWidget(
+                  collectionNum: card_likes_count,
+                  isCollection: card_liked,
+                  onClickColleciotn: onClickColleciotn,
+                ),
+              ],
+            ),
+          ),
+          // 公司名称
+          Expanded(
             child: MyTextView(
               company_name,
               maxLines: 1,
               isTextEllipsis: true,
               textAlign: TextAlign.start,
-              marginLeft: 13,
+              marginLeft: 10,
               fontSize: 11,
               textColor: ColorUtils.string2Color('#666666'),
               alignment: Alignment.centerLeft,
               isFontRegular: true,
             ),
-          ),
-        )
-      ],
+          )
+        ],
+      ),
     );
   }
 }
@@ -192,8 +175,6 @@ class CollectionWidget extends HookConsumerWidget {
     final collectionNumState = useState(collectionNum);
     final isCollectionState = useState(isCollection);
     return Container(
-        width: 60,
-        height: 30,
         alignment: Alignment.center,
         // decoration: BoxDecoration(
         //   color: ColorUtils.string2Color('#E5E5E5'),
@@ -211,8 +192,8 @@ class CollectionWidget extends HookConsumerWidget {
               ),
               MyLoadImage(
                 isCollectionState.value? Assets.communityLikeActive: Assets.communityLike,
-                width: 14.1,
-                height: 14,
+                width: isCollectionState.value? 15.5:14.1,
+                height: isCollectionState.value? 14:14,
               )
             ]
           // 点击 收餐/取消收藏

+ 22 - 33
packages/cpt_services/lib/modules/services/inProgress/in_progress_page.dart

@@ -1,4 +1,5 @@
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
@@ -38,14 +39,13 @@ class InProgressPage extends HookConsumerWidget {
     }
   }
 
-
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(inProgressVmProvider.notifier);
     final state = ref.watch(inProgressVmProvider);
     // final appConfigState = ref.watch(appConfigServiceProvider)
 
-    int serviceTypeCode = servicesConstants.servicesType['houseCleaning']?['code'];
+    String cleanServiceType = servicesConstants.servicesType['houseCleaning']?['code'];
     int serviceStatusCode = servicesConstants.servicesStatus['1']?['code'];
 
     useEffect(() {
@@ -71,12 +71,12 @@ class InProgressPage extends HookConsumerWidget {
             key: ValueKey('inProgress'),
             controller: vm.refreshController,
             // 上拉加载
-            onLoad: () async{
+            onLoad: () async {
               Log.d("----onLoad");
               vm.loadMore();
             },
             // 下拉刷新
-            onRefresh: () async{
+            onRefresh: () async {
               Log.d("----onRefresh");
               vm.onRefresh();
             },
@@ -86,23 +86,16 @@ class InProgressPage extends HookConsumerWidget {
               errorRetry: () {
                 vm.retryRequest();
               },
-              successSliverWidget:[
+              successSliverWidget: [
                 SliverList(
                   delegate: SliverChildBuilderDelegate(
-                        (context, index) {
-                      return  _buildInProgressItem(
-                          context,
-                          ref,
-                          state.list[index],
-                          vm,
-                          serviceTypeCode,
-                          serviceStatusCode
-                      ).onTap((){
+                    (context, index) {
+                      return _buildInProgressItem(context, ref, state.list[index], vm,  cleanServiceType, serviceStatusCode).onTap(() {
                         vm.gotoCleanOrderDetailPage(
-                            context,
-                            state.list?[index]['id'],
-                            serviceTypeCode,
-                            serviceStatusCode
+                          context,
+                          state.list[index].id != null ? int.tryParse(state.list[index].id!) ?? 0 : 0,
+                          cleanServiceType,
+                          serviceStatusCode,
                         );
                       });
                     },
@@ -111,12 +104,11 @@ class InProgressPage extends HookConsumerWidget {
                 )
               ],
             ),
-          ).marginOnly(left: 15,right: 15,top: 0,bottom: 15)
-      ),
+          ).marginOnly(left: 15, right: 15, top: 0, bottom: 15)),
     );
   }
 
-  Widget _buildInProgressItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm, int serviceTypeCode, int serviceStatusCode){
+  Widget _buildInProgressItem(BuildContext context, WidgetRef ref, GarageSaleHistoryList item, vm, String cleanServiceType, int serviceStatusCode) {
     return Container(
       margin: const EdgeInsets.only(top: 9),
       width: double.infinity,
@@ -132,18 +124,15 @@ class InProgressPage extends HookConsumerWidget {
         ],
       ),
       child: StausCardItem(
-          key: UniqueKey(),
-          cardHeight: 175.0,
-          serviceId: item['id'],
-          serviceTypeCode: serviceTypeCode,
-          serviceStatusCode: serviceStatusCode,
-          itemObj: item.cast<String, dynamic>(),
-          onClickCard: (dynamic value) async {
-            // Log.d("点击了喜欢按钮  --id:${item['id']}- $collectionValue");
-            // int id = item['id'];
-            // return await vm.handlerClickCollection(id, collectionValue);
-          },
+        key: UniqueKey(),
+        cardHeight: 140.0,
+        item: item,
+        onClickCard: (dynamic value) async {
+          // Log.d("点击了喜欢按钮  --id:${item['id']}- $collectionValue");
+          // int id = item['id'];
+          // return await vm.handlerClickCollection(id, collectionValue);
+        },
       ),
     );
   }
-}
+}

+ 3 - 2
packages/cpt_services/lib/modules/services/inProgress/in_progress_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class InProgressState {
@@ -7,7 +8,7 @@ class InProgressState {
 
   String? keyword;
   bool? isLiked;
-  List<Map<String, dynamic>> list;
+  List<GarageSaleHistoryList> list;
 
 
   InProgressState({
@@ -25,7 +26,7 @@ class InProgressState {
     bool? isLiked,
     Map<String, dynamic>? activeSortMap,
     List<Map<String, dynamic>>? activeCateGoryList,
-    List<Map<String, dynamic>>? list,
+    List<GarageSaleHistoryList>? list,
   }) {
     return InProgressState(
       loadingState: loadingState ?? this.loadingState,

+ 61 - 165
packages/cpt_services/lib/modules/services/inProgress/in_progress_vm.dart

@@ -1,9 +1,11 @@
-
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -14,14 +16,15 @@ import '../../../respository/services_respository.dart';
 import '../../../router/page/services_page_router.dart';
 import '../clean_order_detail/clean_order_detail_page.dart';
 import 'in_progress_state.dart';
+import 'package:shared/utils/event_bus.dart';
 
 part 'in_progress_vm.g.dart';
 
 @riverpod
-class InProgressVm extends _$InProgressVm {
+class InProgressVm extends _$InProgressVm with DioCancelableMixin {
   late ServicesRespository servicesRespositoryInstance;
   bool _needShowPlaceholder = false; //是否展示LoadingView
-  int _page = 1;  // 当前页
+  int _page = 1; // 当前页
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
 
@@ -33,33 +36,31 @@ class InProgressVm extends _$InProgressVm {
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   InProgressState initState() {
-    return InProgressState(
-        list: []
-    );
+    return InProgressState(list: []);
   }
 
   @override
-  InProgressState build(){
+  InProgressState build() {
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     // 引入数据仓库
     // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
     final state = initState();
+    registerEventBus();
     Log.d("--------------------------build---------------------");
-
+    registerCancellation(callback: () {
+      unregisterEventBus();
+    });
     return state;
   }
 
-
   //刷新页面状态
   void changeLoadingState(LoadState loadState, String? errorMsg) {
-    state = state.copyWith(
-        loadingState: loadState,
-        errorMessage: errorMsg
-    );
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
   }
 
   // 初始化页面数据
@@ -75,7 +76,6 @@ class InProgressVm extends _$InProgressVm {
     getListData();
   }
 
-
   // 下拉刷新
   Future onRefresh() async {
     // 当前pageView 页面正处于显示状态
@@ -85,7 +85,6 @@ class InProgressVm extends _$InProgressVm {
     getListData();
   }
 
-
   // 手动进行刷新
   Future triggerRefresh() async {
     Log.d("trggerRefresh");
@@ -94,7 +93,7 @@ class InProgressVm extends _$InProgressVm {
 
   // 手动进行刷新
   Future directRefresh() async {
-    state = state.copyWith(list:[]);
+    state = state.copyWith(list: []);
     // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
     // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
     refreshController.callRefresh();
@@ -104,7 +103,6 @@ class InProgressVm extends _$InProgressVm {
     getListData();
   }
 
-
   // 重试请求
   Future retryRequest() async {
     _page = 1;
@@ -112,195 +110,93 @@ class InProgressVm extends _$InProgressVm {
     getListData();
   }
 
-
   // 获取list 列表数据
   Future getListData<T>({bool? isLoadMore}) async {
     if (_needShowPlaceholder) {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 0,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
+    // 获取列表
+    var listResult = await servicesRespositoryInstance.fetchPaidServiceOrderList(
+      type: "in_progress",
+      curPage: _page,
+      cancelToken: cancelToken,
+    );
 
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.list);
+    } else {
+      changeLoadingState(LoadState.State_Error, listResult.errorMsg);
+    }
 
     // 最后赋值
     _needShowPlaceholder = false;
-
-  }
-
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
-    Future.delayed(const Duration(seconds: 1)).then((value) {
-      if(isList){
-        // list 数据模式
-        if(list != null && list.isNotEmpty){
-          if(_page == 1){
-            state.list.clear();
-            state.list!.addAll(list);
-            refreshController.finishRefresh();
-            changeLoadingState(LoadState.State_Success, null);
-          }else {
-            final allList = state.list;
-            allList!.addAll(list);
-            state = state.copyWith(list: allList);
-            refreshController.finishLoad();
-          }
-        }else {
-          if(_page == 1){
-            state.list.clear();
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishRefresh();
-          }else {
-            refreshController.finishLoad(IndicatorResult.noMore);
-          }
-        }
-      }else {
-        // 单个数据模式
-        if(data!=null){
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Success, null);
-        }else {
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Empty, null);
-        }
-      }
-    });
   }
 
-  void handlerResultList(List<GarageSaleRentList>? list, bool isLoadMore) {
+  // 处理数据与展示的逻辑
+  void handleList(List<GarageSaleHistoryList>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_page == 1) {
         //刷新的方式
-        state.list!.clear();
-        state.list!.addAll(list.map((item) => item.toJson()).toList());
+        state = state.copyWith(list: list);
         refreshController.finishRefresh();
+
         //更新展示的状态
         changeLoadingState(LoadState.State_Success, null);
       } else {
         //加载更多
-        final allList = state.list;
-        allList!.addAll(list.map((item) => item.toJson()).toList());
-        state = state.copyWith(list: allList);
+        state.list.addAll(List<GarageSaleHistoryList>.from(state.list)..addAll(list));
         refreshController.finishLoad();
       }
     } else {
       if (_page == 1) {
         //展示无数据的布局
-        state.list!.clear();
+        state = state.copyWith(list: []);
         changeLoadingState(LoadState.State_Empty, null);
         refreshController.finishRefresh();
       } else {
         //展示加载完成,没有更多数据了
-        if (_page == 1) {
-          //展示无数据的布局
-          state.list!.clear();
-          changeLoadingState(LoadState.State_Empty, null);
-          refreshController.finishRefresh();
-        } else {
-          //展示加载完成,没有更多数据了
-          if(state.list!.length == 0){
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishLoad();
-          }else {
-            if(_needShowPlaceholder){
-              changeLoadingState(LoadState.State_Success, null);
-            }
-          }
-          //更新展示的状态
-          refreshController.finishLoad(IndicatorResult.noMore);
-        }
+        refreshController.finishLoad(IndicatorResult.noMore);
       }
     }
   }
 
   // 设置当前的 _queryParams
-  setCurrentQueryParams(Map<String, dynamic> params){
+  setCurrentQueryParams(Map<String, dynamic> params) {
     _queryParams.addAll(params);
   }
 
   // 获取当前的 _queryParams
-  Map<String, dynamic> getCurrentQueryParams(String? key){
-    if(key!=null && key!.isNotEmpty){
+  Map<String, dynamic> getCurrentQueryParams(String? key) {
+    if (key != null && key!.isNotEmpty) {
       return _queryParams[key];
     }
     return _queryParams;
   }
 
+  // EventBus 的事件接收
+  Subscription? subscribe;
+
+  void registerEventBus() {
+    subscribe = bus.on(AppConstant.eventServiceOrderRefresh, (arg) {
+      if (arg is String) {
+        final String id = arg;
+        Log.d("需要删除的订单id:$id");
+        //从页面列表中找到对应的id并删除对应的Item
+        final updatedList = state.list.where((element) => element.id != id).toList();
+        state = state.copyWith(list: updatedList);
+      }
+    });
+  }
+
+  void unregisterEventBus() {
+    bus.off(AppConstant.eventServiceOrderRefresh, subscribe);
+  }
+
   //  去详情页面
-  gotoCleanOrderDetailPage(BuildContext context, int id, int serviceTypeCode, int serviesStatusCode){
-    CleanOrderDetailPage.startInstance(id: id, serviceTypeCode: serviceTypeCode, serviesStatusCode: serviesStatusCode);
+  gotoCleanOrderDetailPage(BuildContext context, int id, String cleanServiceType, int serviesStatusCode) {
+    CleanOrderDetailPage.startInstance(id: id, cleanServiceType: cleanServiceType, serviesStatusCode: serviesStatusCode);
   }
-}
+}

+ 1 - 1
packages/cpt_services/lib/modules/services/inProgress/in_progress_vm.g.dart

@@ -6,7 +6,7 @@ part of 'in_progress_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$inProgressVmHash() => r'f3c62cd304779aec9504c09d4f83e8b32787073a';
+String _$inProgressVmHash() => r'cf2b1d13c3c134c4b8a29e257fda6e652af9061d';
 
 /// See also [InProgressVm].
 @ProviderFor(InProgressVm)

+ 14 - 11
packages/cpt_services/lib/modules/services/repair/repair_page.dart

@@ -27,14 +27,15 @@ final GlobalKey<ExtendedNestedScrollViewState> extendedNestedScrollViewKey =
 GlobalKey<ExtendedNestedScrollViewState>();
 @RoutePage()
 class RepairPage extends HookConsumerWidget with WidgetsBindingObserver {
-  RepairPage({Key? key}) : super(key: key);
+  int parentCategoryId = 0; //父级分类id
+  RepairPage({Key? key, required this.parentCategoryId}) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context}) {
+  static void startInstance({BuildContext? context, required int parentCategoryId}) {
     if (context != null) {
-      context.router.push( RepairPageRoute());
+      context.router.push( RepairPageRoute(parentCategoryId:parentCategoryId));
     } else {
-      appRouter.push( RepairPageRoute());
+      appRouter.push( RepairPageRoute(parentCategoryId:parentCategoryId));
     }
   }
 
@@ -120,13 +121,15 @@ class RepairPage extends HookConsumerWidget with WidgetsBindingObserver {
             context,
             value: vm.getCurrentQueryParams('keyword'),
             actions: [
-              const MyAssetImage(
-                Assets.serviceServiceScoreYes,
-                width: 21.5,
-                height: 21.5,
-              ).onTap((){
-                vm.handlerClickNavbarLikeBtn(context);
-              }),
+              (state.currentPageViewIdx == 0) ? Container(
+                child: const MyAssetImage(
+                  Assets.serviceServiceScoreYes,
+                  width: 21.5,
+                  height: 21.5,
+                ).onTap((){
+                  vm.handlerClickNavbarLikeBtn(context);
+                }),
+              ):const SizedBox.shrink(),
               const SizedBox(width: 15),
             ],
             backgroundColor: context.appColors.backgroundWhite,

+ 87 - 35
packages/cpt_services/lib/modules/services/repair_history/history_page.dart

@@ -1,5 +1,4 @@
-import 'package:cs_resources/generated/assets.dart';
-import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/service_in_progress_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -46,7 +45,7 @@ class RepairHistoryPage extends HookConsumerWidget {
     final state = ref.watch(repairHistoryVmProvider);
     // final appConfigState = ref.watch(appConfigServiceProvider)
 
-    int serviceTypeCode = servicesConstants.servicesType['houseCleaning']?['code'];
+    String cleanServiceType = servicesConstants.servicesType['houseCleaning']?['code'];
     int serviceStatusCode = servicesConstants.servicesStatus['2']?['code'];
 
 
@@ -62,7 +61,7 @@ class RepairHistoryPage extends HookConsumerWidget {
     return Scaffold(
       // appBar: MyAppBar.appBar(
       //   context,
-      //   "RepairHistory",
+      //   "History",
       //   backgroundColor: context.appColors.whiteBG,
       // ),
       backgroundColor: ColorUtils.string2Color("#F2F3F6"),
@@ -73,12 +72,12 @@ class RepairHistoryPage extends HookConsumerWidget {
             key: ValueKey('history'),
             controller: vm.refreshController,
             // 上拉加载
-            onLoad: () async{
+            onLoad: () async {
               Log.d("----onLoad");
               vm.loadMore();
             },
             // 下拉刷新
-            onRefresh: () async{
+            onRefresh: () async {
               Log.d("----onRefresh");
               vm.onRefresh();
             },
@@ -88,24 +87,18 @@ class RepairHistoryPage extends HookConsumerWidget {
               errorRetry: () {
                 vm.retryRequest();
               },
-              successSliverWidget:[
+              successSliverWidget: [
                 SliverList(
                   delegate: SliverChildBuilderDelegate(
-                        (context, index) {
-                      return  _buildRepairHistoryItem(
-                          context,
-                          ref,
-                          state.list[index],
-                          vm,
-                          serviceTypeCode,
-                          serviceStatusCode,
-                      ).onTap((){
-                        // vm.gotoCleanOrderDetailPage(
-                        //   context,
-                        //   state.list?[index]['id'],
-                        //   serviceTypeCode,
-                        //   serviceStatusCode,
-                        // );
+                    (context, index) {
+                      return _buildRepairHistoryItem(
+                        context,
+                        ref,
+                        state.list[index],
+                        vm,
+                        cleanServiceType,
+                        serviceStatusCode,
+                      ).onTap(() {
                       });
                     },
                     childCount: state.list.length,
@@ -113,12 +106,11 @@ class RepairHistoryPage extends HookConsumerWidget {
                 )
               ],
             ),
-          ).marginOnly(left: 15,right: 15,top: 0,bottom: 15)
-      ),
+          ).marginOnly(left: 15, right: 15, top: 0, bottom: 15)),
     );
   }
 
-  Widget _buildRepairHistoryItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm, int serviceTypeCode, int serviceStatusCode){
+  Widget _buildRepairHistoryItem(BuildContext context, WidgetRef ref, ServiceInProgressList item, vm, String cleanServiceType, int serviceStatusCode){
     return Container(
       margin: const EdgeInsets.only(top: 9),
       width: double.infinity,
@@ -133,16 +125,76 @@ class RepairHistoryPage extends HookConsumerWidget {
           ),
         ],
       ),
-      child: RepairStausCardItem(
-        key: UniqueKey(),
-        cardHeight: 150.0,
-        serviceId: item['id'],
-        serviceTypeCode: serviceTypeCode,
-        serviceStatusCode: serviceStatusCode,
-        itemObj: item.cast<String, dynamic>(),
-        onClickCard: (dynamic value) async {
-        },
+      child: Container(
+        width: double.infinity,
+        height: 140,
+        child: Padding(
+          padding: const EdgeInsets.only(
+              left: 18.0, right: 18.0, top: 10.0, bottom: 10.0),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Expanded(
+                  child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  // 标题 和状态
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: [
+                      // 标题
+                      Expanded(
+                        child: MyTextView(
+                          item?.service?.name ?? "-",
+                          fontSize: 16,
+                          maxLines: 1,
+                          isFontBold: true,
+                          textAlign: TextAlign.left,
+                        ),
+                      ),
+                      // 状态
+                      MyTextView(
+                        item?.orderStatus ?? "-",
+                        fontSize: 14,
+                        maxLines: 1,
+                        isFontRegular: true,
+                        textAlign: TextAlign.left,
+                        textColor: context.appColors.textPrimary,
+                      ),
+                    ],
+                  ),
+                  // 公司名称
+                  MyTextView(
+                    item?.merchant?.name ?? "-",
+                    fontSize: 14,
+                    maxLines: 1,
+                    isFontRegular: true,
+                    textAlign: TextAlign.left,
+                    marginTop: 6,
+                  ),
+                  const SizedBox(
+                    height: 5,
+                  ),
+                  // visit time
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: [
+                      MyTextView(
+                        item?.merchantNotes ?? "-",
+                        fontSize: 14,
+                        maxLines: 1,
+                        isFontRegular: true,
+                        textAlign: TextAlign.left,
+                        textColor: context.appColors.textDarkGray,
+                      ),
+                    ],
+                  ),
+                ],
+              )),
+            ],
+          ),
+        ),
       ),
     );
   }
-}
+}

+ 5 - 4
packages/cpt_services/lib/modules/services/repair_history/history_state.dart

@@ -1,3 +1,5 @@
+import 'package:domain/entity/garage_sale_history_entity.dart';
+import 'package:domain/entity/service_in_progress_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class RepairHistoryState {
@@ -7,8 +9,7 @@ class RepairHistoryState {
 
   String? keyword;
   bool? isLiked;
-  List<Map<String, dynamic>> list;
-
+  List<ServiceInProgressList> list;
 
   RepairHistoryState({
     this.loadingState = LoadState.State_Loading,
@@ -25,7 +26,7 @@ class RepairHistoryState {
     bool? isLiked,
     Map<String, dynamic>? activeSortMap,
     List<Map<String, dynamic>>? activeCateGoryList,
-    List<Map<String, dynamic>>? list,
+    List<ServiceInProgressList>? list,
   }) {
     return RepairHistoryState(
       loadingState: loadingState ?? this.loadingState,
@@ -35,4 +36,4 @@ class RepairHistoryState {
       list: list ?? this.list,
     );
   }
-}
+}

+ 40 - 164
packages/cpt_services/lib/modules/services/repair_history/history_vm.dart

@@ -1,9 +1,11 @@
-
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
+import 'package:domain/entity/service_in_progress_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -18,10 +20,10 @@ import 'history_state.dart';
 part 'history_vm.g.dart';
 
 @riverpod
-class RepairHistoryVm extends _$RepairHistoryVm {
+class RepairHistoryVm extends _$RepairHistoryVm with DioCancelableMixin {
   late ServicesRespository servicesRespositoryInstance;
   bool _needShowPlaceholder = false; //是否展示LoadingView
-  int _page = 1;  // 当前页
+  int _page = 1; // 当前页
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
 
@@ -33,33 +35,29 @@ class RepairHistoryVm extends _$RepairHistoryVm {
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   RepairHistoryState initState() {
-    return RepairHistoryState(
-        list: []
-    );
+    return RepairHistoryState(list: []);
   }
 
   @override
-  RepairHistoryState build(){
+  RepairHistoryState build() {
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     // 引入数据仓库
     // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
     final state = initState();
     Log.d("--------------------------build---------------------");
+    registerCancellation();
 
     return state;
   }
 
-
   //刷新页面状态
   void changeLoadingState(LoadState loadState, String? errorMsg) {
-    state = state.copyWith(
-        loadingState: loadState,
-        errorMessage: errorMsg
-    );
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
   }
 
   // 初始化页面数据
@@ -75,7 +73,6 @@ class RepairHistoryVm extends _$RepairHistoryVm {
     getListData();
   }
 
-
   // 下拉刷新
   Future onRefresh() async {
     // 当前pageView 页面正处于显示状态
@@ -85,7 +82,6 @@ class RepairHistoryVm extends _$RepairHistoryVm {
     getListData();
   }
 
-
   // 手动进行刷新
   Future triggerRefresh() async {
     Log.d("trggerRefresh");
@@ -94,7 +90,7 @@ class RepairHistoryVm extends _$RepairHistoryVm {
 
   // 手动进行刷新
   Future directRefresh() async {
-    state = state.copyWith(list:[]);
+    state = state.copyWith(list: []);
     // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
     // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
     refreshController.callRefresh();
@@ -104,7 +100,6 @@ class RepairHistoryVm extends _$RepairHistoryVm {
     getListData();
   }
 
-
   // 重试请求
   Future retryRequest() async {
     _page = 1;
@@ -112,195 +107,76 @@ class RepairHistoryVm extends _$RepairHistoryVm {
     getListData();
   }
 
-
   // 获取list 列表数据
   Future getListData<T>({bool? isLoadMore}) async {
     if (_needShowPlaceholder) {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 2,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 2,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 3,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
+    // 获取列表
+    var listResult =
+        await servicesRespositoryInstance.fetchRepairServiceOrderList(
+      status: 1,
+      curPage: _page,
+      cancelToken: cancelToken,
+    );
 
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.list);
+    } else {
+      changeLoadingState(LoadState.State_Error, listResult.errorMsg);
+    }
 
     // 最后赋值
     _needShowPlaceholder = false;
-
   }
 
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
-    Future.delayed(const Duration(seconds: 1)).then((value) {
-      if(isList){
-        // list 数据模式
-        if(list != null && list.isNotEmpty){
-          if(_page == 1){
-            state.list.clear();
-            state.list!.addAll(list);
-            refreshController.finishRefresh();
-            changeLoadingState(LoadState.State_Success, null);
-          }else {
-            final allList = state.list;
-            allList!.addAll(list);
-            state = state.copyWith(list: allList);
-            refreshController.finishLoad();
-          }
-        }else {
-          if(_page == 1){
-            state.list.clear();
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishRefresh();
-          }else {
-            refreshController.finishLoad(IndicatorResult.noMore);
-          }
-        }
-      }else {
-        // 单个数据模式
-        if(data!=null){
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Success, null);
-        }else {
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Empty, null);
-        }
-      }
-    });
-  }
-
-  void handlerResultList(List<GarageSaleRentList>? list, bool isLoadMore) {
+  // 处理数据与展示的逻辑
+  void handleList(List<ServiceInProgressList>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_page == 1) {
         //刷新的方式
-        state.list!.clear();
-        state.list!.addAll(list.map((item) => item.toJson()).toList());
+        state = state.copyWith(list: list);
         refreshController.finishRefresh();
+
         //更新展示的状态
         changeLoadingState(LoadState.State_Success, null);
       } else {
         //加载更多
-        final allList = state.list;
-        allList!.addAll(list.map((item) => item.toJson()).toList());
-        state = state.copyWith(list: allList);
+        state.list
+            .addAll(List<ServiceInProgressList>.from(state.list)..addAll(list));
         refreshController.finishLoad();
       }
     } else {
       if (_page == 1) {
         //展示无数据的布局
-        state.list!.clear();
+        state = state.copyWith(list: []);
         changeLoadingState(LoadState.State_Empty, null);
         refreshController.finishRefresh();
       } else {
         //展示加载完成,没有更多数据了
-        if (_page == 1) {
-          //展示无数据的布局
-          state.list!.clear();
-          changeLoadingState(LoadState.State_Empty, null);
-          refreshController.finishRefresh();
-        } else {
-          //展示加载完成,没有更多数据了
-          if(state.list!.length == 0){
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishLoad();
-          }else {
-            if(_needShowPlaceholder){
-              changeLoadingState(LoadState.State_Success, null);
-            }
-          }
-          //更新展示的状态
-          refreshController.finishLoad(IndicatorResult.noMore);
-        }
+        refreshController.finishLoad(IndicatorResult.noMore);
       }
     }
   }
 
   // 设置当前的 _queryParams
-  setCurrentQueryParams(Map<String, dynamic> params){
+  setCurrentQueryParams(Map<String, dynamic> params) {
     _queryParams.addAll(params);
   }
 
   // 获取当前的 _queryParams
-  Map<String, dynamic> getCurrentQueryParams(String? key){
-    if(key!=null && key!.isNotEmpty){
+  Map<String, dynamic> getCurrentQueryParams(String? key) {
+    if (key != null && key!.isNotEmpty) {
       return _queryParams[key];
     }
     return _queryParams;
   }
 
   // 去详情页面
-  gotoCleanOrderDetailPage(BuildContext context, int id, int serviceTypeCode, int serviesStatusCode){
-    CleanOrderDetailPage.startInstance(id: id, serviceTypeCode: serviceTypeCode, serviesStatusCode: serviesStatusCode);
+  gotoCleanOrderDetailPage(BuildContext context, int id, String cleanServiceType, int serviesStatusCode){
+    CleanOrderDetailPage.startInstance(id: id, cleanServiceType: cleanServiceType, serviesStatusCode: serviesStatusCode);
   }
-}
+}

+ 1 - 1
packages/cpt_services/lib/modules/services/repair_history/history_vm.g.dart

@@ -6,7 +6,7 @@ part of 'history_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$repairHistoryVmHash() => r'a85e3ce352d40334a0721d399e66a94c49f2869e';
+String _$repairHistoryVmHash() => r'02b81fc894e21133f15ca8b36d8026e2c195880e';
 
 /// See also [RepairHistoryVm].
 @ProviderFor(RepairHistoryVm)

+ 15 - 8
packages/cpt_services/lib/modules/services/repair_homeService/home_service_page.dart

@@ -1,5 +1,6 @@
 import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/repair_service_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -95,14 +96,19 @@ class RepairHomeServicePage extends HookConsumerWidget {
                           crossAxisCount: 2, // 每行显示两个项目
                           mainAxisSpacing: 15,
                           crossAxisSpacing: 15,
-                          childAspectRatio: 172.5/170, // 宽高比
+                          // childAspectRatio: 172.5/170, // 宽高比
+                          childAspectRatio: 180/200, // 宽高比
                           // childAspectRatio:  172.5/170 * ScreenUtil.getAdapterSizeCtx(context, 172.5/170), // 宽高比
                           // childAspectRatio:  172.5/170 * ((172.5/170).ap), // 宽高比
                         ),
                         delegate: SliverChildBuilderDelegate(
                               (context, index) {
-                            return  _buildRepairHomeServiceItem(context, ref, state.list[index], vm).onTap((){
-                              vm.handlerGotoDetail(context: context, id: state.list[index]['id'], serviceTypeCode: state.list[index]['service_type']);
+                            return  _buildRepairHomeServiceItem(context, ref, state.list[index] as RepairServiceList, vm).onTap((){
+                              // 去详情页面
+                              RepairServiceList repairServiceEntity = state.list[index] as RepairServiceList;
+                              RepairServiceListCategory repairServiceCategory = repairServiceEntity.category!;
+                              vm.handlerGotoDetail(context: context, id: repairServiceEntity.id!, repairServiceListCategory: repairServiceCategory!);
+
                             });
                           },
                           childCount: state.list.length,
@@ -110,7 +116,7 @@ class RepairHomeServicePage extends HookConsumerWidget {
                       ),
                     ],
                   ),
-                ).marginOnly(left: 15,right: 15,top: 0,bottom: 15),
+                ).marginOnly(left: 15,right: 15,top: 15,bottom: 15),
               ),
             ],
           )
@@ -118,7 +124,7 @@ class RepairHomeServicePage extends HookConsumerWidget {
     );
   }
 
-  Widget _buildRepairHomeServiceItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm){
+  Widget _buildRepairHomeServiceItem(BuildContext context, WidgetRef ref, RepairServiceList item, vm){
     return SizedBox(
       width: double.infinity,
       // height: 170,
@@ -143,10 +149,11 @@ class RepairHomeServicePage extends HookConsumerWidget {
               Expanded(
                 child: RepairHomeServiceCard(
                     key: UniqueKey(),
-                    itemObj: item.cast<String, dynamic>(),
+                    itemEntity: item,
+                    cleanServiceType: item.category!.type,
                     onClickColleciotn: (dynamic collectionValue) async {
-                      Log.d("点击了喜欢按钮  --id:${item['id']}- $collectionValue");
-                      int id = item['id'];
+                      Log.d("点击了喜欢按钮  --id:${item.id}- $collectionValue");
+                      int id = item.id!;
                       return await vm.handlerClickCollection(id, collectionValue);
                     }
                 ),

+ 3 - 2
packages/cpt_services/lib/modules/services/repair_homeService/home_service_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/repair_service_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class RepairHomeServiceState {
@@ -12,7 +13,7 @@ class RepairHomeServiceState {
   String? sortBySelectedOption;
 
   List<Map<String, dynamic>> activeCateGoryList;
-  List<Map<String, dynamic>> list;
+  List<RepairServiceList> list;
 
 
   RepairHomeServiceState({
@@ -32,7 +33,7 @@ class RepairHomeServiceState {
     bool? isLiked,
     String? sortBySelectedOption,
     List<Map<String, dynamic>>? activeCateGoryList,
-    List<Map<String, dynamic>>? list,
+    List<RepairServiceList>? list,
   }) {
     return RepairHomeServiceState(
       loadingState: loadingState ?? this.loadingState,

+ 81 - 83
packages/cpt_services/lib/modules/services/repair_homeService/home_service_vm.dart

@@ -1,8 +1,6 @@
 
-import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
-import 'package:domain/entity/garage_sale_rent_entity.dart';
-import 'package:domain/entity/newsfeed_detail_entity.dart';
+import 'package:domain/entity/repair_service_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
@@ -16,6 +14,7 @@ import 'package:widgets/my_checkbox_group.dart';
 import 'package:widgets/picker/option_pick_util.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../../../constants_services.dart';
 import '../../../respository/services_respository.dart';
 import '../../../router/page/services_page_router.dart';
 import 'home_service_state.dart';
@@ -55,7 +54,7 @@ class RepairHomeServiceVm extends _$RepairHomeServiceVm {
   @override
   RepairHomeServiceState build(){
     // 引入数据仓库
-    // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     final state = initState();
     Log.d("--------------------------build---------------------");
 
@@ -88,8 +87,6 @@ class RepairHomeServiceVm extends _$RepairHomeServiceVm {
   // 下拉刷新
   Future onRefresh() async {
     // 当前pageView 页面正处于显示状态
-    Log.d("----forsale_vm-----onRefresh ");
-    // await Future.delayed(const Duration(seconds: 2));
     _page = 1;
     getListData();
   }
@@ -128,75 +125,75 @@ class RepairHomeServiceVm extends _$RepairHomeServiceVm {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 2,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'Repair Services',
-        'price': 30,
-        'unit': '/hr',
-        'liked': true,
-        'likes_count': 12,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 2,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'Repair Air Conditioning',
-        'price': 10,
-        'unit': '/unit',
-        'liked': false,
-        'likes_count': 10,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 2,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'Repair air Conditioner Services',
-        'price': 200,
-        'unit': '/hr',
-        'liked': true,
-        'likes_count': 1212,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
+    // List<Map<String, dynamic>> list = [
+    //   {
+    //     'id':1,
+    //     'service_type': 2,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'Repair Services',
+    //     'price': 30,
+    //     'unit': '/hr',
+    //     'liked': true,
+    //     'likes_count': 12,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    //   {
+    //     'id':2,
+    //     'service_type': 2,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'Repair Air Conditioning',
+    //     'price': 10,
+    //     'unit': '/unit',
+    //     'liked': false,
+    //     'likes_count': 10,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    //   {
+    //     'id':3,
+    //     'service_type': 2,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'Repair air Conditioner Services',
+    //     'price': 200,
+    //     'unit': '/hr',
+    //     'liked': true,
+    //     'likes_count': 1212,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    // ];
 
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
+    try {
+      //请求网络
+      Map<String, dynamic>  params = {
+        "sort": null, // 排序(desc=降序,asc=升序)
+        "sort_by": null,  // 排序(likes_count=点赞量,orders_count=下单量,clicks_count=点击量)
+        "category_id": _queryParams['category_id'],
+        "keyword": _queryParams['keyword'],
+        "page": _page,
+        "limit": _limit,
+      };
+      Log.d("请求参数------$params");
+      final result = await servicesRespositoryInstance.fetchRepairServiceList(params);
+      //校验成功失败
+      if (result.isSuccess) {
+        handlerResultList((result.data as RepairServiceEntity)?.list as List<RepairServiceList>?, isLoadMore ?? false);
+      } else {
+        String errorMessage = result.errorMsg!;
+        changeLoadingState(LoadState.State_Error, errorMessage);
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
 
     // 最后赋值
     _needShowPlaceholder = false;
 
   }
 
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
+  handlerResultData(bool isList, {List<RepairServiceList>? list, dynamic? data}){
     Future.delayed(const Duration(seconds: 1)).then((value) {
       if(isList){
         // list 数据模式
@@ -242,20 +239,20 @@ class RepairHomeServiceVm extends _$RepairHomeServiceVm {
     });
   }
 
-  void handlerResultList(List<GarageSaleRentList>? list, bool isLoadMore) {
+  void handlerResultList(List<RepairServiceList>? list, bool isLoadMore) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_page == 1) {
         //刷新的方式
         state.list!.clear();
-        state.list!.addAll(list.map((item) => item.toJson()).toList());
+        state.list!.addAll(list);
         refreshController.finishRefresh();
         //更新展示的状态
         changeLoadingState(LoadState.State_Success, null);
       } else {
         //加载更多
         final allList = state.list;
-        allList!.addAll(list.map((item) => item.toJson()).toList());
+        allList!.addAll(list);
         state = state.copyWith(list: allList);
         refreshController.finishLoad();
       }
@@ -409,22 +406,19 @@ class RepairHomeServiceVm extends _$RepairHomeServiceVm {
       //请求网络
       Map<String, dynamic>  params = {
         "id": id,
+        "type": 'inquiry', // 类型(paid=付费服务,inquiry=询价服务)
       };
       Log.d("请求参数------$params");
       final result = await servicesRespositoryInstance.fetchServiceLiked(params);
       //校验成功失败
       if (result.isSuccess) {
         // 修改 该id 的 liked 和 likes_count 字段
-        state.list!.forEach((Map<String, dynamic> element) {
-          GarageSaleRentList elementEntity = GarageSaleRentList.fromJson(element);
+        state.list!.forEach((RepairServiceList elementEntity) {
 
           if(elementEntity.id == id){
             elementEntity.liked = !elementEntity.liked!;
             elementEntity.likesCount = elementEntity.liked! ? (elementEntity.likesCount! + 1) : (elementEntity.likesCount! - 1);
           }
-
-          element = elementEntity.toJson();
-
         });
         return true;
       } else {
@@ -480,6 +474,7 @@ class RepairHomeServiceVm extends _$RepairHomeServiceVm {
       onPickerChanged: (_, index) {
         state = state.copyWith(sortBySelectedOption: state.sortByOptionsList?[index]);
         // 调用list 接口
+        directRefresh();
       },
     );
   }
@@ -502,15 +497,18 @@ class RepairHomeServiceVm extends _$RepairHomeServiceVm {
   }
 
   // 去详情页面
-  void handlerGotoDetail({BuildContext? context, required int id, int serviceTypeCode= 0 }){
-    Log.d("去详情页面  $id  $serviceTypeCode");
-    if(serviceTypeCode == 0 || serviceTypeCode == 1){
+  void handlerGotoDetail({BuildContext? context, required int id, required RepairServiceListCategory repairServiceListCategory }){
+
+    final cleanServiceType = repairServiceListCategory.name!;
+    Log.d("去详情页面:  $id  $cleanServiceType");
+    if(cleanServiceType == servicesConstants.servicesType['repairAirConditioner']!['code']){
       // clean service  跳转到 clean 详情页
-      appRouter.push(ServiceCleanDetailPageRoute(id: id, serviceTypeCode: serviceTypeCode));
-    }else if(serviceTypeCode == 2){
-      // repair service 跳转到 repair 详情页
-      appRouter.push(ServiceRepairDetailPageRoute(id: id, serviceTypeCode: serviceTypeCode));
+      appRouter.push(ServiceRepairDetailPageRoute(id: id, cleanServiceType: cleanServiceType));
+    }else {
+      // other service  跳转到 other 详情页
+      ToastEngine.show("${cleanServiceType} 类型的详情暂未开放");
     }
+
   }
 
 }

+ 1 - 1
packages/cpt_services/lib/modules/services/repair_homeService/home_service_vm.g.dart

@@ -7,7 +7,7 @@ part of 'home_service_vm.dart';
 // **************************************************************************
 
 String _$repairHomeServiceVmHash() =>
-    r'a3b0fad948ce8102784f895ebc097ee87ffe844d';
+    r'4006150cdf360bf7db04f0c4e591f14e32e38990';
 
 /// See also [RepairHomeServiceVm].
 @ProviderFor(RepairHomeServiceVm)

+ 105 - 124
packages/cpt_services/lib/modules/services/repair_homeService/service_card_item.dart

@@ -1,176 +1,159 @@
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/repair_service_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:shared/utils/color_utils.dart';
 import 'package:shared/utils/ext_dart.dart';
-import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 
-import '../../../constants_services.dart';
-
-
-// 'id':1,
-// 'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-// 'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-// 'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-// 'title': 'House Cleaning Services',
-// 'price': 66,
-// 'unit': '/hr',
-// 'liked': true,
-// 'likes_count': 1212,
-// 'company_name': 'HONG YE GROUP PTE LTD',
-
-
 class RepairHomeServiceCard extends StatelessWidget {
-  Map<String, dynamic>? serviceType = servicesConstants.servicesType['houseCleaning'];
-  Map<String, dynamic> itemObj;
+  String? cleanServiceType;
+  RepairServiceList itemEntity;
   double? cardHeight;
   final Function()? onTap;
   final Function(dynamic)? onClickColleciotn;
 
   RepairHomeServiceCard({
     Key? key,
-    this.serviceType,
-    required this.itemObj,
+    this.cleanServiceType,
+    required this.itemEntity,
     this.onTap,
     this.onClickColleciotn,
     double? cardHeight,
   }) : super(key: key) {
-    this.cardHeight ??= 170;
+    this.cardHeight ??= 180;
   }
 
   @override
   Widget build(BuildContext context) {
-    List? card_resources = itemObj.getValue<List>("resources", [])?? [];
+    List? card_resources = itemEntity.resources?? [];
+    int card_id = itemEntity.id?? 0;
     String card_img = card_resources.length>0? card_resources[0]:"";
-    String card_title = itemObj.getValue("title", "");
-    final unit = itemObj.getValue("unit", "");
+    String card_name = itemEntity.name?? "";
 
-    int card_price = itemObj.getValue("price", "");
-    String card_created_at = itemObj.getValue("created_at", "");
-    bool card_liked = itemObj.getValue("liked", false);
-    int card_likes_count = itemObj.getValue("likes_count", 0);
-    final company_name = itemObj.getValue("company_name", "");
-    return Column(
-      children: [
-        // 图片
-        Row(
-          mainAxisAlignment: MainAxisAlignment.center,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            Expanded(
-              child: ClipRRect(
-                borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8),),
-                child: MyLoadImage(
-                  card_img,
-                  width: 172.5,
-                  height: 80.5.ap,
-                  isCircle: false,
-                  fit: BoxFit.cover,
-                ),
-              ),
-            ),
-          ],
-        ),
-        // 标题
-        Padding(
-          padding: const EdgeInsets.only(left: 10, right: 10, top: 10,),
-          child: Row(
+    bool card_liked = itemEntity.liked??false;
+    int card_likes_count = itemEntity.likesCount?? 0;
+
+    final company_name = itemEntity.merchant?.name?? "";
+    return Container(
+      height: cardHeight!.ap,
+      child: Column(
+        children: [
+          // 图片
+          Row(
             mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               Expanded(
-                child: SizedBox(
-                  height: 30.ap,
-                  child: MyTextView(
-                    card_title,
-                    maxLines: 2,
-                    isTextEllipsis: true,
-                    textAlign: TextAlign.left,
-                    textColor: context.appColors.textBlack,
-                    fontSize: 15,
-                    isFontRegular: true,
+                child: ClipRRect(
+                  borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8),),
+                  child: MyLoadImage(
+                    card_img,
+                    width: 172.5.ap,
+                    height: 70.ap,
+                    isCircle: false,
+                    fit: BoxFit.fitWidth,
                   ),
                 ),
               ),
             ],
           ),
-        ),
-        // 价格 及 收藏
-        Padding(
-          padding: const EdgeInsets.only(left: 10, right: 10,top: 0, bottom: 0),
-          child: Row(
-            mainAxisAlignment: MainAxisAlignment.spaceAround,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              Expanded(
-                child: Row(
-                  mainAxisAlignment: MainAxisAlignment.start,
-                  crossAxisAlignment: CrossAxisAlignment.center,
-                  children: [
-                    MyTextView(
-                      'from',
-                      maxLines: 1,
-                      isTextEllipsis: true,
-                      textAlign: TextAlign.start,
-                      textColor: ColorUtils.string2Color('#666666'),
-                      fontSize: 11,
-                      isFontMedium: true,
-                    ),
-                    MyTextView(
-                      '\$$card_price',
-                      maxLines: 1,
-                      isTextEllipsis: true,
-                      textAlign: TextAlign.start,
-                      textColor: ColorUtils.string2Color('#4161D0'),
-                      fontSize: 15,
-                      isFontMedium: true,
-                      marginLeft: 2,
-                    ),
-                    MyTextView(
-                      '$unit',
-                      maxLines: 1,
+          // 标题
+          Padding(
+            padding:  EdgeInsets.only(left: 10.ap, right: 10.ap, top: 5.ap,),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: [
+                Expanded(
+                  child: SizedBox(
+                    height: 36.ap,
+                    child: MyTextView(
+                      card_name,
+                      maxLines: 2,
                       isTextEllipsis: true,
-                      textAlign: TextAlign.start,
-                      textColor: ColorUtils.string2Color('#666666'),
-                      fontSize: 11,
-                      isFontMedium: true,
+                      textAlign: TextAlign.left,
+                      textColor: context.appColors.textBlack,
+                      fontSize: 14,
+                      isFontRegular: true,
                     ),
-                  ],
+                  ),
                 ),
-              ),
-              // 动态的 收藏数
-              CollectionWidget(
-                collectionNum: card_likes_count,
-                isCollection: card_liked,
-                onClickColleciotn: onClickColleciotn,
-              ),
-            ],
+              ],
+            ),
           ),
-        ),
-        // 公司名称
-        Expanded(
-          child: Padding(
-            padding: const EdgeInsets.only(bottom: 5),
+          // 价格 及 收藏
+          Padding(
+            padding:  EdgeInsets.only(left: 10.ap, right: 10.ap,top: 5.ap, bottom: 0),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                Expanded(
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.start,
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      MyTextView(
+                        'get a quote',
+                        maxLines: 1,
+                        isTextEllipsis: true,
+                        textAlign: TextAlign.start,
+                        textColor: ColorUtils.string2Color('#666666'),
+                        fontSize: 11,
+                        isFontMedium: true,
+                      ),
+                      // MyTextView(
+                      //   '\$$card_price',
+                      //   maxLines: 1,
+                      //   isTextEllipsis: true,
+                      //   textAlign: TextAlign.start,
+                      //   textColor: ColorUtils.string2Color('#4161D0'),
+                      //   fontSize: 15,
+                      //   isFontMedium: true,
+                      //   marginLeft: 2,
+                      // ),
+                      // MyTextView(
+                      //   '$',
+                      //   maxLines: 1,
+                      //   isTextEllipsis: true,
+                      //   textAlign: TextAlign.start,
+                      //   textColor: ColorUtils.string2Color('#666666'),
+                      //   fontSize: 11,
+                      //   isFontMedium: true,
+                      // ),
+                    ],
+                  ),
+                ),
+                // 动态的 收藏数
+                CollectionWidget(
+                  collectionNum: card_likes_count,
+                  isCollection: card_liked,
+                  onClickColleciotn: onClickColleciotn,
+                ),
+              ],
+            ),
+          ),
+          // 公司名称
+          Expanded(
             child: MyTextView(
               company_name,
               maxLines: 1,
               isTextEllipsis: true,
               textAlign: TextAlign.start,
-              marginLeft: 13,
+              marginLeft: 10,
               fontSize: 11,
               textColor: ColorUtils.string2Color('#666666'),
               alignment: Alignment.centerLeft,
               isFontRegular: true,
             ),
-          ),
-        )
-      ],
+          )
+        ],
+      ),
     );
   }
 }
@@ -192,8 +175,6 @@ class CollectionWidget extends HookConsumerWidget {
     final collectionNumState = useState(collectionNum);
     final isCollectionState = useState(isCollection);
     return Container(
-        width: 60,
-        height: 30,
         alignment: Alignment.center,
         // decoration: BoxDecoration(
         //   color: ColorUtils.string2Color('#E5E5E5'),

+ 91 - 35
packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_page.dart

@@ -1,5 +1,7 @@
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/service_in_progress_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -46,7 +48,7 @@ class RepairInProgressPage extends HookConsumerWidget {
     final state = ref.watch(repairInProgressVmProvider);
     // final appConfigState = ref.watch(appConfigServiceProvider)
 
-    int serviceTypeCode = servicesConstants.servicesType['houseCleaning']?['code'];
+    String cleanServiceType = servicesConstants.servicesType['houseCleaning']?['code'];
     int serviceStatusCode = servicesConstants.servicesStatus['1']?['code'];
 
     useEffect(() {
@@ -61,7 +63,7 @@ class RepairInProgressPage extends HookConsumerWidget {
     return Scaffold(
       // appBar: MyAppBar.appBar(
       //   context,
-      //   "RepairInProgress",
+      //   "InProgress",
       //   backgroundColor: context.appColors.whiteBG,
       // ),
       backgroundColor: ColorUtils.string2Color("#F2F3F6"),
@@ -72,12 +74,12 @@ class RepairInProgressPage extends HookConsumerWidget {
             key: ValueKey('inProgress'),
             controller: vm.refreshController,
             // 上拉加载
-            onLoad: () async{
+            onLoad: () async {
               Log.d("----onLoad");
               vm.loadMore();
             },
             // 下拉刷新
-            onRefresh: () async{
+            onRefresh: () async {
               Log.d("----onRefresh");
               vm.onRefresh();
             },
@@ -87,24 +89,18 @@ class RepairInProgressPage extends HookConsumerWidget {
               errorRetry: () {
                 vm.retryRequest();
               },
-              successSliverWidget:[
+              successSliverWidget: [
                 SliverList(
                   delegate: SliverChildBuilderDelegate(
-                        (context, index) {
-                      return  _buildRepairInProgressItem(
-                          context,
-                          ref,
-                          state.list[index],
-                          vm,
-                          serviceTypeCode,
-                          serviceStatusCode
-                      ).onTap((){
-                        // vm.gotoCleanOrderDetailPage(
-                        //     context,
-                        //     state.list?[index]['id'],
-                        //     serviceTypeCode,
-                        //     serviceStatusCode
-                        // );
+                    (context, index) {
+                      return _buildRepairInProgressItem(
+                              context,
+                              ref,
+                              state.list[index],
+                              vm,
+                              cleanServiceType,
+                              serviceStatusCode)
+                          .onTap(() {
                       });
                     },
                     childCount: state.list.length,
@@ -112,12 +108,14 @@ class RepairInProgressPage extends HookConsumerWidget {
                 )
               ],
             ),
-          ).marginOnly(left: 15,right: 15,top: 0,bottom: 15)
-      ),
+          ).marginOnly(left: 15, right: 15, top: 0, bottom: 15)),
     );
   }
 
-  Widget _buildRepairInProgressItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm, int serviceTypeCode, int serviceStatusCode){
+  Widget _buildRepairInProgressItem(BuildContext context, WidgetRef ref, ServiceInProgressList item,
+      vm,
+      String cleanServiceType,
+      int serviceStatusCode) {
     return Container(
       margin: const EdgeInsets.only(top: 9),
       width: double.infinity,
@@ -132,18 +130,76 @@ class RepairInProgressPage extends HookConsumerWidget {
           ),
         ],
       ),
-      child: RepairStausCardItem(
-          key: UniqueKey(),
-          cardHeight: 120.0,
-          serviceId: item['id'],
-          serviceTypeCode: serviceTypeCode,
-          serviceStatusCode: serviceStatusCode,
-          itemObj: item.cast<String, dynamic>(),
-          onClickCard: (dynamic value) async {
-            // Log.d("点击了喜欢按钮  --id:${item['id']}- $collectionValue");
-            // int id = item['id'];
-            // return await vm.handlerClickCollection(id, collectionValue);
-          },
+      child: Container(
+        width: double.infinity,
+        height: 140,
+        child: Padding(
+          padding: const EdgeInsets.only(
+              left: 18.0, right: 18.0, top: 22.0, bottom: 22.0),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Expanded(
+                  child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  // 标题 和状态
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: [
+                      // 标题
+                      Expanded(
+                        child: MyTextView(
+                          item?.service?.name ?? "-",
+                          fontSize: 16,
+                          maxLines: 1,
+                          isFontBold: true,
+                          textAlign: TextAlign.left,
+                        ),
+                      ),
+                      // 状态
+                      MyTextView(
+                        item?.orderStatus ?? "-",
+                        fontSize: 14,
+                        maxLines: 1,
+                        isFontRegular: true,
+                        textAlign: TextAlign.left,
+                        textColor: context.appColors.textPrimary,
+                      ),
+                    ],
+                  ),
+                  // 公司名称
+                  MyTextView(
+                    item?.merchant?.name ?? "-",
+                    fontSize: 14,
+                    maxLines: 1,
+                    isFontRegular: true,
+                    textAlign: TextAlign.left,
+                    marginTop: 6,
+                  ),
+                  const SizedBox(
+                    height: 7.5,
+                  ),
+                  // visit time
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                    children: [
+                      MyTextView(
+                        item?.merchantNotes ?? "-",
+                        fontSize: 14,
+                        maxLines: 1,
+                        isFontRegular: true,
+                        textAlign: TextAlign.left,
+                        textColor: context.appColors.textDarkGray,
+                      ),
+               
+                    ],
+                  ),
+                ],
+              )),
+            ],
+          ),
+        ),
       ),
     );
   }

+ 5 - 3
packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_state.dart

@@ -1,5 +1,8 @@
+import 'package:domain/entity/garage_sale_history_entity.dart';
+import 'package:domain/entity/service_in_progress_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
+
 class RepairInProgressState {
   //页面 LoadView 状态的展示
   LoadState loadingState;
@@ -7,8 +10,7 @@ class RepairInProgressState {
 
   String? keyword;
   bool? isLiked;
-  List<Map<String, dynamic>> list;
-
+  List<ServiceInProgressList> list;
 
   RepairInProgressState({
     this.loadingState = LoadState.State_Loading,
@@ -25,7 +27,7 @@ class RepairInProgressState {
     bool? isLiked,
     Map<String, dynamic>? activeSortMap,
     List<Map<String, dynamic>>? activeCateGoryList,
-    List<Map<String, dynamic>>? list,
+    List<ServiceInProgressList>? list,
   }) {
     return RepairInProgressState(
       loadingState: loadingState ?? this.loadingState,

+ 40 - 165
packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_vm.dart

@@ -1,9 +1,11 @@
-
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
+import 'package:domain/entity/service_in_progress_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -18,10 +20,10 @@ import 'in_progress_state.dart';
 part 'in_progress_vm.g.dart';
 
 @riverpod
-class RepairInProgressVm extends _$RepairInProgressVm {
+class RepairInProgressVm extends _$RepairInProgressVm with DioCancelableMixin {
   late ServicesRespository servicesRespositoryInstance;
   bool _needShowPlaceholder = false; //是否展示LoadingView
-  int _page = 1;  // 当前页
+  int _page = 1; // 当前页
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
 
@@ -33,33 +35,28 @@ class RepairInProgressVm extends _$RepairInProgressVm {
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   RepairInProgressState initState() {
-    return RepairInProgressState(
-        list: []
-    );
+    return RepairInProgressState(list: []);
   }
 
   @override
-  RepairInProgressState build(){
+  RepairInProgressState build() {
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     // 引入数据仓库
     // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
     final state = initState();
     Log.d("--------------------------build---------------------");
-
+    registerCancellation();
     return state;
   }
 
-
   //刷新页面状态
   void changeLoadingState(LoadState loadState, String? errorMsg) {
-    state = state.copyWith(
-        loadingState: loadState,
-        errorMessage: errorMsg
-    );
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
   }
 
   // 初始化页面数据
@@ -75,7 +72,6 @@ class RepairInProgressVm extends _$RepairInProgressVm {
     getListData();
   }
 
-
   // 下拉刷新
   Future onRefresh() async {
     // 当前pageView 页面正处于显示状态
@@ -85,7 +81,6 @@ class RepairInProgressVm extends _$RepairInProgressVm {
     getListData();
   }
 
-
   // 手动进行刷新
   Future triggerRefresh() async {
     Log.d("trggerRefresh");
@@ -94,7 +89,7 @@ class RepairInProgressVm extends _$RepairInProgressVm {
 
   // 手动进行刷新
   Future directRefresh() async {
-    state = state.copyWith(list:[]);
+    state = state.copyWith(list: []);
     // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
     // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
     refreshController.callRefresh();
@@ -104,7 +99,6 @@ class RepairInProgressVm extends _$RepairInProgressVm {
     getListData();
   }
 
-
   // 重试请求
   Future retryRequest() async {
     _page = 1;
@@ -112,195 +106,76 @@ class RepairInProgressVm extends _$RepairInProgressVm {
     getListData();
   }
 
-
   // 获取list 列表数据
   Future getListData<T>({bool? isLoadMore}) async {
     if (_needShowPlaceholder) {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 0,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
+    // 获取列表
+    var listResult =
+        await servicesRespositoryInstance.fetchRepairServiceOrderList(
+      status: 0,
+      curPage: _page,
+      cancelToken: cancelToken,
+    );
 
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.list);
+    } else {
+      changeLoadingState(LoadState.State_Error, listResult.errorMsg);
+    }
 
     // 最后赋值
     _needShowPlaceholder = false;
-
   }
 
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
-    Future.delayed(const Duration(seconds: 1)).then((value) {
-      if(isList){
-        // list 数据模式
-        if(list != null && list.isNotEmpty){
-          if(_page == 1){
-            state.list.clear();
-            state.list!.addAll(list);
-            refreshController.finishRefresh();
-            changeLoadingState(LoadState.State_Success, null);
-          }else {
-            final allList = state.list;
-            allList!.addAll(list);
-            state = state.copyWith(list: allList);
-            refreshController.finishLoad();
-          }
-        }else {
-          if(_page == 1){
-            state.list.clear();
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishRefresh();
-          }else {
-            refreshController.finishLoad(IndicatorResult.noMore);
-          }
-        }
-      }else {
-        // 单个数据模式
-        if(data!=null){
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Success, null);
-        }else {
-          if(_page == 1){
-            refreshController.finishRefresh();
-          }else{
-            refreshController.finishLoad();
-          }
-          changeLoadingState(LoadState.State_Empty, null);
-        }
-      }
-    });
-  }
-
-  void handlerResultList(List<GarageSaleRentList>? list, bool isLoadMore) {
+  // 处理数据与展示的逻辑
+  void handleList(List<ServiceInProgressList>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_page == 1) {
         //刷新的方式
-        state.list!.clear();
-        state.list!.addAll(list.map((item) => item.toJson()).toList());
+        state = state.copyWith(list: list);
         refreshController.finishRefresh();
+
         //更新展示的状态
         changeLoadingState(LoadState.State_Success, null);
       } else {
         //加载更多
-        final allList = state.list;
-        allList!.addAll(list.map((item) => item.toJson()).toList());
-        state = state.copyWith(list: allList);
+        state.list
+            .addAll(List<ServiceInProgressList>.from(state.list)..addAll(list));
         refreshController.finishLoad();
       }
     } else {
       if (_page == 1) {
         //展示无数据的布局
-        state.list!.clear();
+        state = state.copyWith(list: []);
         changeLoadingState(LoadState.State_Empty, null);
         refreshController.finishRefresh();
       } else {
         //展示加载完成,没有更多数据了
-        if (_page == 1) {
-          //展示无数据的布局
-          state.list!.clear();
-          changeLoadingState(LoadState.State_Empty, null);
-          refreshController.finishRefresh();
-        } else {
-          //展示加载完成,没有更多数据了
-          if(state.list!.length == 0){
-            changeLoadingState(LoadState.State_Empty, null);
-            refreshController.finishLoad();
-          }else {
-            if(_needShowPlaceholder){
-              changeLoadingState(LoadState.State_Success, null);
-            }
-          }
-          //更新展示的状态
-          refreshController.finishLoad(IndicatorResult.noMore);
-        }
+        refreshController.finishLoad(IndicatorResult.noMore);
       }
     }
   }
 
   // 设置当前的 _queryParams
-  setCurrentQueryParams(Map<String, dynamic> params){
+  setCurrentQueryParams(Map<String, dynamic> params) {
     _queryParams.addAll(params);
   }
 
   // 获取当前的 _queryParams
-  Map<String, dynamic> getCurrentQueryParams(String? key){
-    if(key!=null && key!.isNotEmpty){
+  Map<String, dynamic> getCurrentQueryParams(String? key) {
+    if (key != null && key!.isNotEmpty) {
       return _queryParams[key];
     }
     return _queryParams;
   }
 
   //  去详情页面
-  gotoCleanOrderDetailPage(BuildContext context, int id, int serviceTypeCode, int serviesStatusCode){
-    CleanOrderDetailPage.startInstance(id: id, serviceTypeCode: serviceTypeCode, serviesStatusCode: serviesStatusCode);
+  gotoCleanOrderDetailPage(BuildContext context, int id, String cleanServiceType, int serviesStatusCode){
+    CleanOrderDetailPage.startInstance(id: id, cleanServiceType: cleanServiceType, serviesStatusCode: serviesStatusCode);
   }
-}
+}

+ 1 - 1
packages/cpt_services/lib/modules/services/repair_inProgress/in_progress_vm.g.dart

@@ -7,7 +7,7 @@ part of 'in_progress_vm.dart';
 // **************************************************************************
 
 String _$repairInProgressVmHash() =>
-    r'968f6c5d90c2f5e7b510e0430617bacbff3062d4';
+    r'a35790c3e5285086a1bf7792c6c7d3c704e4bfa9';
 
 /// See also [RepairInProgressVm].
 @ProviderFor(RepairInProgressVm)

+ 152 - 142
packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_page.dart

@@ -1,8 +1,7 @@
 import 'package:cpt_services/components/chooseAirConditionContent.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
-import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
-import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
@@ -22,6 +21,7 @@ import 'package:widgets/my_like_button.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
+import 'package:shared/utils/richText_utils.dart';
 
 import '../../../components/chooseHouseCleanContent.dart';
 import '../../../components/user_evaluate_card_item.dart';
@@ -33,15 +33,17 @@ import '../../../router/page/services_page_router.dart';
 @RoutePage()
 class ServiceCleanDetailPage extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
+  bool liked = false;
+  int likesCount = 0;
 
-  const ServiceCleanDetailPage({Key? key,@PathParam('id') required this.id, @PathParam('serviceTypeCode') required this.serviceTypeCode}) : super(key: key);
+  ServiceCleanDetailPage({Key? key,@PathParam('id') required this.id, @PathParam('cleanServiceType') required this.cleanServiceType, required this.liked, required this.likesCount}) : super(key: key);
   // 启动当前页面
-  static void startInstance({BuildContext? context, int? id, int? serviceTypeCode = 0}) {
+  static void startInstance({BuildContext? context, int? id, String? cleanServiceType, bool? liked, int? likesCount}) {
     if (context != null) {
-      context.router.push(ServiceCleanDetailPageRoute(id: id!, serviceTypeCode: serviceTypeCode!));
+      context.router.push(ServiceCleanDetailPageRoute(id: id!, cleanServiceType: cleanServiceType!, liked: liked!, likesCount: likesCount = 0));
     } else {
-      appRouter.push(ServiceCleanDetailPageRoute(id: id!, serviceTypeCode: serviceTypeCode!));
+      appRouter.push(ServiceCleanDetailPageRoute(id: id!, cleanServiceType: cleanServiceType!, liked: liked!, likesCount: likesCount = 0));
     }
   }
 
@@ -53,11 +55,12 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
     final String pageTitle = 'Clean Details';
     GlobalKey _likeButtonKey = GlobalKey<MyLikeButtonState>();
 
-    Map<String, dynamic>? detailInfo = state.datas?? null;
-    String title =  detailInfo?['title']?? '';
+    PaidServiceDetailEntity? detailInfo = state.datas?? null;
+
 
     useEffect((){
-      vm.setInitPageData(id: id, serviceTypeCode: serviceTypeCode,);
+      vm.setInitPageData(id: id, cleanServiceType: cleanServiceType, liked: liked, likesCount: likesCount);
+
       // 组件挂载时执行 - 执行接口请求
       Future.microtask(() => vm.initPageData());
       return () {
@@ -126,16 +129,19 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
     );
   }
 
-  Widget _buildContentBox(BuildContext context, WidgetRef ref, Map<String, dynamic> detailInfo) {
-    List<String> resources = detailInfo?['resources'].cast<String>()??[];
-    String title =  detailInfo?['title']??'';
-    double score = detailInfo?['score']?? 5.0;
+  Widget _buildContentBox(BuildContext context, WidgetRef ref, PaidServiceDetailEntity detailInfo) {
+    final String title = detailInfo?.name??'';
+    List<String> resources = detailInfo!.resources?.cast<String>()??[];
+    double evaluationsAvgScore = (detailInfo?.evaluationsAvgScore?? 5.0).toDouble();
+    final hilightStr = detailInfo?.highlight??'';
+    final description =  RichtextUtils.getHandleResult(detailInfo?.description??'');
 
-    final hilightStr = detailInfo?['hilightStr']??'On call, at the fastest 30 minutes to come to the door';
+    final String merchantName = detailInfo?.merchant?.name??'';
 
-
-    String description = detailInfo?['description']??'';
+    List<dynamic> evaluations = detailInfo?.evaluations??[];
+    bool hasEvaluations = evaluations.isNotEmpty;
     CarouselSliderController buttonCarouselController = CarouselSliderController();
+
     return Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         children: [
@@ -186,9 +192,11 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                       hilightStr,
                       fontSize: 13,
                       isFontRegular: true,
+                      isTextEllipsis: true,
+                      maxLines: 2,
                       textColor: context.appColors.textDarkGray,
                       marginLeft: 5,
-                    ):const SizedBox.shrink(),
+                    ).expanded():const SizedBox.shrink(),
                   ],
                 ),
               ),
@@ -203,7 +211,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
                         MyTextView(
-                          "House Cleaning Services",
+                          '$title',
                           textColor: context.appColors.textBlack,
                           fontSize: 18,
                           isFontBold: true,
@@ -214,7 +222,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                           crossAxisAlignment: CrossAxisAlignment.center,
                           children: [
                             AnimatedRatingStars(
-                              initialRating: score,
+                              initialRating: evaluationsAvgScore,
                               onChanged: (rating) {
                               },
                               readOnly: true,
@@ -229,7 +237,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                               animationCurve: Curves.easeInOut,
                             ),
                             MyTextView(
-                              "${score}",
+                              "${evaluationsAvgScore}",
                               textColor: context.appColors.textBlack,
                               fontSize: 16,
                               isFontMedium: true,
@@ -238,7 +246,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                           ],
                         ),
                         MyTextView(
-                          "HONG YE GROUP PTE LTD",
+                          '$merchantName',
                           textColor: context.appColors.textDarkGray999,
                           fontSize: 12,
                           isFontRegular: true,
@@ -253,127 +261,127 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
               //  室内清洁选择服务 或者 空调清洁选择空调选项
               _buildSelectHouseCleanOrAirConditioner(context, ref, detailInfo),
               // user Reviews
-              _buildUserReviews(context, ref, detailInfo),
-              // 介绍图
-              Padding(
-                padding: const EdgeInsets.only(left: 16, right: 16, top: 16),
-                child: Column(
-                  children: List.generate(6, (index) {
-                    // 创建一个映射来关联字符串和资源
-                    final Map<String, String> assetMap = {
-                      'serviceDetail01': Assets.serviceDetail01,
-                      'serviceDetail02': Assets.serviceDetail02,
-                      'serviceDetail03': Assets.serviceDetail03,
-                      'serviceDetail04': Assets.serviceDetail04,
-                      'serviceDetail05': Assets.serviceDetail05,
-                      'serviceDetail06': Assets.serviceDetail06,
-                    };
-                    String curDetailStr = 'serviceDetail0${(index + 1)}';
-                    return MyAssetImage(
-                      assetMap[curDetailStr]!,
-                      width: SizeConfig().screenWidth,
-                      fit: BoxFit.cover,
-                    );
-                  }).toList(),
-                )
-              ),
+              hasEvaluations? _buildUserReviews(context, ref, detailInfo): const SizedBox.shrink(),
+              // description
+              Html(data: description),
             ],
           ),
         ]
     );
   }
 
-  Widget _buildUserReviews(BuildContext context, WidgetRef ref, Map<String, dynamic> detailInfo) {
+  // user Reviews
+  Widget _buildUserReviews(BuildContext context, WidgetRef ref, PaidServiceDetailEntity detailInfo) {
     final vm = ref.read(serviceCleanDetailVmProvider.notifier);
     final state = ref.watch(serviceCleanDetailVmProvider);
     int reviewScoreMaxNum = 3;
     double reviewScoreItemCardHeight = 275;
+    double reviewScoreItemCardWidth = 300;
+    List<PaidServiceDetailEvaluations>? evaluations = detailInfo?.evaluations;
 
+    if (evaluations == null || evaluations.isEmpty) {
+      return const SizedBox.shrink();
+    }else {
+      if(evaluations.length >= reviewScoreMaxNum){
+        reviewScoreMaxNum = reviewScoreMaxNum;
+        reviewScoreItemCardWidth = 300;
+      }else{
+        reviewScoreMaxNum = evaluations.length;
+        reviewScoreItemCardWidth = (context.screenSize.width! - 32) / reviewScoreMaxNum;
+      }
 
-    Map<String, dynamic> item = {
-      'name': "User Sandy",
-      'avatar': "",
-      'score': 5.0,
-      'card_created_at': "14 Oct 2024 15:00",
-      'content': "This aunt is very careful because I haven't been home for three or four months. The house is",
-      'resources': [],
-    };
-    return Container(
-      width: context.screenSize.width! * reviewScoreMaxNum,
-      height: reviewScoreItemCardHeight,
-      child: Column(
-        children: [
-          Container(
-            padding: const EdgeInsets.only(left: 16, right: 16, top: 16,bottom: 0),
-            color: context.appColors.whiteBG,
-            child: Row(
-              mainAxisAlignment: MainAxisAlignment.spaceBetween,
-              crossAxisAlignment: CrossAxisAlignment.center,
-              children: [
-                MyTextView(
-                  "User Reviews",
-                  textColor: context.appColors.textBlack,
-                  fontSize: 17,
-                  isFontBold: true,
-                ),
-                Wrap(
-                  crossAxisAlignment: WrapCrossAlignment.center,
-                  spacing: 5,
-                  children: [
-                    MyTextView(
-                      "All",
-                      textColor: context.appColors.textDarkGray999,
-                      fontSize: 14,
-                      isFontRegular: true,
-                    ),
-                    MyAssetImage(
-                      Assets.serviceArrowRightIcon,
-                      width: 12.5,
-                      height: 10,
-                      color: context.appColors.textPrimary,
-                    ),
-                  ]
-                ),
-              ],
-            ).onTap((){
-              vm.gotoUserReviewsPage(context, id, serviceTypeCode);
-            }),
-          ),
-          Expanded(
-            child: SingleChildScrollView(
-              scrollDirection: Axis.horizontal,
-              physics: const BouncingScrollPhysics(),
-              child: Container(
-                color: context.appColors.whiteBG,
-                padding: const EdgeInsets.only(left: 16, right: 16, top: 0,bottom: 16),
-                child: Row(
-                  children: List.generate(reviewScoreMaxNum, (index){
-                    return _buildserviceEvaluateListItem(context, ref, item, vm, 300);
-                  }),
+      Log.d("evaluations 数量:${evaluations.length}");
+      Log.d("evaluation 最大展示数量:$reviewScoreMaxNum");
+
+      Map<String, dynamic> item = {
+        'name': "User Sandy",
+        'avatar': "",
+        'score': 5.0,
+        'card_created_at': "14 Oct 2024 15:00",
+        'content': "This aunt is very careful because I haven't been home for three or four months. The house is",
+        'resources': [],
+      };
+
+      return Container(
+        width: context.screenSize.width! * reviewScoreMaxNum,
+        height: reviewScoreItemCardHeight,
+        child: Column(
+          children: [
+            Container(
+              padding: const EdgeInsets.only(left: 16, right: 16, top: 16,bottom: 0),
+              color: context.appColors.whiteBG,
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  MyTextView(
+                    "User Reviews",
+                    textColor: context.appColors.textBlack,
+                    fontSize: 17,
+                    isFontBold: true,
+                  ),
+                  Wrap(
+                      crossAxisAlignment: WrapCrossAlignment.center,
+                      spacing: 5,
+                      children: [
+                        MyTextView(
+                          "All",
+                          textColor: context.appColors.textDarkGray999,
+                          fontSize: 14,
+                          isFontRegular: true,
+                        ),
+                        MyAssetImage(
+                          Assets.serviceArrowRightIcon,
+                          width: 12.5,
+                          height: 10,
+                          color: context.appColors.textPrimary,
+                        ),
+                      ]
+                  ),
+                ],
+              ).onTap((){
+                vm.gotoUserReviewsPage(context, id, cleanServiceType);
+              }),
+            ),
+            // evaluate list
+            Expanded(
+              child: SingleChildScrollView(
+                scrollDirection: Axis.horizontal,
+                physics: const BouncingScrollPhysics(),
+                child: Container(
+                  color: context.appColors.whiteBG,
+                  padding: const EdgeInsets.only(left: 16, right: 16, top: 0,bottom: 16),
+                  child: Row(
+                    children: List.generate(reviewScoreMaxNum, (index){
+                      PaidServiceDetailEvaluations item = evaluations[index];
+                      return _buildserviceEvaluateListItem(context, ref, item, vm, reviewScoreItemCardWidth);
+                    }),
+                  ),
                 ),
               ),
-            ),
-          )
-        ],
-      ),
-    );
+            )
+          ],
+        ),
+      );
+    }
   }
 
-  Widget _buildserviceEvaluateListItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm, double cardWidth){
-    String card_name = item?['name']?? "User Sandy";
-    String card_avatar = item?['avatar']?? "";
-    double card_score = item?['score']?? 5.0;
-    String card_created_at = item?['card_created_at']?? "14 Oct 2024 15:00";
-    String card_content = item.getValue("content", "This aunt is very careful because I haven't been home for three or four months. The house is");
-    List? card_resources =  ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'];
+  Widget _buildserviceEvaluateListItem(BuildContext context, WidgetRef ref, PaidServiceDetailEvaluations item, vm, double cardWidth){
+    int? card_id = item.id?? null;
+    double card_score = (item.score?? 5.0).toDouble();
+    String card_comment = item.comment??"";
+    List<String>? card_resources = (item.resources??[]).cast<String>();
+    String card_created_at = item.createdAt??"";
+    PaidServiceDetailEvaluationsAccount? account=item.account??null;
+    String card_name = account?.name??"";
+    String card_avatar = account?.avatar??"";
 
     // Log.d("card_resources  $card_resources");
     return LayoutBuilder(
       builder: (context, constraints) {
         final maxWidth = constraints.maxWidth;
         final maxHeight = constraints.maxHeight;
-        // Log.d("8933 $maxWidth  $maxHeight");
-        Log.d("55555 $cardWidth");
+        Log.d("maxWidth  $maxWidth");
         return Container(
           margin: const EdgeInsets.only(top: 10),
           width: cardWidth,
@@ -400,7 +408,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                   avator: card_avatar,
                   score: card_score,
                   time: card_created_at,
-                  content: card_content,
+                  content: card_comment,
                   contentTextMaxLines: 2,
                   imageUrls: card_resources,
                 ),
@@ -412,10 +420,11 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
     );
   }
 
-  Widget _buildSelectHouseCleanOrAirConditioner(BuildContext context, WidgetRef ref, Map<String, dynamic> detailInfo) {
-    if(serviceTypeCode == servicesConstants.servicesType['houseCleaning']!['code']){
+  Widget _buildSelectHouseCleanOrAirConditioner(BuildContext context, WidgetRef ref, PaidServiceDetailEntity detailInfo) {
+    if(cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code']){
+      List<PaidServiceDetailProducts>? houseCleanList = detailInfo?.products??[];
       // 室内清洁
-      return Column(
+      return houseCleanList.isNotEmpty? Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         children: [
           Padding(
@@ -441,15 +450,12 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
               ],
             ),
           ),
-          ChooseHouseCleanContent(id: id, serviceTypeCode: serviceTypeCode,),
+          ChooseHouseCleanContent(id: id, cleanServiceType: cleanServiceType, products: houseCleanList),
         ],
-      );
-    }else if(serviceTypeCode == servicesConstants.servicesType['airConditioner']!['code']){
-      // 空调清洁
-      // return ChooseAirConditionContent(id: id, serviceTypeCode: serviceTypeCode);
-    }else if(serviceTypeCode == servicesConstants.servicesType['repaire']!['code']){
-      // 维修
-      return SizedBox.shrink();
+      ): SizedBox.shrink();
+    }else if(cleanServiceType == servicesConstants.servicesType['airConditioner']!['code']){
+      // 空调清洁  页面中没有直接展示 选择数量的  直接在弹窗中选择了
+      // return ChooseAirConditionContent(id: id, cleanServiceType: cleanServiceType);
     }
     return SizedBox.shrink();
   }
@@ -459,14 +465,16 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
       WidgetRef ref,
       likeButtonKey,
       {
-        required Map<String, dynamic> detailInfo,
+        required PaidServiceDetailEntity detailInfo,
       }
       ) {
     final vm = ref.read(serviceCleanDetailVmProvider.notifier);
 
-    int? likes_count =  detailInfo['likesCount']??0;
-    bool isLiked = detailInfo['isLiked']??false;
-    final contact = detailInfo['contact']??'+8613563656325';
+    PaidServiceDetailMerchant? merchant = detailInfo?.merchant??null;
+    final contact = merchant?.contactPhone??"";
+
+    int? likes_count = likesCount?? 0;
+    bool isLiked = liked?? false;
 
     final _likes_count = useState<int>(likes_count!);
     final _isLiked = useState<bool>(isLiked);
@@ -498,13 +506,13 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                         isCustomIcon: true,
                         customIconUnActiveAssets: Assets.communityCollection,
                         customIconActiveAssets: Assets.communityLikeActive,
-                        customIconWidth: 19,
+                        customIconWidth: 20,
                         customIconHeight: 18,
                         onLike: () async {
                           Log.d('点击了like button');
-                          int id = detailInfo!['id'] as int;
-                          final isSuccess = await vm.handlerClickCollection(context, id, true);
-                          if(isSuccess!=null && isSuccess){
+                          int id = detailInfo.id!;
+                          final isSuccess = await vm.handlerClickLikedBtn(context, id, true);
+                          if(isSuccess!=null && isSuccess == true){
                             // 成功
                             if(_isLiked.value){
                               Log.d("取消点赞");
@@ -526,6 +534,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                         marginLeft: 5,
                         marginRight: 15,
                         onClick: (){
+                          // 点击了like button
                           final state = likeButtonKey.currentState;
                           state?.triggerTap();
                         },
@@ -542,6 +551,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                       width: 21.5,
                       height: 18,
                     ).onTap((){
+                      // 点击了打电话
                       vm.handlerClickMobile(context, contact);
                     }),
                     const SizedBox(width: 15,),
@@ -563,7 +573,7 @@ class ServiceCleanDetailPage extends HookConsumerWidget {
                 ),
               ),
             ).onTap((){
-              vm.handlerClickBookNow(context, id: id , serviceTypeCode: serviceTypeCode);
+              vm.handlerClickBookNow(context, id: id , cleanServiceType: cleanServiceType,);
             }),
           ),
         ],

+ 12 - 5
packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_state.dart

@@ -1,4 +1,5 @@
 import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class ServiceCleanDetailState {
@@ -12,22 +13,29 @@ class ServiceCleanDetailState {
 
   final int? id;
   final String? type;
-  double? totalPrice;
-  Map<String, dynamic>? datas;
+
+  double? get urgentPrice => datas?.urgentPrice?.toDouble(); // 加急价格
+  double? get holidayPrice => datas?.holidayPrice?.toDouble(); // 节假日价格
+  double? get nightPrice => datas?.nightPrice?.toDouble(); // 夜间价格
+
+  String?  get servicePeriodStart => datas?.servicePeriodStart; // 服务开始时间
+  String? get servicePeriodEnd => datas?.servicePeriodEnd; // 服务结束时间
+  int? get servicePeriodInterval => datas?.servicePeriodInterval; // 服务时间间隔
+
+  PaidServiceDetailEntity? datas;
 
   ServiceCleanDetailState({
     this.loadingState = LoadState.State_Loading,
     this.errorMessage,
     this.dialogLoadingState = LoadState.State_Loading,
     this.dialogErrorMessage,
-    this.totalPrice = 0,
     this.id,
     this.type,
     required this.datas,
   });
 
   ServiceCleanDetailState copyWith({
-    Map<String, dynamic>? datas,
+    PaidServiceDetailEntity? datas,
     LoadState? loadingState,
     String? errorMessage,
     LoadState? dialogLoadingState,
@@ -41,7 +49,6 @@ class ServiceCleanDetailState {
       errorMessage: errorMessage ?? this.errorMessage,
       dialogLoadingState: dialogLoadingState ?? this.dialogLoadingState,
       dialogErrorMessage: dialogErrorMessage ?? this.dialogErrorMessage,
-      totalPrice: totalPrice?? this.totalPrice,
       id: id ?? this.id,
       type: type ?? this.type,
       datas: datas?? this.datas,

+ 107 - 93
packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_vm.dart

@@ -1,17 +1,21 @@
 
 import 'dart:async';
 
+import 'package:cpt_services/components/chooseAirConditionContent_vm.dart';
 import 'package:cpt_services/components/chooseVisitTimeContent.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_basic/basic_export.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/permission/permission_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/ext_dart.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/load_state_layout.dart';
@@ -22,6 +26,7 @@ import 'package:widgets/dialog/dialog_content_wrap.dart';
 import '../../../components/chooseAirConditionContent.dart';
 import '../../../components/chooseAirConditionTitle.dart';
 import '../../../components/chooseHouseCleanContent.dart';
+import '../../../components/chooseHouseCleanContent_vm.dart';
 import '../../../components/chooseHouseCleanTitle.dart';
 import '../../../constants_services.dart';
 import '../../../respository/services_respository.dart';
@@ -41,17 +46,16 @@ final _chooseAirCleanDialogGlobalKey = GlobalKey<DialogContentWrapState>();
 class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
   late ServicesRespository serviceRespositoryInstance;
 
-  int _detailId = 0;
-  int _detailServiceTypeCode = 0;
-
   bool _needShowPlaceholder = false; //是否展示LoadingView
   int _page = 1;  // 当前页
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
 
-  int _totalnum = 130;
+  int? _detailId;
+  String? _cleanServiceType;
+  bool? _liked;
+  num? _likesCount;
 
-  int totalnum = 50;
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
@@ -84,14 +88,16 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
     );
   }
 
-  setInitPageData({required int id, required int serviceTypeCode}){
+  setInitPageData({required int id, required String cleanServiceType, bool? liked, num? likesCount}){
+    Log.d("service_clean_detail 设置 initpagedata ---  id:$id cleanServiceType:$cleanServiceType");
     _detailId = id;
-    _detailServiceTypeCode = serviceTypeCode;
+    _cleanServiceType = cleanServiceType!;
+    _liked = liked;
+    _likesCount = likesCount;
   }
   
   // 初始化页面数据
   initPageData() {
-    Log.d("----for_sale_vm-----initPageData   ${state.loadingState}");
     onRefresh();
   }
 
@@ -141,42 +147,13 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-
-    // await Future.delayed(const Duration(milliseconds: 1500));
-    //
-    // final Map<String, dynamic> detailData = {
-    //   'id':1,
-    //   'goods_img': 'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-    //   'title': 'Electronic keyboard',
-    //   'price': '\$66',
-    //   'description':'Electronic keyboards for sale. I will attend together with the booth.\$10 per day usage Negotiable usage',
-    //   'isCollection': true,
-    //   'contactType': 'WhatsApp',
-    //   'contactInfo': '+1 123456789',
-    //   'collection_num': 12,
-    //   'publisher': 'William Jefferson',
-    //   'publisher_avatar': 'https://img1.baidu.com/it/u=3890726495,1572750319&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
-    //   'publisher_time': 'June 17,2024 at 7:23 PM'
-    // };
-
-    // state = state.copyWith(datas: GarageSaleRentDetailEntity(
-    // ));
-    //
-    // changeLoadingState(LoadState.State_Success, null);
-    //
-    // refreshController.finishRefresh();
-    //
-    // // 最后赋值
-    // _needShowPlaceholder = false;
-
-
     try {
       Map<String, dynamic> params = {
         "id": _detailId,
       };
       final result = await serviceRespositoryInstance.fetchPaidServiceCleanDetailInfo(params);
       if(result.isSuccess){
-        state = state.copyWith(datas: result.data as Map<String, dynamic>);
+        state = state.copyWith(datas: result.data as PaidServiceDetailEntity);
         changeLoadingState(LoadState.State_Success, null);
         refreshController.finishRefresh();
       } else {
@@ -194,20 +171,22 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
   }
 
 
-  // 点击了底部的收藏按钮
-  Future<bool?> handlerClickCollection(BuildContext? context, int id, bool isCollection) async{
-    // var vm;
-    // if(_detailServiceTypeCode == "forSale"){
-    //   // vm = ref.read(forsaleVmProvider.notifier);
-    // }else if(_detailServiceTypeCode == "forRent"){
-    //   vm = ref.read(forrentVmProvider.notifier);
-    // }
-    // try {
-    //   final isSuccess = await vm.handlerClickCollection(id, isCollection);
-    //   return isSuccess;
-    // }catch(e){
-    //
-    // }
+  // 点击了底部的点赞按钮
+  Future<bool?> handlerClickLikedBtn(BuildContext? context, int id, bool isLiked) async{
+    try {
+      Map<String, dynamic> params = {
+        "id": id,
+        "type": 'paid', // 类型(paid=付费服务,inquiry=询价服务)
+      };
+      final result = await serviceRespositoryInstance.fetchServiceLiked(params);
+      if(result.isSuccess){
+        return true;
+      }else{
+        return false;
+      }
+    }catch(e){
+      return false;
+    }
   }
 
   // 判断是whatsapp 还是 mobile  (通过 contact: whatsapp:+8617671757687)
@@ -232,8 +211,8 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
 
   // 点击 whatsapp
   handlerClickWhatsapp(BuildContext? context,String contactType, String title, int price){
-    // 假设你有一个获取 WhatsApp 号码的方法
-    String whatsappNumber = getContactNumber(contactType); // 你需要实现这个方法
+    // 获取 WhatsApp 号码
+    String whatsappNumber = getContactNumber(contactType); 
     // 构建消息并进行编码
     String message = Uri.encodeComponent("Hello, I am interested in your listing: $title for $price.");
     // 打开WhatsApp
@@ -252,39 +231,54 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
   }
 
   // 点击 电话
-  handlerClickMobile(BuildContext? context,String contact){
-    String mobileNumber = getContactNumber(contact);
-    // 拨打电话
-    makePhoneCall(mobileNumber);
+  handlerClickMobile(BuildContext? context,String mobileNumber){
+    if(mobileNumber.isEmpty){
+      ToastEngine.show("No phone number found");
+      return;
+    }else {
+      // 拨打电话
+      makePhoneCall(mobileNumber);
+    }
   }
 
   // 拨打电话
   Future<void> makePhoneCall(String phoneNumber) async {
-    final Uri launchUri = Uri(
-      scheme: 'tel',
-      path: phoneNumber,
-    );
-
-    if (await canLaunchUrl(launchUri)) {
-      await launchUrl(launchUri);
-    } else {
-      ToastEngine.show("Could not launch $launchUri");
-      throw 'Could not launch $launchUri';
-    }
+    PermissionEngine().requestCallPhonePermission(() async {
+      final Uri launchUri = Uri(
+        scheme: 'tel',
+        path: phoneNumber,
+      );
+
+      if (await canLaunchUrl(launchUri)) {
+        await launchUrl(launchUri);
+      } else {
+        ToastEngine.show("Could not launch $launchUri");
+        throw 'Could not launch $launchUri';
+      }
+    });
   }
 
   // 点击了 Book Now 按钮
-  handlerClickBookNow(BuildContext context, {int? id, int? serviceTypeCode} ){
+  handlerClickBookNow(BuildContext context, {int? id, String? cleanServiceType} ){
     final detailId = id ?? _detailId;
-    final detailServiceTypeCode = serviceTypeCode ?? _detailServiceTypeCode;   // 0 房屋清洁  1 空调清洁  2 维修
-    if(detailServiceTypeCode == servicesConstants.servicesType['houseCleaning']!['code']){
+    final cleanType = cleanServiceType ?? _cleanServiceType;   // 0 房屋清洁  1 空调清洁  2 维修
+    if(cleanType == servicesConstants.servicesType['houseCleaning']!['code']){
       // 房屋清洁
-      handlerShowChooseCleanConditionerDialog(context);
-    }else if(detailServiceTypeCode == servicesConstants.servicesType['airConditioner']!['code']){
+      final chooseHouseCleanContentVm= ref.read(chooseHouseCleanContentVmProvider.notifier);
+      if(!chooseHouseCleanContentVm.state.hasCheckdService){
+        // 详情页面中没有选择 服务项目 此时需要弹出底部弹框供选择
+        // handlerShowChooseCleanConditionerDialog(context);
+        ToastEngine.show("Please select service");
+      }else {
+        // 详情页面中已经选择 服务项目 此时直接 跳转到 订单页面
+        // 跳转到 订单确认页面
+        gotoServiceOrderConfirmPage();
+      }
+    }else if(cleanType == servicesConstants.servicesType['airConditioner']!['code']){
       // 空调清洁
       // 弹出选择 空调型号和数量的弹框
       handlerShowChooseAirConditionerDialog(context);
-    }else if(detailServiceTypeCode == servicesConstants.servicesType['repaire']!['code']){
+    }else if(cleanType == servicesConstants.servicesType['repaire']!['code']){
       // 维修
     }
   }
@@ -292,10 +286,11 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
   // 显示选择 房屋清洁的弹框
   handlerShowChooseCleanConditionerDialog(BuildContext context) async{
     // 定时器
-    LoadState dialogState = LoadState.State_Loading;
+    LoadState dialogState = LoadState.State_Success;
     DialogEngine.show(
         tag: "chooseHouseClean",
         position: DialogPosition.bottom,
+        clickMaskDismiss:false,
         widget: DialogContentWrap(
           key: _chooseHouseCleanDialogGlobalKey,
           loadingState: dialogState,
@@ -311,6 +306,7 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
           // bottomBtnSectionPadding: EdgeInsets.only(left: 20, right: 20, bottom: 20,top: 20),
           yesBtnBg: context.appColors.redDefault,
           noBtnBg: context.appColors.grayBgE9,
+          closeIconColor: context.appColors.textPrimary,
           confirmTxt: "Confirm Selection",
           cancelTxt: "Cancel",
           // yesBtnTextStyle: TextStyle(
@@ -323,6 +319,7 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
           //   fontSize: 17,
           //   fontWeight: FontWeight.w400
           // ),
+          closeAction: (){},
           confirmAction: chooseHouseCleanConfirmFn,
           cancelAction: chooseHouseCleanCancelFn,
           titleBuilder: (context) {
@@ -333,11 +330,12 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
           },
         )
     );
-
-    await Future.delayed(Duration(milliseconds: 1000));
-
-    _chooseHouseCleanDialogGlobalKey.currentState?.changeDialogLoadingState(LoadState.State_Success);    
   }
+  // 改变 _chooseHouseCleanDialogGlobalKey 的Loading状态
+  changeHouseCleanDialogLoadingState(LoadState state){
+    _chooseHouseCleanDialogGlobalKey.currentState?.changeDialogLoadingState(LoadState.State_Success);
+  }
+
   // 显示 选择空调型号和数量的弹框
   handlerShowChooseAirConditionerDialog(BuildContext context, ) async{
     // 定时器
@@ -345,10 +343,11 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
     DialogEngine.show(
       tag: "chooseAirConditionClean",
       position: DialogPosition.bottom,
+        clickMaskDismiss:false ,
       widget: DialogContentWrap(
         key: _chooseAirCleanDialogGlobalKey,
         loadingState: dialogState,
-        maxHeight: 315.5,
+        maxHeight: 450.0,
         dialogWidth: context.screenSize.width,
         isShowConfirmBtn: true,
         isShowCancelBtn: false,
@@ -358,6 +357,7 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
         topLeftRadius: 20.0,
         topRightRadius: 20.0,
         // bottomBtnSectionPadding: EdgeInsets.only(left: 20, right: 20, bottom: 20,top: 20),
+        closeIconColor: context.appColors.textPrimary,
         yesBtnBg: context.appColors.redDefault,
         noBtnBg: context.appColors.grayBgE9,
         confirmTxt: "Confirm Selection",
@@ -372,6 +372,8 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
         //   fontSize: 17,
         //   fontWeight: FontWeight.w400
         // ),
+        isConfirmAutoClose: false,
+        closeAction: () {},
         confirmAction: chooseAirConditionConfirmFn,
         cancelAction: chooseAirConditionCancelFn,
         titleBuilder: (context) {
@@ -392,8 +394,13 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
     Log.d("点击了确定");
     DialogEngine.dismiss(tag: "chooseHouseClean");
     // 跳转到 订单确认页面
-    // appRouter.push(ServiceOrderConfirmPageRoute(id: _detailId, serviceTypeCode: _detailServiceTypeCode));
-    ServiceOrderConfirmPage.startInstance(id: _detailId, serviceTypeCode: _detailServiceTypeCode);
+    gotoServiceOrderConfirmPage();
+  }
+
+  // 去订单确认页面
+  gotoServiceOrderConfirmPage(){
+    // appRouter.push(ServiceOrderConfirmPageRoute(id: _detailId, cleanServiceType: _cleanServiceType));
+    ServiceOrderConfirmPage.startInstance(id: _detailId!, cleanServiceType: _cleanServiceType!);
   }
 
   chooseHouseCleanCancelFn(){
@@ -404,10 +411,16 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
 
   chooseAirConditionConfirmFn(){
     Log.d("点击了确定");
-    DialogEngine.dismiss(tag: "chooseAirConditionClean");
-    // 跳转到 订单确认页面
-    // appRouter.push(ServiceOrderConfirmPageRoute(id: _detailId, serviceTypeCode: _detailServiceTypeCode));
-    ServiceOrderConfirmPage.startInstance(id: _detailId, serviceTypeCode: _detailServiceTypeCode);
+    final chooseAirCleanContentVm= ref.watch(chooseAirConditionContentVmProvider.notifier);
+    if(chooseAirCleanContentVm?.state.hasCheckdService??false){
+      // 跳转到 订单确认页面
+      // appRouter.push(ServiceOrderConfirmPageRoute(id: _detailId, cleanServiceType: _cleanServiceType));
+      ServiceOrderConfirmPage.startInstance(id: _detailId!, cleanServiceType: _cleanServiceType!);
+      DialogEngine.dismiss(tag: "chooseAirConditionClean");
+    }else {
+      // 一个数量也没选 则英文提示
+      ToastEngine.show("Please Select Service");
+    }
   }
 
   chooseAirConditionCancelFn(){
@@ -416,23 +429,24 @@ class ServiceCleanDetailVm extends _$ServiceCleanDetailVm {
 
   
   Widget buildChooseHouseCleanTitle(BuildContext context){
-    return ChooseHouseCleanTitle(id: 0, serviceTypeCode: 0);
+    return ChooseHouseCleanTitle(id: _detailId!, cleanServiceType: _cleanServiceType!);
   }
 
   Widget buildChooseHouseCleanContent(BuildContext context){
-    return ChooseHouseCleanContent(id: 0, serviceTypeCode: 0,);
+    Log.d("打开弹框 products: ${state.datas!.products!}");
+    return ChooseHouseCleanContent(id: _detailId!, cleanServiceType: _cleanServiceType!, products: state.datas!.products!,);
   }
 
   Widget buildChooseAirConditionTitle(BuildContext context){
-    return ChooseAirConditionTitle(id: 0, serviceTypeCode: 0);
+    return ChooseAirConditionTitle(id: _detailId!, cleanServiceType: _cleanServiceType!);
   }
   
   Widget buildChooseAirConditionContent(BuildContext context){
-    return ChooseAirConditionContent(id: 0, serviceTypeCode: 0,);
+    return ChooseAirConditionContent(id: _detailId!, cleanServiceType: _cleanServiceType!,products: state.datas!.products!);
   }
 
   // 去 评价列表页面
-  gotoUserReviewsPage(BuildContext context, int id, int serviceTypeCode){
-    ServiceEvaluateListPage.startInstance(id:id, serviceTypeCode: serviceTypeCode);
+  gotoUserReviewsPage(BuildContext context, int id, String cleanServiceType){
+    ServiceEvaluateListPage.startInstance(id:id, cleanServiceType: cleanServiceType);
   }
 }

+ 1 - 1
packages/cpt_services/lib/modules/services/service_clean_detail/service_clean_detail_vm.g.dart

@@ -7,7 +7,7 @@ part of 'service_clean_detail_vm.dart';
 // **************************************************************************
 
 String _$serviceCleanDetailVmHash() =>
-    r'77e8421e0ac469ea7f2131499d6c15634efb6faa';
+    r'd1d4a37356ed36d9d30fd6ee92c9fa2a2b8b71c6';
 
 /// See also [ServiceCleanDetailVm].
 @ProviderFor(ServiceCleanDetailVm)

+ 7 - 6
packages/cpt_services/lib/modules/services/service_evaluate_create/service_evaluate_create_page.dart

@@ -31,19 +31,19 @@ import 'service_evaluate_create_vm.dart';
 @RoutePage()
 class ServiceEvaluateCreatePage extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
   const ServiceEvaluateCreatePage({
     Key? key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
   }) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context, required int id, required int serviceTypeCode}) {
+  static void startInstance({BuildContext? context, required int id, required String cleanServiceType}) {
     if (context != null) {
-      context.router.push(ServiceEvaluateCreatePageRoute(id: id, serviceTypeCode: serviceTypeCode));
+      context.router.push(ServiceEvaluateCreatePageRoute(id: id, cleanServiceType: cleanServiceType));
     } else {
-      appRouter.push(ServiceEvaluateCreatePageRoute(id:id, serviceTypeCode: serviceTypeCode));
+      appRouter.push(ServiceEvaluateCreatePageRoute(id:id, cleanServiceType: cleanServiceType));
     }
   }
 
@@ -58,7 +58,7 @@ class ServiceEvaluateCreatePage extends HookConsumerWidget {
 
     useEffect(() {
       // 组件挂载时执行 - 执行接口请求
-      Future.microtask(() => vm.initPageData());
+      Future.microtask(() => vm.initPageData(id: id));
       return () {
         // 组件卸载时执行
       };
@@ -302,6 +302,7 @@ class ServiceEvaluateCreatePage extends HookConsumerWidget {
             expands: true,
             onChanged: (text) {
               // 当文本改变时,更新字符数量
+              vm.setNotes(context, text);
               noteCount.value = text.length;
             },
           ),

+ 36 - 8
packages/cpt_services/lib/modules/services/service_evaluate_create/service_evaluate_create_vm.dart

@@ -58,6 +58,7 @@ class ServiceEvaluateCreateVm extends _$ServiceEvaluateCreateVm {
   @override
   ServiceEvaluateCreateState build() {
     // 初始化状态
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     ServiceEvaluateCreateState state = initState();
 
     // 当前渲染完成后执行一次
@@ -85,7 +86,8 @@ class ServiceEvaluateCreateVm extends _$ServiceEvaluateCreateVm {
     _serviceTypeCode = serviceTypeCode;
   }
   // 初始化页面数据
-  initPageData() {
+  initPageData({int? id,}) {
+    _id = id;
     // changeLoadingState(LoadState.State_Success, null);
 
     // onRefresh();
@@ -468,12 +470,38 @@ class ServiceEvaluateCreateVm extends _$ServiceEvaluateCreateVm {
   setScore(BuildContext context, double score){
     state = state.copyWith(score: score);
   }
-
-  handlerEvaluateSubmit(BuildContext context,){
-    Log.d("handlerEvaluateSubmit");
-    context.appRouter.pushAndPopUntil(const EvaluateCreateSuccessPageRoute(), predicate: (Route<dynamic> route) {       // 根据具体条件返回 true 或 false
-      // Log.d("888 ${route.settings}");
-      return route.settings.name != 'ServiceEvaluateCreatePageRoute';
-    });
+  setNotes(BuildContext context, String notes){
+    state = state.copyWith(notes: notes);
+  }
+  handlerEvaluateSubmit(BuildContext context,) async {
+     try {
+      //请求网络
+      Map<String, dynamic>  params = {
+        "order_id": _id,
+        "score": state.score??5.0,
+        "comment":state.notes,
+        "resources": state.imgList,
+      };
+      Log.d("请求参数------$params");
+      final result = await servicesRespositoryInstance.fetchPublishEvaluation(params);
+      //校验成功失败
+      if (result.isSuccess) {
+        Log.d("handlerEvaluateSubmit");
+        context.appRouter
+            .pushAndPopUntil(const EvaluateCreateSuccessPageRoute(),
+                predicate: (Route<dynamic> route) {
+          // 根据具体条件返回 true 或 false
+          // Log.d("888 ${route.settings}");
+          return route.settings.name != 'ServiceEvaluateCreatePageRoute';
+        });
+      } else {
+        String errorMessage = result.errorMsg!;
+        changeLoadingState(LoadState.State_Error, errorMessage);
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+    
   }
 }

+ 1 - 1
packages/cpt_services/lib/modules/services/service_evaluate_create/service_evaluate_create_vm.g.dart

@@ -7,7 +7,7 @@ part of 'service_evaluate_create_vm.dart';
 // **************************************************************************
 
 String _$serviceEvaluateCreateVmHash() =>
-    r'e3dcc7851836ad14ed970e2f4d5cc0482c71efcb';
+    r'4076871c4476ccd72aa607ef8e83e3925d25a789';
 
 /// See also [ServiceEvaluateCreateVm].
 @ProviderFor(ServiceEvaluateCreateVm)

+ 13 - 14
packages/cpt_services/lib/modules/services/service_evaluate_list/service_evaluate_list_page.dart

@@ -1,5 +1,4 @@
-import 'package:cs_resources/generated/assets.dart';
-import 'package:domain/entity/garage_sale_rent_entity.dart';
+
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -29,19 +28,19 @@ import '../../../components/status_card_item.dart';
 @RoutePage()
 class ServiceEvaluateListPage extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
   const ServiceEvaluateListPage({
     Key? key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
   }) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context, required int id, required int serviceTypeCode}) {
+  static void startInstance({BuildContext? context, required int id, required String cleanServiceType}) {
     if (context != null) {
-      context.router.push( ServiceEvaluateListPageRoute(id:id, serviceTypeCode:serviceTypeCode));
+      context.router.push( ServiceEvaluateListPageRoute(id:id, cleanServiceType:cleanServiceType));
     } else {
-      appRouter.push(ServiceEvaluateListPageRoute(id:id, serviceTypeCode:serviceTypeCode));
+      appRouter.push(ServiceEvaluateListPageRoute(id:id, cleanServiceType:cleanServiceType));
     }
   }
 
@@ -55,7 +54,7 @@ class ServiceEvaluateListPage extends HookConsumerWidget {
 
     useEffect(() {
       // 组件挂载时执行 - 执行接口请求
-      Future.microtask(() => vm.initPageData());
+      Future.microtask(() => vm.initPageData(id: id));
       return () {
         // 组件卸载时执行
         Log.d("serviceEvaluateList_page 组件卸载时执行");
@@ -108,11 +107,11 @@ class ServiceEvaluateListPage extends HookConsumerWidget {
   }
 
   Widget _buildserviceEvaluateListItem(BuildContext context, WidgetRef ref, Map<String, dynamic> item, vm){
-    String card_name = item?['name']?? "User Sandy";
-    String card_avatar = item?['avatar']?? "";
-    double card_score = item?['score']?? 5.0;
-    String card_created_at = item?['card_created_at']?? "14 Oct 2024 15:00";
-    String card_content = item.getValue("content", "This aunt is very careful because I haven't been home for three or four months. The house is");
+    String card_name = item?['account']['name']?? "User Sandy";
+    String card_avatar = item?['account']['avatar']?? "";
+    int card_score = item?['score']?? 5.0;
+    String card_created_at = item?['created_at']?? "14 Oct 2024 15:00";
+    String card_content = item?['comment']??"";
     List? card_resources = item.getValue<List>("resources", [])?? [];
     return Container(
       margin: const EdgeInsets.only(top: 10),
@@ -134,7 +133,7 @@ class ServiceEvaluateListPage extends HookConsumerWidget {
           key: UniqueKey(),
           name: card_name,
           avator: card_avatar,
-          score: card_score,
+          score: card_score.toDouble(),
           time: card_created_at,
           content: card_content,
           contentTextMaxLines: 9999,

+ 111 - 125
packages/cpt_services/lib/modules/services/service_evaluate_list/service_evaluate_list_vm.dart

@@ -1,7 +1,7 @@
-
 import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
+import 'package:domain/entity/service_evaluate_list_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -20,50 +20,40 @@ part 'service_evaluate_list_vm.g.dart';
 class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
   late ServicesRespository servicesRespositoryInstance;
   bool _needShowPlaceholder = false; //是否展示LoadingView
-  int _page = 1;  // 当前页
+  int _page = 1; // 当前页
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
-
-  Map<String, dynamic> _queryParams = {
-    'category_id': null,
-    'keyword': null,
-    'is_liked': null,
-  };
+  int serviceId = 0;
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   ServiceEvaluateListState initState() {
-    return ServiceEvaluateListState(
-        list: []
-    );
+    return ServiceEvaluateListState(list: []);
   }
 
   @override
-  ServiceEvaluateListState build(){
+  ServiceEvaluateListState build() {
     // 引入数据仓库
-    // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
     final state = initState();
     Log.d("--------------------------build---------------------");
 
     return state;
   }
 
-
   //刷新页面状态
   void changeLoadingState(LoadState loadState, String? errorMsg) {
-    state = state.copyWith(
-        loadingState: loadState,
-        errorMessage: errorMsg
-    );
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
   }
 
   // 初始化页面数据
-  initPageData() {
+  initPageData({int? id}) {
     Log.d("----home_service_vm-----initPageData   ${state.loadingState}");
+    serviceId = id!;
     onRefresh();
   }
 
@@ -74,7 +64,6 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
     getListData();
   }
 
-
   // 下拉刷新
   Future onRefresh() async {
     // 当前pageView 页面正处于显示状态
@@ -84,7 +73,6 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
     getListData();
   }
 
-
   // 手动进行刷新
   Future triggerRefresh() async {
     Log.d("trggerRefresh");
@@ -93,7 +81,7 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
 
   // 手动进行刷新
   Future directRefresh() async {
-    state = state.copyWith(list:[]);
+    state = state.copyWith(list: []);
     // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
     // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
     refreshController.callRefresh();
@@ -103,7 +91,6 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
     getListData();
   }
 
-
   // 重试请求
   Future retryRequest() async {
     _page = 1;
@@ -111,125 +98,123 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
     getListData();
   }
 
-
   // 获取list 列表数据
   Future getListData<T>({bool? isLoadMore}) async {
     if (_needShowPlaceholder) {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 2,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 2,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 3,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
+    // List<Map<String, dynamic>> list = [
+    //   {
+    //     'id':1,
+    //     'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500','https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'House Cleaning Services',
+    //     'duration': 'Daily cleaning for 2 hours',
+    //     'totalPrice': 66,
+    //     'visit_time': '14 0ct 2024 15:00',
+    //     'order_time': '13 0ct 2024 12:00',
+    //     'status_text': 'In Progress',
+    //     'status_code': 2,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    //   {
+    //     'id':2,
+    //     'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'House Cleaning Services',
+    //     'duration': 'Daily cleaning for 2 hours',
+    //     'totalPrice': 66,
+    //     'visit_time': '14 0ct 2024 15:00',
+    //     'order_time': '13 0ct 2024 12:00',
+    //     'status_text': 'In Progress',
+    //     'status_code': 2,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    //   {
+    //     'id':3,
+    //     'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
+    //     'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
+    //     'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
+    //     'title': 'House Cleaning Services',
+    //     'duration': 'Daily cleaning for 2 hours',
+    //     'totalPrice': 66,
+    //     'visit_time': '14 0ct 2024 15:00',
+    //     'order_time': '13 0ct 2024 12:00',
+    //     'status_text': 'In Progress',
+    //     'status_code': 3,
+    //     'company_name': 'HONG YE GROUP PTE LTD',
+    //   },
+    // ];
+    // handlerResultData(true, list:list);
 
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
+    try {
+      //请求网络
+      Map<String, dynamic> params = {
+        "service_id":serviceId,
+        "page": _page,
+        "limit": _limit,
+      };
+      Log.d("请求参数------$params");
+      final result =
+          await servicesRespositoryInstance.fetchEvaluationDataList(params);
+      //校验成功失败
+      if (result.isSuccess) {
+        handlerResultList((result.data as ServiceEvaluateListEntity).list, isLoadMore ?? false);
+      } else {
+        String errorMessage = result.errorMsg!;
+        changeLoadingState(LoadState.State_Error, errorMessage);
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
 
     // 最后赋值
     _needShowPlaceholder = false;
-
   }
 
-  handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
+  handlerResultData(bool isList,
+      {List<Map<String, dynamic>>? list, dynamic? data}) {
     Future.delayed(const Duration(seconds: 1)).then((value) {
-      if(isList){
+      if (isList) {
         // list 数据模式
-        if(list != null && list.isNotEmpty){
-          if(_page == 1){
+        if (list != null && list.isNotEmpty) {
+          if (_page == 1) {
             state.list.clear();
             state.list!.addAll(list);
             refreshController.finishRefresh();
             changeLoadingState(LoadState.State_Success, null);
-          }else {
+          } else {
             final allList = state.list;
             allList!.addAll(list);
             state = state.copyWith(list: allList);
             refreshController.finishLoad();
           }
-        }else {
-          if(_page == 1){
+        } else {
+          if (_page == 1) {
             state.list.clear();
             changeLoadingState(LoadState.State_Empty, null);
             refreshController.finishRefresh();
-          }else {
+          } else {
             refreshController.finishLoad(IndicatorResult.noMore);
           }
         }
-      }else {
+      } else {
         // 单个数据模式
-        if(data!=null){
-          if(_page == 1){
+        if (data != null) {
+          if (_page == 1) {
             refreshController.finishRefresh();
-          }else{
+          } else {
             refreshController.finishLoad();
           }
           changeLoadingState(LoadState.State_Success, null);
-        }else {
-          if(_page == 1){
+        } else {
+          if (_page == 1) {
             refreshController.finishRefresh();
-          }else{
+          } else {
             refreshController.finishLoad();
           }
           changeLoadingState(LoadState.State_Empty, null);
@@ -238,7 +223,7 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
     });
   }
 
-  void handlerResultList(List<GarageSaleRentList>? list, bool isLoadMore) {
+  void handlerResultList(List<ServiceEvaluateListList>? list, bool isLoadMore) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_page == 1) {
@@ -270,11 +255,11 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
           refreshController.finishRefresh();
         } else {
           //展示加载完成,没有更多数据了
-          if(state.list!.length == 0){
+          if (state.list!.length == 0) {
             changeLoadingState(LoadState.State_Empty, null);
             refreshController.finishLoad();
-          }else {
-            if(_needShowPlaceholder){
+          } else {
+            if (_needShowPlaceholder) {
               changeLoadingState(LoadState.State_Success, null);
             }
           }
@@ -286,21 +271,22 @@ class ServiceEvaluateListVm extends _$ServiceEvaluateListVm {
   }
 
   // 设置当前的 _queryParams
-  setCurrentQueryParams(Map<String, dynamic> params){
-    _queryParams.addAll(params);
-  }
+  // setCurrentQueryParams(Map<String, dynamic> params) {
+  //   _queryParams.addAll(params);
+  // }
 
-  // 获取当前的 _queryParams
-  Map<String, dynamic> getCurrentQueryParams(String? key){
-    if(key!=null && key!.isNotEmpty){
-      return _queryParams[key];
-    }
-    return _queryParams;
-  }
+  // // 获取当前的 _queryParams
+  // Map<String, dynamic> getCurrentQueryParams(String? key) {
+  //   if (key != null && key!.isNotEmpty) {
+  //     return _queryParams[key];
+  //   }
+  //   return _queryParams;
+  // }
 
   // 去详情页面
-  void handlerGotoDetail({BuildContext? context, required int id, String type='forSale'}){
+  void handlerGotoDetail(
+      {BuildContext? context, required int id, String type = 'forSale'}) {
     Log.d("去详情页面");
     // appRouter.push(GaragesaleDetailPageRoute(id: id, type: 'forSale'));
   }
-}
+}

+ 1 - 1
packages/cpt_services/lib/modules/services/service_evaluate_list/service_evaluate_list_vm.g.dart

@@ -7,7 +7,7 @@ part of 'service_evaluate_list_vm.dart';
 // **************************************************************************
 
 String _$serviceEvaluateListVmHash() =>
-    r'993c979ca4e734163a320a8369185748208344b6';
+    r'ca4e3fa5efaf52a15ee7505769b887eba5f465b4';
 
 /// See also [ServiceEvaluateListVm].
 @ProviderFor(ServiceEvaluateListVm)

+ 188 - 98
packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_page.dart

@@ -1,14 +1,19 @@
 import 'package:cpt_services/components/chooseAirConditionContent.dart';
 import 'package:cpt_services/components/chooseAirConditionContent_vm.dart';
+import 'package:cpt_services/components/chooseHouseCleanContent_vm.dart';
+import 'package:cpt_services/modules/services/service_clean_detail/service_clean_detail_vm.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
+import 'package:domain/entity/user_me_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:plugin_basic/provider/app_config/app_config_service.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
 import 'package:router/componentRouter/component_service_manager.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/color_utils.dart';
@@ -24,7 +29,9 @@ import 'package:widgets/my_appbar.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../../../components/chooseAirConditionContent_state.dart';
 import '../../../components/chooseHouseCleanContent.dart';
+import '../../../components/chooseHouseCleanContent_state.dart';
 import '../../../components/chooseVisitTimeContent_vm.dart';
 import '../../../constants_services.dart';
 import '../../../router/page/services_page_router.dart';
@@ -35,19 +42,19 @@ import '../../../components/status_card_item.dart';
 @RoutePage()
 class ServiceOrderConfirmPage extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String cleanServiceType;
   const ServiceOrderConfirmPage({
     Key? key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
   }) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context, required int id, required int serviceTypeCode}) {
+  static void startInstance({BuildContext? context, required int id, required String cleanServiceType}) {
     if (context != null) {
-      context.router.push(ServiceOrderConfirmPageRoute(id: id, serviceTypeCode: serviceTypeCode));
+      context.router.push(ServiceOrderConfirmPageRoute(id: id, cleanServiceType: cleanServiceType));
     } else {
-      appRouter.push(ServiceOrderConfirmPageRoute(id:id, serviceTypeCode: serviceTypeCode));
+      appRouter.push(ServiceOrderConfirmPageRoute(id:id, cleanServiceType: cleanServiceType));
     }
   }
 
@@ -58,12 +65,10 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
     final state = ref.watch(serviceOrderConfirmVmProvider);
     // final appConfigState = ref.watch(appConfigServiceProvider)
 
-    final totalPrice = ref.watch(serviceOrderConfirmVmProvider.select((state) => state.totalPrice));
-
     useEffect(() {
-      vm.setInitPageData(id: id, serviceTypeCode: serviceTypeCode);
+      vm.setInitPageData(id: id, cleanServiceType: cleanServiceType);
       // 组件挂载时执行 - 执行接口请求
-      Future.microtask(() => vm.initPageData());
+      Future.microtask(() => vm.initPageData(context));
       return () {
         // 组件卸载时执行
       };
@@ -98,7 +103,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
                     // 底部联系信息
                     Visibility(
                       visible: state.loadingState == LoadState.State_Success,
-                      child: state.datas !=null ? _buildBottomSection(state, vm,ref, context, id, serviceTypeCode, totalPrice): Container(),
+                      child: state.datas !=null ? _buildBottomSection(state, vm,ref, context, id, cleanServiceType): Container(),
                     )
 
                   ],
@@ -128,7 +133,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
             width: double.infinity,
             margin: const EdgeInsets.only(left: 0, right: 0, top: 5, bottom: 0),
             padding: const EdgeInsets.only(left: 10, right: 10, top: 18.5, bottom: 18.5),
-            child: _buildOrderProfile(state, vm, context),
+            child: _buildOrderProfile(state, vm, context, ref),
           ),
           // 订单 服务项目
           Container(
@@ -136,7 +141,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
             width: double.infinity,
             margin: const EdgeInsets.only(left: 0, right: 0, top: 5, bottom: 0),
             padding: const EdgeInsets.only(left: 10, right: 10, top: 18.5, bottom: 18.5),
-            child: _buildOrderService(state, vm, context),
+            child: _buildOrderService(state, vm, context, ref),
           ),
           // 订单 上门时间
           Container(
@@ -144,7 +149,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
             width: double.infinity,
             margin: const EdgeInsets.only(left: 0, right: 0, top: 5, bottom: 0),
             padding: const EdgeInsets.only(left: 10, right: 10, top: 18.5, bottom: 18.5),
-            child: _buildOrderVisitTime(state, vm, context).onTap((){
+            child: _buildOrderVisitTime(state, vm, context, ref).onTap((){
               vm.handlerClickVisitTime(context);
             }),
           ),
@@ -179,7 +184,10 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
   }
 
   Widget _buildOrderScore(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context) {
-    double score = 5.0;
+    PaidServiceDetailEntity? detailInfo = state.datas??null;
+    final String title = detailInfo?.name??'';
+    double evaluationsAvgScore = (detailInfo?.evaluationsAvgScore?? 5.0).toDouble();
+    final String merchantName = detailInfo?.merchant?.name??'';
     //  评分
     return Column(
       children: [
@@ -190,7 +198,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
             crossAxisAlignment: CrossAxisAlignment.start,
             children: [
               MyTextView(
-                "House Cleaning Services",
+                "$title",
                 textColor: context.appColors.textBlack,
                 fontSize: 18,
                 isFontBold: true,
@@ -201,7 +209,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
                 crossAxisAlignment: CrossAxisAlignment.center,
                 children: [
                   AnimatedRatingStars(
-                    initialRating: score,
+                    initialRating: evaluationsAvgScore,
                     onChanged: (rating) {
                     },
                     readOnly: true,
@@ -216,7 +224,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
                     animationCurve: Curves.easeInOut,
                   ),
                   MyTextView(
-                    "${score}",
+                    "${evaluationsAvgScore}",
                     textColor: context.appColors.textBlack,
                     fontSize: 16,
                     isFontMedium: true,
@@ -225,7 +233,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
                 ],
               ),
               MyTextView(
-                "HONG YE GROUP PTE LTD",
+                "$merchantName",
                 textColor: context.appColors.textDarkGray999,
                 fontSize: 12,
                 isFontRegular: true,
@@ -239,7 +247,12 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
     );
   }
 
-  Widget _buildOrderProfile(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context) {
+  Widget _buildOrderProfile(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context, WidgetRef ref) {
+    final userInfoState = UserConfigService.getState(ref: ref);
+    UserMeEntity? user = userInfoState.user;
+    String userUnit = user?.defaultUnit?.unit??'';
+    String userName = '${user?.information?.firstName??''}${user?.information?.lastName??''}';
+    String userPhone = '${user?.information?.phone}'??'';
     return Column(
       children: [
         Row(
@@ -258,7 +271,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
                 MyTextView(
-                  '705 Qiming Huijin Building',
+                  '$userUnit',
                   fontSize: 17,
                   isFontBold: true,
                   textColor: context.appColors.textBlack,
@@ -268,13 +281,13 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
                   mainAxisAlignment: MainAxisAlignment.start,
                   children: [
                     MyTextView(
-                      'Sundy',
+                      '$userName',
                       fontSize: 14,
                       textColor: context.appColors.textDarkGray999,
                       isFontRegular: true,
                     ),
                     MyTextView(
-                      '+6588991122',
+                      '$userPhone',
                       fontSize: 14,
                       textColor: context.appColors.textDarkGray999,
                       isFontRegular: true,
@@ -290,7 +303,11 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
     );
   }
 
-  Widget _buildOrderService(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context) {
+  Widget _buildOrderService(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context, WidgetRef ref) {
+    final result = vm.getCurrentService();
+    List<HouseCleanContentItem> houseCleanCheckedServiceList = result["houseCleanCheckedServiceList"] as List<HouseCleanContentItem>;
+    List<AirConditionContentItem> airCleancheckedServiceList = result["airCleancheckedServiceList"] as List<AirConditionContentItem>;
+
     return Column(
       children: [
         Row(
@@ -314,93 +331,163 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
             ),
           ],
         ),
-        if (serviceTypeCode == servicesConstants.servicesType['houseCleaning']!['code'])
-          // 室内清理
-          _buildCleanContent(state, vm, context)
-        else if (serviceTypeCode == servicesConstants.servicesType['airConditioner']!['code'])
-          // 空调清理
-          _buildCleanContent(state, vm, context)
+        if (cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code'])
+        // 室内清理
+          _buildHouseCleanContent(state, vm, context, ref, houseCleanCheckedServiceList)
+        else if (cleanServiceType == servicesConstants.servicesType['airConditioner']!['code'])
+        // 空调清理
+          _buildAirCleanCleanContent(state, vm, context, ref, airCleancheckedServiceList)
         else
           const SizedBox.shrink(),
       ],
     );
   }
 
-  Widget _buildCleanContent(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context) {
-    final title = 'House Cleaning Services';
-    final areaSizeRange = '1 Bedroom';
-    final num =  1;
-    final price = 0;
-    bool isChecked = false;
-    bool disabled = true;
-    final isDisable = useState<bool>(disabled);
-
-    return Container(
-      padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
-      margin: EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 0),
-      color: ColorUtils.string2Color('#F8F8F8'),
-      child: Column(
-        children: [
-          Row(
-            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              Expanded(
-                child: Column(
-                  crossAxisAlignment: CrossAxisAlignment.start,
+  Widget _buildHouseCleanContent(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context, WidgetRef ref, List<HouseCleanContentItem> checkedServiceList) {
+    if(checkedServiceList.isNotEmpty){
+      return Column(
+        children: List.generate(checkedServiceList.length, (index){
+          HouseCleanContentItem currentItem = checkedServiceList[index] as HouseCleanContentItem;
+          final title = currentItem.name??'';
+          final areaSizeRange = currentItem.areaSizeRange??'';
+          final num = currentItem.num?? 1;
+          final price = currentItem.price?? 0;
+          return  Container(
+            padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
+            margin: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 0),
+            color: ColorUtils.string2Color('#F8F8F8'),
+            child: Column(
+              children: [
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  mainAxisSize: MainAxisSize.max,
                   children: [
-                    MyTextView(
-                      title,
-                      fontSize: 16,
-                      isFontMedium: true,
-                      textColor: context.appColors.textBlack,
+                    Expanded(
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          MyTextView(
+                            title,
+                            fontSize: 16,
+                            isFontMedium: true,
+                            textColor: context.appColors.textBlack,
+                          ),
+                          MyTextView(
+                            areaSizeRange,
+                            fontSize: 15,
+                            isFontRegular: true,
+                            textColor: context.appColors.textDarkGray999,
+                            marginTop: 5,
+                          ),
+                        ],
+                      ),
                     ),
-                    MyTextView(
-                      areaSizeRange,
-                      fontSize: 15,
-                      isFontRegular: true,
-                      textColor: context.appColors.textDarkGray999,
-                      marginTop: 5,
+                    // MyCartNum(onChange: (value){
+                    //   vm.handlerChangeNum(context, value, index);
+                    // })
+                    // MyButton(
+                    //   text: '\$$price',
+                    //   onPressed: (){
+                    //       // vm.handlerChangeNum(context, value, index);
+                    //   },
+                    //   fontSize: 19,
+                    //   fontWeight: FontWeight.w500,
+                    // )
+                    Container(
+                      child: MyButton(
+                        text: '\$$price',
+                        onPressed: null,
+                        minWidth: 80,
+                        minHeight: 40,
+                        fontSize: 19,
+                        fontWeight: FontWeight.w500,
+                        // enable: !isDisable.value,
+                        textColor:  context.appColors.textPrimary,
+                        backgroundColor: context.appColors.textWhite,
+                        disabledBackgroundColor: context.appColors.disEnableGray,
+                        disabledTextColor: context.appColors.textWhite,
+                      ),
                     ),
                   ],
                 ),
-              ),
-              // MyCartNum(onChange: (value){
-              //   vm.handlerChangeNum(context, value, index);
-              // })
-              // MyButton(
-              //   text: '\$$price',
-              //   onPressed: (){
-              //       // vm.handlerChangeNum(context, value, index);
-              //   },
-              //   fontSize: 19,
-              //   fontWeight: FontWeight.w500,
-              // )
-              Container(
-                child: MyButton(
-                  text: '\$$price',
-                  onPressed: null,
-                  minWidth: 80,
-                  minHeight: 40,
-                  fontSize: 19,
-                  fontWeight: FontWeight.w500,
-                  // enable: !isDisable.value,
-                  textColor:  context.appColors.textPrimary,
-                  backgroundColor: context.appColors.textWhite,
-                  disabledBackgroundColor: context.appColors.disEnableGray,
-                  disabledTextColor: context.appColors.textWhite,
+                // Divider(),
+              ],
+            ),
+          );
+        }),
+      );
+    }else {
+      return const SizedBox.shrink();
+    }
+  }
+
+  Widget _buildAirCleanCleanContent(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context, WidgetRef ref, List<AirConditionContentItem> checkedServiceList) {
+    if(checkedServiceList.isNotEmpty){
+      return Column(
+        children: List.generate(checkedServiceList.length, (index){
+          AirConditionContentItem currentItem = checkedServiceList[index] as AirConditionContentItem;
+          final title = currentItem.name??'';
+          final num = currentItem.num?? 1;
+          final price = currentItem.price?? 0;
+          return  Container(
+            padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
+            margin: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 0),
+            color: ColorUtils.string2Color('#F8F8F8'),
+            child: Column(
+              children: [
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  mainAxisSize: MainAxisSize.max,
+                  children: [
+                    Expanded(
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          MyTextView(
+                            title,
+                            fontSize: 16,
+                            isFontMedium: true,
+                            textColor: context.appColors.textBlack,
+                          ),
+                          MyTextView(
+                            'X $num',
+                            fontSize: 15,
+                            isFontRegular: true,
+                            textColor: context.appColors.textDarkGray999,
+                            marginTop: 5,
+                          ),
+                        ],
+                      ),
+                    ),
+                    MyButton(
+                      text: '\$$price',
+                      onPressed: null,
+                      minWidth: 80,
+                      minHeight: 40,
+                      fontSize: 19,
+                      fontWeight: FontWeight.w500,
+                      // enable: !isDisable.value,
+                      textColor:  context.appColors.textPrimary,
+                      backgroundColor: context.appColors.textWhite,
+                      disabledBackgroundColor: context.appColors.disEnableGray,
+                      disabledTextColor: context.appColors.textWhite,
+                    ),
+                  ],
                 ),
-              ),
-            ],
-          ),
-          // Divider(),
-        ],
-      ),
-    );
+                // Divider(),
+              ],
+            ),
+          );
+        }),
+      );
+    }else {
+      return const SizedBox.shrink();
+    }
   }
 
 
-  Widget _buildOrderVisitTime(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context) {
+  Widget _buildOrderVisitTime(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm, BuildContext context, WidgetRef ref) {
+    String visitTime = state.visitTime??'';
     return Row(
       mainAxisSize: MainAxisSize.max,
       mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -429,7 +516,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
             mainAxisAlignment: MainAxisAlignment.end,
             children: [
               MyTextView(
-                '2021-01-01 12:00',
+                '$visitTime',
                 fontSize: 15,
                 textColor: context.appColors.textDarkGray999,
                 isFontRegular: true,
@@ -643,7 +730,10 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
   }
 
   // 底部操作区域
-  Widget _buildBottomSection(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm,WidgetRef ref, BuildContext context, int id, int serviceTypeCode, totalPrice) {
+  Widget _buildBottomSection(ServiceOrderConfirmState state, ServiceOrderConfirmVm vm,WidgetRef ref, BuildContext context, int id, String cleanServiceType) {
+
+    double totalPrice = ref.watch(serviceOrderConfirmVmProvider.select((state) => ((state.cleanServiceToTalCost??0.0) + (state.extraCost??0.0)??0.0)));
+
     return Container(
       height: 50,
       width: double.infinity,
@@ -695,7 +785,7 @@ class ServiceOrderConfirmPage extends HookConsumerWidget {
                 ),
               ),
             ).onTap((){
-              vm.handlerClickPayNow(context, id: id , serviceTypeCode: serviceTypeCode);
+              vm.handlerClickPayNow(context, id: id , cleanServiceType: cleanServiceType);
             }),
           ),
         ],

+ 24 - 9
packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_state.dart

@@ -1,22 +1,33 @@
+import 'package:domain/entity/paid_service_detail_entity.dart';
+import 'package:domain/entity/paid_service_pay_success_info_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class ServiceOrderConfirmState {
+
+  double? get totalPrice => cleanServiceToTalCost?? 0.0.toDouble() + extraCost! ?? 0.0.toDouble(); // 总价(包含购买的所有服务的价格 + 加急/节假日/夜间 等的价格总和)
   //页面 LoadView 状态的展示
   LoadState loadingState;
   String? errorMessage;
-  double? totalPrice;
+  double? cleanServiceToTalCost;  // 服务项目的总价(不包含加急/节假日/夜间 等的价格)
+  double? extraCost; // 额外费用(加急/节假日/夜间 等的额外费用)
+  String? visitTime;
   Map<String, Map<String, dynamic>> remarkInfo;
-  Map<String, dynamic>? datas;
+  PaidServiceDetailEntity? datas;
+
+  // 成功支付后的数据
+  PaidServicePaySuccessInfoEntity? paidServicePaySuccessInfo;
 
 
   ServiceOrderConfirmState({
     this.loadingState = LoadState.State_Loading,
     String? errorMessage,
-    double? totalPrice,
-
+    double? cleanServiceToTalCost,
+    this.extraCost = 0.0,
+    this.visitTime,
     remarkInfo,
     this.datas,
+    this.paidServicePaySuccessInfo,
   }): remarkInfo = remarkInfo ?? {
     "remark": {
       'value': '',
@@ -25,20 +36,24 @@ class ServiceOrderConfirmState {
       'focusNode': FocusNode(),
       'obsecure': false,
     },
-  },
-  totalPrice = totalPrice ?? 0.0;
+  }, cleanServiceToTalCost = cleanServiceToTalCost ?? 0.0;
 
   ServiceOrderConfirmState copyWith({
     LoadState? loadingState,
     String? errorMessage,
-    double? totalPrice,
+    double? cleanServiceToTalCost,
+    double? extraCost,
+    String? visitTime,
     Map<String, dynamic>? remarkInfo,
-    Map<String, dynamic>? datas,
+    PaidServiceDetailEntity? datas,
+    PaidServicePaySuccessInfoEntity? paidServicePaySuccessInfo,
   }) {
     return ServiceOrderConfirmState(
       loadingState: loadingState ?? this.loadingState,
       errorMessage: errorMessage ?? this.errorMessage,
-      totalPrice: totalPrice ?? this.totalPrice,
+      cleanServiceToTalCost: cleanServiceToTalCost ?? this.cleanServiceToTalCost,
+      extraCost: extraCost ?? this.extraCost,
+      visitTime: visitTime ?? this.visitTime,
       remarkInfo: remarkInfo ?? this.remarkInfo,
       datas: datas ?? this.datas,
     );

+ 203 - 129
packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_vm.dart

@@ -8,6 +8,8 @@ import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_detail_entity.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
+import 'package:domain/entity/paid_service_pay_success_info_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
@@ -20,12 +22,15 @@ import 'package:widgets/dialog/dialog_content_wrap.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../../../components/chooseAirConditionContent_state.dart';
 import '../../../components/chooseHouseCleanContent.dart';
+import '../../../components/chooseHouseCleanContent_state.dart';
 import '../../../components/chooseHouseCleanTitle.dart';
 import '../../../components/chooseVisitTimeBottomFooter.dart';
 import '../../../constants_services.dart';
 import '../../../respository/services_respository.dart';
 import '../../../router/page/services_page_router.dart';
+import '../service_clean_detail/service_clean_detail_vm.dart';
 import '../service_pay_success/service_pay_success_page.dart';
 import 'service_order_confirm_state.dart';
 
@@ -42,8 +47,8 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
 
-  int _detailId = 0;
-  int _detailServiceTypeCode = 0;
+  int? _id;
+  String? _cleanServiceType;
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
@@ -51,17 +56,21 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
     controlFinishLoad: true,   //允许加载
   );
 
-  ServiceOrderConfirmState initState() {
+
+
+  ServiceOrderConfirmState initState(PaidServiceDetailEntity detailEntity) {
     return ServiceOrderConfirmState(
-      datas: {}
+      datas: detailEntity
     );
   }
 
   @override
   ServiceOrderConfirmState build(){
     // 引入数据仓库
-    // servicesRespositoryInstance = ref.read(commonGarageRespositoryProvider);
-    final state = initState();
+    servicesRespositoryInstance = ref.read(servicesRespositoryProvider);
+    final serviceDetailVm = ref.read(serviceCleanDetailVmProvider.notifier);
+    PaidServiceDetailEntity detailEntity = serviceDetailVm.state.datas!;
+    final state = initState(detailEntity);
     Log.d("--------------------------build---------------------");
 
     return state;
@@ -77,34 +86,32 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
   }
 
 
-  setInitPageData({required int id, required int serviceTypeCode}){
-    _detailId = id;
-    _detailServiceTypeCode = serviceTypeCode;
+  setInitPageData({required int id, required String cleanServiceType}){
+    _id = id;
+    _cleanServiceType = cleanServiceType;
   }
   // 初始化页面数据
-  initPageData({detailId, detailServiceTypeCode}) {
-    _detailId = detailId??_detailId;
-    _detailServiceTypeCode = detailServiceTypeCode??_detailServiceTypeCode;
+  initPageData(BuildContext context) {
     Log.d("--------------------------initPageData---------------------");
     changeLoadingState(LoadState.State_Success, null);
-    setConfirmOrderTotalPrice(null);
+
+    WidgetsBinding.instance.addPostFrameCallback((_){
+      // 设置/更新 totalPrice
+      setConfirmOrderTotalPrice(context);
+    });
   }
 
   // 上拉加载 更多
   Future loadMore() async {
-    Log.d("----home_service_vm-----loadMore");
     _page++;
-    getListData();
   }
 
 
   // 下拉刷新
   Future onRefresh() async {
     // 当前pageView 页面正处于显示状态
-    Log.d("----forsale_vm-----onRefresh ");
     // await Future.delayed(const Duration(seconds: 2));
     _page = 1;
-    getListData();
   }
 
 
@@ -123,7 +130,6 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
     refreshController.resetFooter();
     _page = 1;
     _needShowPlaceholder = true;
-    getListData();
   }
 
 
@@ -131,89 +137,9 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
   Future retryRequest() async {
     _page = 1;
     _needShowPlaceholder = true;
-    getListData();
   }
 
 
-  // 获取list 列表数据
-  Future getListData<T>({bool? isLoadMore}) async {
-    if (_needShowPlaceholder) {
-      changeLoadingState(LoadState.State_Loading, null);
-    }
-
-    List<Map<String, dynamic>> list = [
-      {
-        'id':1,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 0,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':2,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-      {
-        'id':3,
-        'service_type': 0,  // 0 房屋保洁 1 空调保洁  2 维修
-        'cover_img':  'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500',
-        'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'],
-        'title': 'House Cleaning Services',
-        'duration': 'Daily cleaning for 2 hours',
-        'totalPrice': 66,
-        'visit_time': '14 0ct 2024 15:00',
-        'order_time': '13 0ct 2024 12:00',
-        'status_text': 'In Progress',
-        'status_code': 1,
-        'company_name': 'HONG YE GROUP PTE LTD',
-      },
-    ];
-    handlerResultData(true, list:list);
-
-    // try {
-    //   //请求网络
-    //   Map<String, dynamic>  params = {
-    //     "type": 1,  // 类型(1=Sale,2=Rent)
-    //     "category_id": _queryParams['category_id'],
-    //     "keyword": _queryParams['keyword'],
-    //     "page": _page,
-    //     "limit": _limit,
-    //   };
-    //   Log.d("请求参数------$params");
-    //   final result = await servicesRespositoryInstance.fetchGarageDataList(params);
-    //   //校验成功失败
-    //   if (result.isSuccess) {
-    //     // handlerResultList((result.data as GarageSaleRentEntity).list as List<GarageSaleRentList>, isLoadMore ?? false);
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
-
-    // 最后赋值
-    _needShowPlaceholder = false;
-
-  }
 
   handlerResultData(bool isList, {List<Map<String, dynamic>>? list, dynamic? data}){
     Future.delayed(const Duration(seconds: 1)).then((value) {
@@ -261,27 +187,33 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
     });
   }
 
-
+  // 点击预约时间
   handlerClickVisitTime(BuildContext context){
-    // ToastEngine.show("Visit Time");
     handlerShowChooseVisitTimeDialog(context);
   }
 
-  // 显示 选择空调型号和数量的弹框
+  // 显示 预约时间弹框
   handlerShowChooseVisitTimeDialog(BuildContext context) async{
+    // 每次点击 预约时间按钮,需要 清空 confirm 页面的 extraCost
     // 定时器
-    LoadState dialogState = LoadState.State_Loading;
-
+    LoadState dialogState = LoadState.State_Success;
     DialogEngine.show(
-        tag: "chooseAirConditionClean",
+        tag: "chooseVisitTimeDialog",
         position: DialogPosition.bottom,
+        clickMaskDismiss:false,
+        onDismiss: (){
+          Log.d("--------------------------dismissDialog---------------------");
+          // 弹框消失
+          // _chooseVisitTimeDialogGlobalKey.currentState?.dismissDialog();
+        },
         widget: DialogContentWrap(
           key: _chooseVisitTimeDialogGlobalKey,
           loadingState: dialogState,
-          maxHeight: 480.0,
+          maxHeight: 450.0,
           dialogWidth: context.screenSize.width,
           isShowConfirmBtn: false,
           isShowCancelBtn: false,
+          closeIconColor: context.appColors.textPrimary,
           title: "",
           bottomBtnRadius:0,
           bottomBtnSpace: 0,
@@ -304,6 +236,7 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
           // ),
           confirmAction: chooseVisitTimeConfirmFn,
           cancelAction: chooseVisitTimeCancelFn,
+            closeAction: chooseVisitTimeCloseFn,
           titleBuilder: (context) {
             return buildChooseVisitTimeTitle(context);
           },
@@ -315,60 +248,201 @@ class ServiceOrderConfirmVm extends _$ServiceOrderConfirmVm {
           },
         )
     );
+  }
 
-    await Future.delayed(Duration(milliseconds: 1000));
-
+  // 修改 _chooseVisitTimeDialogGlobalKey 弹框的 loading状态
+  changeDialogLoadingState(LoadState state){
     _chooseVisitTimeDialogGlobalKey.currentState?.changeDialogLoadingState(LoadState.State_Success);
   }
 
   chooseVisitTimeConfirmFn(){
-    Log.d("点击了确定");
+    Log.d("预约时间 点击了确定");
     // 跳转到 订单确认页面
-    // appRouter.push(ServiceOrderConfirmPageRoute(id: _detailId, serviceTypeCode: _detailServiceTypeCode));
+    // appRouter.push(ServiceOrderConfirmPageRoute(id: _id, cleanServiceType: _cleanServiceType));
   }
 
   chooseVisitTimeCancelFn(){
     Log.d("点击了取消");
   }
 
+  chooseVisitTimeCloseFn(){
+    Log.d("点击了右上方关闭");
+  }
+
   Widget buildChooseVisitTimeTitle(BuildContext context){
-    return ChooseVisitTimeTitle(id: 0, serviceTypeCode: 0);
+    return ChooseVisitTimeTitle(id: 0, cleanServiceType: _cleanServiceType!);
   }
 
   Widget buildChooseVisitTimeContent(BuildContext context){
-    return ChooseVisitTimeContent(id: 0, serviceTypeCode: 0,);
+    return ChooseVisitTimeContent(id: _id!, cleanServiceType: _cleanServiceType!,);
   }
 
   Widget buildChooseVisitTimeBottomFooter(BuildContext context){
-    return ChooseVisitTimeBottomFooter(id: 0, serviceTypeCode: 0,);
+    return ChooseVisitTimeBottomFooter(id: _id!, cleanServiceType: _cleanServiceType!,);
+  }
+
+  // 更新visitTime
+  handlerUpdateVisitTime(String visitTime){
+    Log.d("选择的visitTime: $visitTime");
+    state = state.copyWith(visitTime: visitTime);
   }
 
   // 关闭visitTime 选择的弹框
   handlerHideVisitTimeDialog(){
-    DialogEngine.dismiss(tag: 'chooseAirConditionClean');
+    DialogEngine.dismiss(tag: 'chooseVisitTimeDialog');
+  }
+
+  // 获取 当前 所选的服务
+  Map<String, dynamic> getCurrentService(){
+    final chooseHouseCleanServiceDetailVm = ref.watch(chooseHouseCleanContentVmProvider.notifier);
+    List<HouseCleanContentItem> houseCleanCheckedServiceList = [];
+    final chooseAirCleanServiceDetailVm = ref.watch(chooseAirConditionContentVmProvider.notifier);
+    List<AirConditionContentItem> airCleancheckedServiceList = [];
+
+    if (_cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code']) {
+      houseCleanCheckedServiceList = chooseHouseCleanServiceDetailVm.state.checkedServiceList ?? [];
+    } else if (_cleanServiceType == servicesConstants.servicesType['airConditioner']!['code']) {
+      airCleancheckedServiceList = chooseAirCleanServiceDetailVm.state.checkedServiceList ?? [];
+    }
+
+    return {
+      "houseCleanCheckedServiceList": houseCleanCheckedServiceList,
+      "airCleancheckedServiceList": airCleancheckedServiceList
+    };
   }
 
   // 去支付
-  handlerClickPayNow(BuildContext context, {int? id, int? serviceTypeCode}){
-    ToastEngine.show("Pay Now");
-    // 去支付成功页面
-    ServicePaySuccessPage.startInstance(id: 0, serviceTypeCode: 0);
+  handlerClickPayNow(BuildContext context, {int? id, String? cleanServiceType}) async{
+    // ToastEngine.show("Pay Now");
+    if(state.visitTime == null || state.visitTime!.isEmpty){
+      // 预约时间没有
+      ToastEngine.show("Please select the visit time");
+      return;
+    }
+    try {
+      Map<String, dynamic> params = {
+        "planned_service_at": state.visitTime,
+        "notes": getRemarkInfo(),
+      };
+      // params 添加 product 参数
+      Map<String, dynamic> resultParams = handlerSubmitParams();
+      // 数组参数扁平
+      List<Map<String, dynamic>> products = resultParams['products'].cast<Map<String, dynamic>>();
+      String productsKey = 'products';
+      List<String> keys = ['id', 'quantity'];
+
+      Map<String, dynamic> flattenedProducts = handlerFlattenArrayParams(products, productsKey, keys);
+      // 合并参数
+      params.addAll(flattenedProducts);
+      Log.d("最终的参数params:  $params");
+
+      // final result = await servicesRespositoryInstance.fetchPaidServiceBook(params);
+      // if(result.isSuccess){
+      //   state = state.copyWith(paidServicePaySuccessInfo: result.data as PaidServicePaySuccessInfoEntity);
+      //   // 成功后 去支付成功页面
+      //   // ServicePaySuccessPage.startInstance();
+      //   context.appRouter.pushAndPopUntil(const ServicePaySuccessPageRoute(), predicate: (Route<dynamic> route) {       // 根据具体条件返回 true 或 false
+      //     // Log.d("888 ${route.settings}");
+      //     return route.settings.name != 'ServiceOrderConfirmPageRoute';
+      //   });
+      // } else {
+      //   String errorMessage = result.errorMsg!;
+      //   // changeLoadingState(LoadState.State_Error, errorMessage);
+      //   ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      // }
+
+
+      context.appRouter.pushAndPopUntil(const ServicePaySuccessPageRoute(), predicate: (Route<dynamic> route) {       // 根据具体条件返回 true 或 false
+        // Log.d("888 ${route.settings}");
+        return route.settings.name != 'ServiceOrderConfirmPageRoute';
+      });
+
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+
+  }
+
+  Map<String, dynamic> handlerFlattenArrayParams(List<Map<String, dynamic>> products, String productsKey, List<String> keys) {
+    Map<String, dynamic> flattened = {};
+    for (int i = 0; i < products.length; i++) {
+      for (String key in keys) {
+        if (products[i].containsKey(key)) {
+          flattened['$productsKey[$i][$key]'] = products[i][key];
+        }
+      }
+    }
+    return flattened;
   }
 
+  Map<String, dynamic> handlerSubmitParams(){
+    Map<String, dynamic> resultParams = {};
+    final result = getCurrentService();
+    List<HouseCleanContentItem> houseCleanCheckedServiceList = result["houseCleanCheckedServiceList"] as List<HouseCleanContentItem>;
+    List<AirConditionContentItem> airCleancheckedServiceList = result["airCleancheckedServiceList"] as List<AirConditionContentItem>;
+
+    Log.d("houseCleanCheckedServiceList  $houseCleanCheckedServiceList");
+    Log.d("airCleancheckedServiceList  $airCleancheckedServiceList");
+    if(_cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code']){
+      if(houseCleanCheckedServiceList != null && houseCleanCheckedServiceList.length > 0){
+        resultParams['products'] = []; // 初始化 products 为一个 List
+        houseCleanCheckedServiceList.asMap().forEach((idx, element) {
+          resultParams['products'].add({
+            'id': element.id,
+            'quantity': element.num ?? 1,
+          });
+        });
+      }
+    }else if(_cleanServiceType == servicesConstants.servicesType['airConditioner']!['code']){
+      if(airCleancheckedServiceList != null && airCleancheckedServiceList.length > 0){
+        resultParams['products'] = []; // 初始化 products 为一个 List
+        airCleancheckedServiceList.asMap().forEach((idx, element) {
+          resultParams['products'].add({
+            'id': element.id,
+            'quantity': element.num ?? 1,
+          });
+        });
+      }
+    }
+    return resultParams;
+  }
+  // 获取订单备注
+  String getRemarkInfo(){
+    String remarkInfo = "";
+    if(state.remarkInfo != null){
+      remarkInfo = state.remarkInfo!["remark"]!['controller'].text;
+    }
+    Log.d("订单的备注信息: $remarkInfo");
+    return remarkInfo;
+  }
+  // 设置订单相关数据    总价(包含购买的所有服务的价格 + 加急/节假日/夜间 等的价格总和)
   setConfirmOrderTotalPrice(BuildContext? context){
-    final visitTimeTotalPrice = ref.read(chooseVisitTimeContentVmProvider).totalPrice?? 0.0;
-    final airConditionTotalPrice = ref.read(chooseAirConditionContentVmProvider).totalPrice?? 0.0 ;
-    final houseCleaningTotalPrice = ref.read(chooseHouseCleanContentVmProvider).totalPrice?? 0.0;
-    final totalPrice = visitTimeTotalPrice.toDouble() + airConditionTotalPrice.toDouble() + houseCleaningTotalPrice.toDouble();
-    // if( _detailServiceTypeCode == servicesConstants.servicesType['houseCleaning'] ){
-    //
-    // }else if(_detailServiceTypeCode == servicesConstants.servicesType['airConditioner']){
-    //
-    // }else {
-    //
-    // }
+    Log.d("service_order_confirm_vm 设置订单页面的相关数据");
+    double cleanServiceToTalPrice = 0.0;
+    double extraCost = 0.0;  // 加急/节假日/夜间 等费用
+
+    final chooseHouseCleanCotentVm = ref.read(chooseHouseCleanContentVmProvider.notifier);
+    double houseCleanTotalPrice = 0.0;
+    final chooseAirCleanContentVm = ref.read(chooseAirConditionContentVmProvider.notifier);
+    double airCleanTotalPrice = 0.0;
+
+    if (_cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code']) {
+      houseCleanTotalPrice = (chooseHouseCleanCotentVm?.state.totalPrice ?? 0.0).toDouble();
+      cleanServiceToTalPrice = houseCleanTotalPrice;
+    } else if (_cleanServiceType == servicesConstants.servicesType['airConditioner']!['code']) {
+      airCleanTotalPrice = (chooseAirCleanContentVm?.state.totalPrice ?? 0.0).toDouble();
+      cleanServiceToTalPrice = airCleanTotalPrice;
+    }
+    final chooseVisitTimeContentVm = ref.read(chooseVisitTimeContentVmProvider.notifier);
+    extraCost = chooseVisitTimeContentVm?.state.extraTotalCost??0.0;
+    Log.d("当前的 extraCost: $extraCost");
+
+    final serviceDetailVm = ref.read(serviceCleanDetailVmProvider.notifier);
+
     state = state.copyWith(
-        totalPrice: totalPrice
+        cleanServiceToTalCost: cleanServiceToTalPrice,
+        extraCost: extraCost,
+        datas: serviceDetailVm?.state.datas!
     );
   }
 }

+ 1 - 1
packages/cpt_services/lib/modules/services/service_order_confirm/service_order_confirm_vm.g.dart

@@ -7,7 +7,7 @@ part of 'service_order_confirm_vm.dart';
 // **************************************************************************
 
 String _$serviceOrderConfirmVmHash() =>
-    r'f302671a6b33ca6b42dd89579c7a75e3b2356be6';
+    r'b7cf5a927676989e18f7723f78c5535300082b02';
 
 /// See also [ServiceOrderConfirmVm].
 @ProviderFor(ServiceOrderConfirmVm)

+ 5 - 10
packages/cpt_services/lib/modules/services/service_pay_success/service_pay_success_page.dart

@@ -1,5 +1,4 @@
 import 'package:cs_resources/generated/assets.dart';
-import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -28,20 +27,16 @@ import '../../../components/status_card_item.dart';
 
 @RoutePage()
 class ServicePaySuccessPage extends HookConsumerWidget {
-  final int id;
-  final int serviceTypeCode;
   const ServicePaySuccessPage({
     Key? key,
-    required this.id,
-    required this.serviceTypeCode,
   }) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context, required int id, required int serviceTypeCode}) {
+  static void startInstance({BuildContext? context,}) {
     if (context != null) {
-      context.router.push(ServicePaySuccessPageRoute(id: id, serviceTypeCode: serviceTypeCode));
+      context.router.push(ServicePaySuccessPageRoute());
     } else {
-      appRouter.push(ServicePaySuccessPageRoute(id:id, serviceTypeCode: serviceTypeCode));
+      appRouter.push(ServicePaySuccessPageRoute());
     }
   }
 
@@ -103,12 +98,12 @@ class ServicePaySuccessPage extends HookConsumerWidget {
   Widget _buildTopInfo(BuildContext context, ServicePaySuccessState state, WidgetRef ref) {
     return Container(
       width: double.infinity,
-      height: 350,
+      height: 300,
       color: context.appColors.whiteBG,
       child: Column(
         children: [
           Container(
-            margin: const EdgeInsets.only(top: 30),
+            margin: const EdgeInsets.only(top: 20),
             child: const MyAssetImage(
               Assets.servicePaySuccessIcon,
               width: 54,

+ 110 - 0
packages/cpt_services/lib/modules/services/service_repair_detail/getQuoteDialogContent.dart

@@ -0,0 +1,110 @@
+import 'dart:math';
+
+import 'package:auto_route/src/route/page_route_info.dart';
+import 'package:cpt_services/components/chooseVisitTimeBottomFooter.dart';
+import 'package:cpt_services/modules/services/clean_order_detail/clean_order_detail_vm.dart';
+import 'package:cpt_services/modules/services/service_repair_detail/service_repair_detail_vm.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+class GetQuoteDialogContent extends HookConsumerWidget {
+
+  const GetQuoteDialogContent({
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(cleanOrderDetailVmProvider.notifier);
+
+    return SizedBox(
+      width: double.infinity,
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            "Please fill in your remarks information",
+            fontSize: 17,
+            isFontBold: true,
+          ),
+          Container(
+            height: 175,
+            child: _buildTextAreaLayout(context, vm, ref, 'userNotes'),
+          ),
+        ],
+      ),
+    );
+  }
+
+  /// 多行输入框
+  Widget _buildTextAreaLayout(BuildContext context, CleanOrderDetailVm vm, WidgetRef ref, String key) {
+    final state = ref.watch(serviceRepairDetailVmProvider);
+    final repairDetailVm = ref.read(serviceRepairDetailVmProvider.notifier);
+    final noteCount = useState(0);
+    return Stack(children: [
+      Container(
+        color: ColorUtils.string2Color("#F2F3F6"),
+        margin: const EdgeInsets.only(top: 15, bottom: 28.5),
+        padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
+        child: TextField(
+          cursorColor: context.appColors.authFiledText,
+          cursorWidth: 1.5,
+          autofocus: false,
+          enabled: true,
+          maxLines: null,
+          focusNode: state.getQuoteFormData![key]!['focusNode'],
+          controller: state.getQuoteFormData![key]!['controller'],
+          decoration: InputDecoration(
+            isDense: true,
+            isCollapsed: true,
+            border: InputBorder.none,
+            hintText: state.getQuoteFormData![key]!['hintText'],
+            hintStyle: TextStyle(
+              color: context.appColors.authFiledHint,
+              fontSize: 16.0,
+              fontWeight: FontWeight.w400,
+            ),
+          ),
+          style: TextStyle(
+            color: context.appColors.authFiledText,
+            fontSize: 16.0,
+            fontWeight: FontWeight.w400,
+          ),
+          textInputAction: TextInputAction.done,
+          onSubmitted: (value) {
+            FocusScope.of(context).unfocus();
+          },
+          expands: true,
+          onChanged: (text) {
+            // 当文本改变时,更新字符数量
+            noteCount.value = text.length;
+            repairDetailVm.changeGetQuoteFormData(context, text);
+          },
+        ),
+      ),
+      // Positioned(
+      //   bottom: 0.0,
+      //   right: 0.0,
+      //   child: Text(
+      //     S.current.characters(noteCount.value),
+      //     style: TextStyle(
+      //       color: context.appColors.textBlack,
+      //       fontSize: 15.0,
+      //     ),
+      //   ),
+      // ),
+    ]);
+  }
+}

+ 163 - 146
packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_page.dart

@@ -3,6 +3,7 @@ import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
+import 'package:domain/entity/service_repair_detail_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
@@ -14,6 +15,7 @@ import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/color_utils.dart';
 import 'package:shared/utils/ext_dart.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/richText_utils.dart';
 import 'package:shared/utils/size_config.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/load_state_layout.dart';
@@ -31,39 +33,49 @@ import '../../../router/page/services_page_router.dart';
 @RoutePage()
 class ServiceRepairDetailPage extends HookConsumerWidget {
   final int id;
-  final int serviceTypeCode;
+  final String? cleanServiceType;
 
-  const ServiceRepairDetailPage({Key? key,@PathParam('id') required this.id, @PathParam('serviceTypeCode') required this.serviceTypeCode}) : super(key: key);
+  const ServiceRepairDetailPage(
+      {Key? key,
+      @PathParam('id') required this.id,
+      @PathParam('cleanServiceType') required this.cleanServiceType})
+      : super(key: key);
   // 启动当前页面
-  static void startInstance({BuildContext? context, int? id, int? serviceTypeCode = 0}) {
+  static void startInstance(
+      {BuildContext? context, int? id, String? cleanServiceType}) {
     if (context != null) {
-      context.router.push(ServiceRepairDetailPageRoute(id: id!, serviceTypeCode: serviceTypeCode!));
+      context.router.push(ServiceRepairDetailPageRoute(
+          id: id!, cleanServiceType: cleanServiceType!));
     } else {
-      appRouter.push(ServiceRepairDetailPageRoute(id: id!, serviceTypeCode: serviceTypeCode!));
+      appRouter.push(ServiceRepairDetailPageRoute(
+          id: id!, cleanServiceType: cleanServiceType!));
     }
   }
 
-
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final state = ref.watch(serviceRepairDetailVmProvider);
     final vm = ref.read(serviceRepairDetailVmProvider.notifier);
     final String pageTitle = 'Repair Details';
 
-    Map<String, dynamic>? detailInfo = state.datas?? {};
+    ServiceRepairDetailEntity? detailInfo =
+        (state.datas ?? {}) as ServiceRepairDetailEntity?;
 
-    String contactType =  detailInfo?['contact']??'';
+    // String contactType =  detailInfo?['contact']??'';
 
     String description = '';
 
-    useEffect((){
-      vm.setInitPageData(id: id, serviceTypeCode: serviceTypeCode,);
+    useEffect(() {
+      vm.setInitPageData(
+        id: id,
+        cleanServiceType: cleanServiceType,
+      );
       // 组件挂载时执行 - 执行接口请求
       Future.microtask(() => vm.initPageData());
       return () {
         // 组件卸载时执行
       };
-    },[]);
+    }, []);
 
     return Scaffold(
       appBar: MyAppBar.appBar(
@@ -80,38 +92,34 @@ class ServiceRepairDetailPage extends HookConsumerWidget {
               // 上拉加载
               onLoad: null,
               // 下拉刷新
-              onRefresh: () async{
+              onRefresh: () async {
                 Log.d("----onRefresh");
                 vm.onRefresh();
               },
               // header: MaterialHeader(),
-              child: Stack(
-                  children:[
-                    LoadStateLayout(
-                      state: state.loadingState,
-                      errorMessage: state.errorMessage,
-                      errorRetry: () {
-                        vm.retryRequest();
-                      },
-                      // successWidget: SingleChildScrollView(
-                      //   scrollDirection: Axis.vertical,
-                      //   physics: const BouncingScrollPhysics(),
-                      //   clipBehavior: Clip.none,
-                      //   child: _buildContentBox(context, ref, detailInfo,),
-                      // ),
-                      successSliverWidget: [
-                        SliverList(
-                          delegate: SliverChildBuilderDelegate(
-                                  (context, index){
-                                return _buildContentBox(context, ref, detailInfo!, state, vm);
-                              },
-                              childCount: 1
-                          ),
-                        )
-                      ],
-                    ),
-                  ]
-              ),
+              child: Stack(children: [
+                LoadStateLayout(
+                  state: state.loadingState,
+                  errorMessage: state.errorMessage,
+                  errorRetry: () {
+                    vm.retryRequest();
+                  },
+                  // successWidget: SingleChildScrollView(
+                  //   scrollDirection: Axis.vertical,
+                  //   physics: const BouncingScrollPhysics(),
+                  //   clipBehavior: Clip.none,
+                  //   child: _buildContentBox(context, ref, detailInfo,),
+                  // ),
+                  successSliverWidget: [
+                    SliverList(
+                      delegate: SliverChildBuilderDelegate((context, index) {
+                        return _buildContentBox(
+                            context, ref, detailInfo, state, vm);
+                      }, childCount: 1),
+                    )
+                  ],
+                ),
+              ]),
             ),
           ),
         ],
@@ -119,93 +127,97 @@ class ServiceRepairDetailPage extends HookConsumerWidget {
     );
   }
 
+  Widget _buildContentBox(
+      BuildContext context,
+      WidgetRef ref,
+      ServiceRepairDetailEntity? detailInfo,
+      ServiceRepairDetailState state,
+      ServiceRepairDetailVm vm) {
+    final String title = detailInfo?.name??'';
+    final description =  RichtextUtils.getHandleResult(detailInfo?.description??'');
 
-  Widget _buildContentBox(BuildContext context, WidgetRef ref, Map<String, dynamic>? detailInfo, ServiceRepairDetailState state, ServiceRepairDetailVm vm) {
-    // List<String> resources = detailInfo?['resources'].cast<String>()??[];
-    // String title =  detailInfo?['title']??'';
-    double score = detailInfo?['score']?? 5.0;
-    // String description = detailInfo?['description']??'';
-
-    return Column(
+    return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
+      Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         children: [
+          //  评分
           Column(
-            crossAxisAlignment: CrossAxisAlignment.start,
             children: [
-              //  评分
-              Column(
-                children: [
-                  Container(
-                    width: double.infinity,
-                    padding: const EdgeInsets.only(left: 16, right: 16, top: 16,bottom: 16),
-                    color: context.appColors.whiteBG,
-                    child: Column(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        MyTextView(
-                          "House Cleaning Services",
-                          textColor: context.appColors.textBlack,
-                          fontSize: 18,
-                          isFontBold: true,
-                          marginBottom: 5,
-                        ),
-                        Row(
-                          mainAxisAlignment: MainAxisAlignment.start,
-                          crossAxisAlignment: CrossAxisAlignment.center,
-                          children: [
-                            AnimatedRatingStars(
-                              initialRating: score,
-                              onChanged: (rating) {
-                              },
-                              readOnly: true,
-                              displayRatingValue: true, // Display the rating value
-                              interactiveTooltips: true, // Allow toggling half-star state
-                              customFilledIcon: Icons.star,
-                              customHalfFilledIcon: Icons.star_half,
-                              customEmptyIcon: Icons.star_border,
-                              filledColor: ColorUtils.string2Color("#FF0000"),
-                              starSize: 16.5,
-                              animationDuration: const Duration(milliseconds: 0),
-                              animationCurve: Curves.easeInOut,
-                            ),
-                            MyTextView(
-                              "${score}",
-                              textColor: context.appColors.textBlack,
-                              fontSize: 16,
-                              isFontMedium: true,
-                              marginLeft: 15,
-                            ),
-                          ],
-                        ),
-                        MyTextView(
-                          "HONG YE GROUP PTE LTD",
-                          textColor: context.appColors.textDarkGray999,
-                          fontSize: 12,
-                          isFontRegular: true,
-                          marginTop: 10,
-                          marginBottom: 5,
-                        ),
-                      ],
-                    ),
-                  ),
-                ],
-              ),
-              // profile信息
               Container(
                 width: double.infinity,
-                margin: const EdgeInsets.only(left: 0, right: 0, top: 5, bottom: 0),
-                padding: const EdgeInsets.only(left: 10, right: 10, top: 18.5, bottom: 18.5),
-                decoration: BoxDecoration(
-                  color: context.appColors.whiteBG,
+                padding: const EdgeInsets.only(
+                    left: 16, right: 16, top: 16, bottom: 16),
+                color: context.appColors.whiteBG,
+                child: Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      title,
+                      textColor: context.appColors.textBlack,
+                      fontSize: 18,
+                      isFontBold: true,
+                      marginBottom: 5,
+                    ),
+                    // Row(
+                    //   mainAxisAlignment: MainAxisAlignment.start,
+                    //   crossAxisAlignment: CrossAxisAlignment.center,
+                    //   children: [
+                    //     AnimatedRatingStars(
+                    //       initialRating: score,
+                    //       onChanged: (rating) {
+                    //       },
+                    //       readOnly: true,
+                    //       displayRatingValue: true, // Display the rating value
+                    //       interactiveTooltips: true, // Allow toggling half-star state
+                    //       customFilledIcon: Icons.star,
+                    //       customHalfFilledIcon: Icons.star_half,
+                    //       customEmptyIcon: Icons.star_border,
+                    //       filledColor: ColorUtils.string2Color("#FF0000"),
+                    //       starSize: 16.5,
+                    //       animationDuration: const Duration(milliseconds: 0),
+                    //       animationCurve: Curves.easeInOut,
+                    //     ),
+                    //     MyTextView(
+                    //       "${score}",
+                    //       textColor: context.appColors.textBlack,
+                    //       fontSize: 16,
+                    //       isFontMedium: true,
+                    //       marginLeft: 15,
+                    //     ),
+                    //   ],
+                    // ),
+                    detailInfo?.name != ''
+                        ? MyTextView(
+                            detailInfo?.merchant.name ?? '',
+                            textColor: context.appColors.textDarkGray999,
+                            fontSize: 12,
+                            isFontRegular: true,
+                            marginTop: 10,
+                            marginBottom: 5,
+                          )
+                        : Container(),
+                  ],
                 ),
-                child: _buildOrderProfile(context, state, vm),
               ),
-              // quote 按钮
-              Container(
-                width: double.infinity,
-                padding: const EdgeInsets.only(left: 16, right: 16, top: 20,bottom: 20),
-                color: Colors.transparent,
-                child: Column(
+            ],
+          ),
+          // profile信息
+          // Container(
+          //   width: double.infinity,
+          //   margin: const EdgeInsets.only(left: 0, right: 0, top: 5, bottom: 0),
+          //   padding: const EdgeInsets.only(left: 10, right: 10, top: 18.5, bottom: 18.5),
+          //   decoration: BoxDecoration(
+          //     color: context.appColors.whiteBG,
+          //   ),
+          //   child: _buildOrderProfile(context, state, vm),
+          // ),
+          // quote 按钮
+          Container(
+              width: double.infinity,
+              padding: const EdgeInsets.only(
+                  left: 16, right: 16, top: 20, bottom: 20),
+              color: Colors.transparent,
+              child: Column(
                   crossAxisAlignment: CrossAxisAlignment.start,
                   children: [
                     Center(
@@ -218,7 +230,7 @@ class ServiceRepairDetailPage extends HookConsumerWidget {
                         minHeight: 44.5,
                         fontWeight: FontWeight.w400,
                         onPressed: () {
-                          vm.handlerClickQuoteBtn(context, id, serviceTypeCode);
+                          vm.handlerGetQuote(context, id);
                         },
                       ),
                     ),
@@ -235,36 +247,42 @@ class ServiceRepairDetailPage extends HookConsumerWidget {
                         textAlign: TextAlign.center,
                       ),
                     )
+                  ])),
+          // 介绍图
+          Padding(
+              padding: const EdgeInsets.only(left: 16, right: 16, top: 16),
+              child: Column(
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    // description
+                    Html(data: description),
                   ]
-                )
-              ),
-              // 介绍图
-              Padding(
-                  padding: const EdgeInsets.only(left: 16, right: 16, top: 16),
-                  child: Column(
-                    children: List.generate(2, (index) {
-                      // 创建一个映射来关联字符串和资源
-                      final Map<String, String> assetMap = {
-                        'serviceDetail01': Assets.serviceRepairDetail01,
-                        'serviceDetail02': Assets.serviceRepairDetail02,
-                      };
-                      String curDetailStr = 'serviceDetail0${(index + 1)}';
-                      Log.d("curDetailStr   $curDetailStr");
-                      return MyAssetImage(
-                        assetMap[curDetailStr]!,
-                        width: SizeConfig().screenWidth,
-                        fit: BoxFit.cover,
-                      );
-                    }).toList(),
-                  )
-              ),
-            ],
-          ),
-        ]
-    );
+                  // List.generate(2, (index) {
+                  //   // 创建一个映射来关联字符串和资源
+                  //   final Map<String, String> assetMap = {
+                  //     'serviceDetail01': Assets.serviceRepairDetail01,
+                  //     'serviceDetail02': Assets.serviceRepairDetail02,
+                  //   };
+                  //   String curDetailStr = 'serviceDetail0${(index + 1)}';
+                  //   Log.d("curDetailStr   $curDetailStr");
+                  //   return MyAssetImage(
+                  //     assetMap[curDetailStr]!,
+                  //     width: SizeConfig().screenWidth,
+                  //     fit: BoxFit.cover,
+                  //   );
+                  // }).toList(),
+                  )),
+        ],
+      ),
+    ]);
   }
 
-  Widget _buildOrderProfile(BuildContext context, ServiceRepairDetailState state, ServiceRepairDetailVm vm,) {
+  Widget _buildOrderProfile(
+    BuildContext context,
+    ServiceRepairDetailState state,
+    ServiceRepairDetailVm vm,
+  ) {
     return Column(
       children: [
         Row(
@@ -314,5 +332,4 @@ class ServiceRepairDetailPage extends HookConsumerWidget {
       ],
     );
   }
-
 }

+ 22 - 3
packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_state.dart

@@ -1,4 +1,6 @@
 import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
+import 'package:domain/entity/service_repair_detail_entity.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class ServiceRepairDetailState {
@@ -9,7 +11,10 @@ class ServiceRepairDetailState {
   final int? id;
   final String? type;
 
-  Map<String, dynamic>? datas;
+  String? userNotes;  // 取消的文字
+  Map<String, Map<String, dynamic>> getQuoteFormData;
+
+  ServiceRepairDetailEntity? datas;
 
   ServiceRepairDetailState({
     this.loadingState = LoadState.State_Loading,
@@ -17,14 +22,26 @@ class ServiceRepairDetailState {
     this.id,
     this.type,
     required this.datas,
-  });
+    this.userNotes,
+    Map<String, Map<String, dynamic>>? getQuoteFormData,
+  }): getQuoteFormData = getQuoteFormData ?? {
+    "userNotes": {
+      'value': '',
+      'controller': TextEditingController(),
+      'hintText': '',
+      'focusNode': FocusNode(),
+      'obsecure': false,
+    },
+  };
 
   ServiceRepairDetailState copyWith({
-    Map<String, dynamic>? datas,
+    ServiceRepairDetailEntity? datas,
     LoadState? loadingState,
     String? errorMessage,
     int? id,
     String? type,
+    String? userNotes,
+    Map<String, Map<String, dynamic>>? getQuoteFormData,
   }) {
     return ServiceRepairDetailState(
       loadingState: loadingState ?? this.loadingState,
@@ -32,6 +49,8 @@ class ServiceRepairDetailState {
       id: id ?? this.id,
       type: type ?? this.type,
       datas: datas?? this.datas,
+      userNotes: userNotes ?? this.userNotes,
+      getQuoteFormData: getQuoteFormData ?? this.getQuoteFormData,
     );
   }
 }

+ 195 - 82
packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_vm.dart

@@ -1,23 +1,28 @@
-
 import 'package:cpt_services/components/chooseAirConditionContent.dart';
 import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
+import 'package:domain/entity/service_repair_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:plugin_basic/basic_export.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/permission/permission_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/color_utils.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/dialog/app_custom_dialog.dart';
+import 'package:widgets/dialog/dialog_content_wrap.dart';
 import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_button.dart';
 import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
 import 'package:flutter/src/widgets/framework.dart';
 
 import '../../../respository/services_respository.dart';
 import '../../../router/page/services_page_router.dart';
+import 'getQuoteDialogContent.dart';
 import 'service_repair_detail_state.dart';
 
 part 'service_repair_detail_vm.g.dart';
@@ -26,28 +31,28 @@ part 'service_repair_detail_vm.g.dart';
 class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
   late ServicesRespository serviceRespositoryInstance;
 
-  int _detailId = 0;
-  int _detailServiceTypeCode = 0;
+  late int _detailId;
+  late String _cleanServiceType;
 
   bool _needShowPlaceholder = false; //是否展示LoadingView
-  int _page = 1;  // 当前页
+  int _page = 1; // 当前页
   int _limit = 10; // 每页数量
   int _count = 0; // 总条数
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   ServiceRepairDetailState initState() {
     return ServiceRepairDetailState(
-      datas: null,
+      datas: ServiceRepairDetailEntity(),
     );
   }
 
   @override
-  ServiceRepairDetailState build(){
+  ServiceRepairDetailState build() {
     // 引入数据仓库
     serviceRespositoryInstance = ref.read(servicesRespositoryProvider);
     final state = initState();
@@ -56,19 +61,15 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
     return state;
   }
 
-
   //刷新页面状态
   void changeLoadingState(LoadState loadState, String? errorMsg) {
-    state = state.copyWith(
-        loadingState: loadState,
-        errorMessage: errorMsg
-    );
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
   }
 
   // 初始化页面数据
   initPageData() {
     Log.d("----for_sale_vm-----initPageData   ${state.loadingState}");
-    // onRefresh();
+    onRefresh();
     changeLoadingState(LoadState.State_Success, null);
   }
 
@@ -78,14 +79,12 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
     getDetailData();
   }
 
-
   // 下拉刷新
   Future onRefresh() async {
     _page = 1;
     getDetailData();
   }
 
-
   // 手动进行刷新
   Future triggerRefresh() async {
     Log.d("trggerRefresh");
@@ -94,7 +93,7 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
 
   // 手动进行刷新
   Future directRefresh() async {
-    state = state.copyWith(datas:null);
+    state = state.copyWith(datas: null);
     // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
     // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
     refreshController.callRefresh();
@@ -104,7 +103,6 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
     getDetailData();
   }
 
-
   // 重试请求
   Future retryRequest() async {
     _page = 1;
@@ -112,10 +110,9 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
     getDetailData();
   }
 
-
-  setInitPageData({required int id, required int serviceTypeCode}){
+  setInitPageData({required int id, required String? cleanServiceType}) {
     _detailId = id;
-    _detailServiceTypeCode = serviceTypeCode;
+    _cleanServiceType = cleanServiceType?? '';
   }
 
   Future getDetailData<T>() async {
@@ -123,7 +120,6 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-
     // await Future.delayed(const Duration(milliseconds: 1500));
     //
     // final Map<String, dynamic> detailData = {
@@ -151,36 +147,36 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
     // // 最后赋值
     // _needShowPlaceholder = false;
 
+    try {
+      Map<String, dynamic> params = {
+        "id": _detailId,
+      };
+      final result =
+          await serviceRespositoryInstance.fetchServiceRepairDetailInfo(params);
+      if (result.isSuccess) {
+        state = state.copyWith(datas: result.data as ServiceRepairDetailEntity);
+        changeLoadingState(LoadState.State_Success, null);
+        refreshController.finishRefresh();
+      } else {
+        String errorMessage = result.errorMsg!;
+        changeLoadingState(LoadState.State_Error, errorMessage);
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
 
-    // try {
-    //   Map<String, dynamic> params = {
-    //     "id": _detailId,
-    //   };
-    //   final result = await serviceRespositoryInstance.fetchServiceRepairDetailInfo(params);
-    //   if(result.isSuccess){
-    //     state = state.copyWith(datas: result.data as GarageSaleRentDetailEntity);
-    //     changeLoadingState(LoadState.State_Success, null);
-    //     refreshController.finishRefresh();
-    //   } else {
-    //     String errorMessage = result.errorMsg!;
-    //     changeLoadingState(LoadState.State_Error, errorMessage);
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error");
-    //   }
-    // } catch (e) {
-    //   ToastEngine.show("Error: $e");
-    // }
-    //
-    // // 最后赋值
-    // _needShowPlaceholder = false;
+    // 最后赋值
+    _needShowPlaceholder = false;
   }
 
-
   // 点击了底部的收藏按钮
-  Future<bool?> handlerClickCollection(BuildContext? context, int id, bool isCollection) async{
+  Future<bool?> handlerClickCollection(
+      BuildContext? context, int id, bool isCollection) async {
     // var vm;
-    // if(_detailServiceTypeCode == "forSale"){
+    // if(_cleanServiceType == "forSale"){
     //   // vm = ref.read(forsaleVmProvider.notifier);
-    // }else if(_detailServiceTypeCode == "forRent"){
+    // }else if(_cleanServiceType == "forRent"){
     //   vm = ref.read(forrentVmProvider.notifier);
     // }
     // try {
@@ -192,38 +188,39 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
   }
 
   // 判断是whatsapp 还是 mobile  (通过 contact: whatsapp:+8617671757687)
-  String getContactType(String contactType){
+  String getContactType(String contactType) {
     // whatsapp:+8617671757687  截取:前面的字符串
     String type = contactType.split(":")[0];
     return type;
   }
 
-  isContactWhatsApp(String contactType){
+  isContactWhatsApp(String contactType) {
     return contactType.contains("whatsapp");
   }
 
-  isContactMobile(String contactType){
+  isContactMobile(String contactType) {
     return contactType.contains("mobile");
   }
-  String getContactNumber(String contactType){
+
+  String getContactNumber(String contactType) {
     // whatsapp:+8617671757687     mobile:+8617671757687  截取:后面的字符串
     String number = contactType.split(":")[1];
     return number;
   }
+
   // 点击 whatsapp
-  handlerClickWhatsapp(BuildContext? context,String contactType, String title, int price){
-    // 假设你有一个获取 WhatsApp 号码的方法
+  handlerClickWhatsapp(
+      BuildContext? context, String contactType, String title, int price) {
     String whatsappNumber = getContactNumber(contactType); // 你需要实现这个方法
-    // 构建消息并进行编码
-    String message = Uri.encodeComponent("Hello, I am interested in your listing: $title for $price.");
-    // 打开WhatsApp
+    String message = Uri.encodeComponent(
+        "Hello, I am interested in your listing: $title for $price.");
     openWhatsApp(whatsappNumber, message);
   }
 
   // 打开whatsapp
   openWhatsApp(String phoneNumber, String message) async {
     final url = "https://wa.me/$phoneNumber/?text=${Uri.parse(message)}";
-    if (await  canLaunchUrl(Uri.parse(url))) {
+    if (await canLaunchUrl(Uri.parse(url))) {
       await launchUrl(Uri.parse(url));
     } else {
       ToastEngine.show("Could not launch $url");
@@ -232,30 +229,148 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
   }
 
   // 点击 电话
-  handlerClickMobile(BuildContext? context,String contactType){
+  handlerClickMobile(BuildContext? context, String contactType) {
     String mobileNumber = getContactNumber(contactType);
     // 拨打电话
-    makePhoneCall(mobileNumber);
+    PermissionEngine().requestCallPhonePermission(() async {
+      // 拨打电话
+      makePhoneCall(mobileNumber);
+    });
   }
 
   // 拨打电话
   Future<void> makePhoneCall(String phoneNumber) async {
-    final Uri launchUri = Uri(
-      scheme: 'tel',
-      path: phoneNumber,
+    PermissionEngine().requestCallPhonePermission(() async {
+      final Uri launchUri = Uri(
+        scheme: 'tel',
+        path: phoneNumber,
+      );
+
+      if (await canLaunchUrl(launchUri)) {
+        await launchUrl(launchUri);
+      } else {
+        ToastEngine.show("Could not launch $launchUri");
+        throw 'Could not launch $launchUri';
+      }
+    });
+  }
+
+  changeGetQuoteFormData(BuildContext context,String userNotes){
+    state = state.copyWith(
+      userNotes: userNotes,
     );
+  }
 
-    if (await canLaunchUrl(launchUri)) {
-      await launchUrl(launchUri);
-    } else {
-      ToastEngine.show("Could not launch $launchUri");
-      throw 'Could not launch $launchUri';
+  // 获取 报价备注信息
+  String getUserNotes(){
+    String userNotes = "";
+    if(state.getQuoteFormData != null){
+      userNotes = state.getQuoteFormData!["userNotes"]!['controller'].text;
     }
+    Log.d("报价备注信息: $userNotes");
+    return userNotes;
+  }
+
+  // 提交 报价
+  void handlerGetQuote(BuildContext context, int id) async {
+    DialogEngine.show(
+        tag: "getQuote",
+        position: DialogPosition.center,
+        onDismiss: () {
+          // 清空报价备注信息
+          clearUserNotesInput();
+        },
+        widget: DialogContentWrap(
+          loadingState: LoadState.State_Success,
+          maxHeight: 400.0,
+          dialogWidth: 345.0,
+          isShowConfirmBtn: false,
+          isShowCancelBtn: false,
+          confirmTxt: "Confirm",
+          title: "Confirm Information",
+          titleBackgroundColor: context.appColors.textPrimary,
+          closeIconColor: context.appColors.textWhite,
+          titleTextStyle: TextStyle(
+            color: context.appColors.textWhite,
+          ),
+          messageBuilder: (context) {
+            return const GetQuoteDialogContent();
+          },
+          bottomFooterBuilder: (context) {
+            return Padding(
+              padding: const EdgeInsets.only(bottom: 40),
+              child: MyButton(
+                onPressed: () {
+                  // 提交取消订单
+                  submitQuote(context, id);
+                },
+                text: "Confirm",
+                minWidth: 305,
+                minHeight: 45,
+                fontSize: 16,
+                fontWeight: FontWeight.w500,
+                backgroundColor: context.appColors.textPrimary,
+                textColor: context.appColors.textWhite,
+              ),
+            );
+          },
+          bottomBtnRadius: 10,
+          bottomBtnSpace: 5,
+          topLeftRadius: 10.0,
+          topRightRadius: 10.0,
+          bottomLeftRadius: 10.0,
+          bottomRightRadius: 10.0,
+          contentPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 20),
+          bottomBtnSectionPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 20),
+          cancelAction: () {
+            DialogEngine.dismiss(tag: 'getQuote');
+            clearUserNotesInput();
+          },
+          confirmAction: () {
+            clearUserNotesInput();
+          },
+        ));
   }
 
-  handlerClickQuoteBtn(BuildContext context, int id, int serviceTypeCode) async{
+  clearUserNotesInput() {
+    state = state.copyWith(
+      userNotes: "",
+      getQuoteFormData: {
+        "userNotes": {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': '',
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        }
+      },
+    );
+  }
+
+  Future submitQuote<T>(
+      BuildContext context, int id) async {
+    try {
+      Map<String, dynamic> params = {"service_id": id, "user_notes": getUserNotes()};
+      final result =
+          await serviceRespositoryInstance.fetchRepairServiceSubmit(params);
+      if (result.isSuccess) {
+        // 关闭 getQuote dialog
+        DialogEngine.dismiss(tag: 'getQuote');
+        // 弹出成功的提示dialog
+        handlerClickQuoteBtn(context, id);
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+  }
+
+  // 报价提交成功后的 提示dialog
+  handlerClickQuoteBtn(
+      BuildContext context, int id) async {
     await DialogEngine.show(
-        tag: "gotoQuote",
+        tag: "gotoQuoteSuccess",
         position: DialogPosition.center,
         widget: AppCustomDialog(
           message: '',
@@ -265,20 +380,21 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
           // contentBoxMinHeight: 300,
           isShowConfirmBtn: true,
           confirmTxt: "Confirm",
-          isShowCancelBtn:false,
-          messageBuilder: (BuildContext context){
+          isShowCancelBtn: false,
+          messageBuilder: (BuildContext context) {
             return Container(
-              padding: EdgeInsets.symmetric(horizontal: 30),
-              child: Column(
-                children: [
+                padding: EdgeInsets.symmetric(horizontal: 30),
+                child: Column(children: [
                   MyTextView(
-                    "Please select the category of the service you want to quote:",
+                    "We have received your quotation inquiry",
                     fontSize: 16,
                     isFontMedium: true,
                     textAlign: TextAlign.center,
                     textColor: ColorUtils.string2Color("#4161D0"),
                   ),
-                  SizedBox(height: 20,),
+                  const SizedBox(
+                    height: 20,
+                  ),
                   MyTextView(
                     "We will contact you as soon as possible. Please keep your phone open",
                     fontSize: 16,
@@ -287,15 +403,12 @@ class ServiceRepairDetailVm extends _$ServiceRepairDetailVm {
                     textColor: ColorUtils.string2Color("#000000"),
                     // textColor: context.appColors.textPrimary,
                   ),
-                ]
-              )
-            );
+                ]));
           },
-          confirmAction: (){
+          confirmAction: () {
             // 点击了确定
             Log.d("----点击了确定按钮");
           },
-        )
-    );
+        ));
   }
-}
+}

+ 1 - 1
packages/cpt_services/lib/modules/services/service_repair_detail/service_repair_detail_vm.g.dart

@@ -7,7 +7,7 @@ part of 'service_repair_detail_vm.dart';
 // **************************************************************************
 
 String _$serviceRepairDetailVmHash() =>
-    r'26e25c4041436aaefa8c3eb25a2921a7c3daeb7a';
+    r'2a6458bfaa88196839a05fd1ac64a32e77490a4c';
 
 /// See also [ServiceRepairDetailVm].
 @ProviderFor(ServiceRepairDetailVm)

+ 94 - 49
packages/cpt_services/lib/modules/services/services_main_page.dart

@@ -1,5 +1,7 @@
 
+import 'package:cpt_services/modules/services/services_main_vm.dart';
 import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/service_category_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -8,8 +10,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:plugin_basic/provider/user_config/user_config_service.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/ext_dart.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/custom_sliver_persistent_header_delegate.dart';
+import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_text_view.dart';
@@ -18,13 +22,10 @@ import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:widgets/widget_export.dart';
 
 import '../../router/page/services_page_router.dart';
-import 'inProgress/in_progress_page.dart';
-import 'repair/repair_page.dart';
-import 'services_page.dart';
 
 enum ServicesType {
-  cleaning,
-  repair,
+  paid,
+  inquiry,
 }
 
 
@@ -44,57 +45,108 @@ class ServicesMainPage extends HookConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-
-    useEffect(() {
-      // 监听窗口
-    }, []);
-
+    final vm = ref.read(serviceMainVmProvider.notifier);
+    final state = ref.watch(serviceMainVmProvider);
 
     useEffect(() {
       Log.d("ServicesMainPage initState");
-      // 延迟监听
-
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => vm.initPageData());
+      return () {
+        Log.d("ServicesMainPage dispose");
+      };
     }, []);
 
     return Scaffold(
       appBar: MyAppBar.appBar(
         context,
-        "ServicesMain",
+        "Service",
         backgroundColor: context.appColors.whiteBG,
       ),
       backgroundColor: ColorUtils.string2Color("#F2F3F6"),
-      body: Container(
-        child: GridView.count(
-          crossAxisCount: 2,
-          padding: EdgeInsets.all(10),
-          mainAxisSpacing: 10,
-          crossAxisSpacing: 10,
-          childAspectRatio: 165/146,
-          children: [
-            _buildServiceCard(
-              context,
-              ServicesType.cleaning,
-              Assets.serviceHomeServices,
-              "Home Services",
-              102.5,
-              82.5,
-              ServicesPage.startInstance,
-            ),
-            _buildServiceCard(
-              context,
-              ServicesType.repair,
-              Assets.serviceMaintenance,
-              "Maintenance",
-              129,
-              107.5,
-              RepairPage.startInstance,
+      body: Column(
+        children: [
+          Expanded(
+            child: EasyRefresh(
+              controller: vm.refreshController,
+              // 上拉加载
+              onLoad: null,
+              // 下拉刷新
+              onRefresh: () async{
+                Log.d("----onRefresh");
+                vm.onRefresh();
+              },
+              child: LoadStateLayout(
+                state: state.loadingState!,
+                errorMessage: state.errorMessage,
+                errorRetry: () {
+                  vm.retryRequest();
+                },
+                successSliverWidget:[
+                  SliverGrid(
+                    gridDelegate:  const SliverGridDelegateWithFixedCrossAxisCount(
+                      crossAxisCount: 2,
+                      mainAxisSpacing: 10,
+                      crossAxisSpacing: 5,
+                      childAspectRatio: 165/146, //宽高比
+                    ),
+                    delegate: SliverChildBuilderDelegate(
+                          (context, index) {
+                        return  Padding(
+                          padding: const EdgeInsets.all(10.0),
+                          child: _buildCardItem(context, ref, state.datas?[index] as ServiceCategoryEntity, vm).onTap((){
+                            final data = state.datas?[index] as ServiceCategoryEntity;
+                            if (data.id != null && data.type != null) {
+                              vm.goToPaidOrRepairListPage(context, data.id!, data.type!, data);
+                            }
+                          }),
+                        );
+                      },
+                      childCount: state.datas?.length,
+                    ),
+                  ),
+                ]
+              ),
             ),
-          ]
-        ),
+          ),
+        ],
       ),
     );
   }
 
+  Widget _buildCardItem(BuildContext context, WidgetRef ref, ServiceCategoryEntity data, ServiceMainVm vm){
+    if(data?.id == 1){
+      // home Services
+      return _buildServiceCard(
+        context,
+        ServicesType.paid,
+        Assets.serviceHomeServices,
+        "Home Services",
+        102.5,
+        82.5
+      );
+    }else if(data?.id == 4){
+        // maintenance
+        return _buildServiceCard(
+          context,
+          ServicesType.inquiry,
+          Assets.serviceMaintenance,
+          "Maintenance",
+          102.5,
+          82.5
+        );
+    }else {
+      return _buildServiceCard(
+        context,
+        ServicesType.paid,
+        Assets.serviceHomeServices,
+        "Home Services",
+        102.5,
+        82.5
+      );
+    }
+  }
+
   Widget _buildServiceCard(
     BuildContext context,
     ServicesType type,
@@ -102,7 +154,6 @@ class ServicesMainPage extends HookConsumerWidget {
     String title,
       double iconWidth,
       double iconHeight,
-    Function() onTap,
   ) {
     return Container(
       margin: EdgeInsets.all(10),
@@ -134,7 +185,7 @@ class ServicesMainPage extends HookConsumerWidget {
             child: Container(
               child: MyLoadImage(
                 imagePath,
-                fit: BoxFit.cover,
+                fit: BoxFit.fitWidth,
                 width: iconWidth,
                 height: iconHeight,
               ),
@@ -142,13 +193,7 @@ class ServicesMainPage extends HookConsumerWidget {
           )
         ]
       )
-    ).onTap((){
-      if(type == ServicesType.cleaning){
-        ServicesPage.startInstance();
-      }else if(type == ServicesType.repair){
-        RepairPage.startInstance();
-      }
-    });
+    );
   }
 }
 

+ 35 - 0
packages/cpt_services/lib/modules/services/services_main_state.dart

@@ -0,0 +1,35 @@
+import 'package:domain/entity/service_category_entity.dart';
+import 'package:widgets/load_state_layout.dart';
+
+class ServiceMainState {
+  //页面 LoadView 状态的展示
+  LoadState? loadingState;
+  String? errorMessage;
+
+  // getter curId
+  int? get curId => curCategory?.id;
+  final ServiceCategoryEntity? curCategory;
+
+  List<ServiceCategoryEntity>? datas;
+
+  ServiceMainState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    this.curCategory,
+    this.datas,
+  });
+
+  ServiceMainState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    ServiceCategoryEntity? curCategory,
+    List<ServiceCategoryEntity>? datas,
+  }) {
+    return ServiceMainState(
+      loadingState: loadingState ?? this.loadingState,
+      errorMessage: errorMessage ?? this.errorMessage,
+      curCategory: curCategory ?? this.curCategory,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 163 - 0
packages/cpt_services/lib/modules/services/services_main_vm.dart

@@ -0,0 +1,163 @@
+
+import 'dart:async';
+
+import 'package:cpt_services/modules/services/repair/repair_page.dart';
+import 'package:cpt_services/modules/services/services_page.dart';
+import 'package:domain/entity/service_category_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/ext_dart.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:widgets/dialog/dialog_content_wrap.dart';
+import '../../../respository/services_respository.dart';
+import '../../../router/page/services_page_router.dart';
+import 'services_main_page.dart';
+import 'services_main_state.dart';
+
+part 'services_main_vm.g.dart';
+
+
+@riverpod
+class ServiceMainVm extends _$ServiceMainVm {
+  late ServicesRespository serviceRespositoryInstance;
+
+  int _detailId = 0;
+  int _detailServiceTypeCode = 0;
+
+  bool _needShowPlaceholder = true; //是否展示LoadingView
+
+  int _page = 1;  // 当前页
+  int _limit = 10; // 每页数量
+  int _count = 0; // 总条数
+
+  int _totalnum = 130;
+
+  int totalnum = 50;
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  ServiceMainState initState() {
+    return ServiceMainState(
+      datas: null,
+    );
+  }
+
+  @override
+  ServiceMainState build(){
+    // 引入数据仓库
+    serviceRespositoryInstance = ref.read(servicesRespositoryProvider);
+    final state = initState();
+    Log.d("--------------------------build---------------------");
+
+    return state;
+  }
+
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(
+        loadingState: loadState,
+        errorMessage: errorMsg
+    );
+  }
+
+
+  // 初始化页面数据
+  initPageData() {
+    Log.d("----for_sale_vm-----initPageData   ${state.loadingState}");
+    onRefresh();
+  }
+
+  // 上拉加载 更多
+  Future loadMore() async {
+    _page++;
+    getServicesData();
+  }
+
+
+  // 下拉刷新
+  Future onRefresh() async {
+    _page = 1;
+    getServicesData();
+  }
+
+
+  // 手动进行刷新
+  Future triggerRefresh() async {
+    Log.d("trggerRefresh");
+    refreshController.callRefresh();
+  }
+
+  // 手动进行刷新
+  Future directRefresh() async {
+    state = state.copyWith(datas:null);
+    // 注意:由于 nestedscrollview 嵌套easyfresh 组件  refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口
+    // https://github.com/xuelongqy/flutter_easy_refresh/issues/692
+    refreshController.callRefresh();
+    refreshController.resetFooter();
+    _page = 1;
+    _needShowPlaceholder = true;
+    getServicesData();
+  }
+
+
+  // 重试请求
+  Future retryRequest() async {
+    _page = 1;
+    _needShowPlaceholder = true;
+    getServicesData();
+  }
+
+
+  Future getServicesData<T>() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    try {
+      Map<String, dynamic> params = {
+        "parent_id": null,
+      };
+      final result = await serviceRespositoryInstance.fetchServiceCateGoryList(params);
+      if(result.isSuccess){
+        state = state.copyWith(datas: result.list as List<ServiceCategoryEntity>);
+        changeLoadingState(LoadState.State_Success, null);
+        refreshController.finishRefresh();
+      } else {
+        String errorMessage = result.errorMsg!;
+        changeLoadingState(LoadState.State_Error, errorMessage);
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+
+
+    // // 最后赋值
+    _needShowPlaceholder = false;
+  }
+  
+  // 去付费服务/维修服务  列表页
+  goToPaidOrRepairListPage(BuildContext context, int id, String type, ServiceCategoryEntity entity){
+    state = state.copyWith(
+        curCategory: entity
+    );
+    if(id == 1){
+      ServicesPage.startInstance(parentCategoryId: 1);
+    }else if(id == 4){
+      RepairPage.startInstance(parentCategoryId: 4);
+    }else {
+      ToastEngine.show("暂未开放");
+    }
+  }
+}

+ 26 - 0
packages/cpt_services/lib/modules/services/services_main_vm.g.dart

@@ -0,0 +1,26 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'services_main_vm.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$serviceMainVmHash() => r'c23e9cdb4f2f2b504eb42420d8863f94ce105105';
+
+/// See also [ServiceMainVm].
+@ProviderFor(ServiceMainVm)
+final serviceMainVmProvider =
+    AutoDisposeNotifierProvider<ServiceMainVm, ServiceMainState>.internal(
+  ServiceMainVm.new,
+  name: r'serviceMainVmProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$serviceMainVmHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$ServiceMainVm = AutoDisposeNotifier<ServiceMainState>;
+// ignore_for_file: type=lint
+// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 17 - 11
packages/cpt_services/lib/modules/services/services_page.dart

@@ -27,14 +27,15 @@ final GlobalKey<ExtendedNestedScrollViewState> extendedNestedScrollViewKey =
 GlobalKey<ExtendedNestedScrollViewState>();
 @RoutePage()
 class ServicesPage extends HookConsumerWidget with WidgetsBindingObserver {
-  ServicesPage({Key? key}) : super(key: key);
+  int parentCategoryId = 0; //父级分类id
+  ServicesPage({Key? key, required this.parentCategoryId}) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context}) {
+  static void startInstance({BuildContext? context, required int parentCategoryId}) {
     if (context != null) {
-      context.router.push( ServicesPageRoute());
+      context.router.push( ServicesPageRoute(parentCategoryId:parentCategoryId));
     } else {
-      appRouter.push( ServicesPageRoute());
+      appRouter.push( ServicesPageRoute(parentCategoryId:parentCategoryId));
     }
   }
 
@@ -91,6 +92,8 @@ class ServicesPage extends HookConsumerWidget with WidgetsBindingObserver {
     final currentPageIdx = tabsRouterKey.currentState?.controller?.activeIndex ?? 0;
 
     useEffect(() {
+      vm.setInitPageData(context, parentCategoryId);
+
       // 监听窗口
       WidgetsBinding.instance.addObserver(this);
     }, []);
@@ -115,18 +118,21 @@ class ServicesPage extends HookConsumerWidget with WidgetsBindingObserver {
       };
     },[]);
 
+
     return Scaffold(
         appBar: MyAppBar.searchAppBar(
             context,
             value: vm.getCurrentQueryParams('keyword'),
             actions: [
-              const MyAssetImage(
-                Assets.serviceServiceScoreYes,
-                width: 21.5,
-                height: 21.5,
-              ).onTap((){
-                vm.handlerClickNavbarLikeBtn(context);
-              }),
+              (state.currentPageViewIdx == 0) ? Container(
+                 child: const MyAssetImage(
+                    Assets.serviceServiceScoreYes,
+                    width: 21.5,
+                    height: 21.5,
+                 ).onTap((){
+                    vm.handlerClickNavbarLikeBtn(context);
+                 }),
+               ):const SizedBox.shrink(),
               const SizedBox(width: 15),
             ],
             backgroundColor: context.appColors.backgroundWhite,

+ 5 - 1
packages/cpt_services/lib/modules/services/services_state.dart

@@ -3,12 +3,14 @@ import 'package:cs_resources/generated/assets.dart';
 
 class ServicesVmState {
   List<Map<String, dynamic>>? topSectionsData;
+
+  int? parentCategoryId;
   int currentPageViewIdx = 0;
   dynamic? tabsRouter;
 
-
   ServicesVmState({
     List<Map<String, dynamic>>? topSectionsData,
+    this.parentCategoryId,
     required this.currentPageViewIdx,
     this.tabsRouter,
   }) : topSectionsData = topSectionsData?? [
@@ -31,11 +33,13 @@ class ServicesVmState {
 
   ServicesVmState copyWith({
     List<Map<String, dynamic>>? topSectionsData,
+    int? parentCategoryId,
     int? currentPageViewIdx,
     dynamic? tabsRouter,
   }) {
     return ServicesVmState(
       topSectionsData: topSectionsData ?? this.topSectionsData,
+      parentCategoryId: parentCategoryId ?? this.parentCategoryId,
       currentPageViewIdx: currentPageViewIdx ?? this.currentPageViewIdx,
       tabsRouter: tabsRouter ?? this.tabsRouter,
     );

+ 18 - 1
packages/cpt_services/lib/modules/services/services_vm.dart

@@ -1,4 +1,7 @@
 
+import 'package:cpt_services/modules/services/history/history_vm.dart';
+import 'package:cpt_services/modules/services/homeService/home_service_vm.dart';
+import 'package:cpt_services/modules/services/inProgress/in_progress_vm.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/cupertino.dart';
@@ -23,6 +26,9 @@ part 'services_vm.g.dart';
 
 @riverpod
 class ServicesVm extends _$ServicesVm {
+
+  late int _parentCategoryId;
+
   get topSectionsData => state.topSectionsData;
   late ServicesRespository servicesRespositoryInstance;
   late Map<int, dynamic> providerMap = {};
@@ -78,6 +84,15 @@ class ServicesVm extends _$ServicesVm {
     return state;
   }
 
+  setInitPageData(BuildContext context, int parentCategoryId){
+    _parentCategoryId = parentCategoryId;
+    WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
+      state = state.copyWith(
+        parentCategoryId: parentCategoryId,
+      );
+    });
+  }
+
   // 搜集pageView 对应的vm
   void getPageViewVm(){
     // 每次切换后需要重新获取 一组 pageView的 vm
@@ -86,9 +101,11 @@ class ServicesVm extends _$ServicesVm {
       ServicesPageviewIdxData.values.forEach((key, value) {
         switch(key){
           case 0:
+            providerMap[key] = ref.read(homeServiceVmProvider.notifier);
           case 1:
+            providerMap[key] = ref.read(inProgressVmProvider.notifier);
           case 2:
-          // providerMap[key] = ref.read(forrentVmProvider.notifier);
+          providerMap[key] = ref.read(historyVmProvider.notifier);
         }
       });
     });

+ 1 - 1
packages/cpt_services/lib/modules/services/services_vm.g.dart

@@ -6,7 +6,7 @@ part of 'services_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$servicesVmHash() => r'7805f3c3765a93ec9b488e6e288a5baa346ba2ed';
+String _$servicesVmHash() => r'960eacf01f767979f64ce3c1e026549f5cfda0f4';
 
 /// See also [ServicesVm].
 @ProviderFor(ServicesVm)

+ 210 - 194
packages/cpt_services/lib/respository/services_respository.dart

@@ -1,10 +1,21 @@
 import 'package:domain/constants/api_constants.dart';
+import 'package:domain/entity/garage_sale_history_entity.dart';
 import 'package:domain/entity/garage_sale_rent_detail_entity.dart';
 import 'package:domain/entity/garage_sale_rent_entity.dart';
 import 'package:domain/entity/myposts_sale_rent_entity.dart';
 import 'package:domain/entity/newsfeed_foryou_entity.dart';
 import 'package:domain/entity/newsfeed_news_entity.dart';
+import 'package:domain/entity/paid_service_detail_entity.dart';
+import 'package:domain/entity/paid_service_entity.dart';
+import 'package:domain/entity/paid_service_pay_success_info_entity.dart';
+import 'package:domain/entity/repair_service_entity.dart';
 import 'package:domain/entity/server_time.dart';
+import 'package:domain/entity/service_category_entity.dart';
+import 'package:domain/entity/service_in_progress_entity.dart';
+import 'package:domain/entity/service_time_period_entity.dart';
+import 'package:domain/entity/service_order_detail_entity.dart';
+import 'package:domain/entity/service_evaluate_list_entity.dart';
+import 'package:domain/entity/service_repair_detail_entity.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/platform_export.dart';
 import 'package:plugin_platform/http/dio_engine.dart';
@@ -16,7 +27,6 @@ import 'package:shared/utils/util.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:plugin_basic/provider/http_provider/http_provider.dart';
 
-
 part 'services_respository.g.dart';
 
 @Riverpod(keepAlive: true)
@@ -35,9 +45,9 @@ class ServicesRespository {
 
   //服务 获取 分类 字典
   Future<HttpResult<Object>> fetchServiceCateGoryList(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -50,20 +60,22 @@ class ServicesRespository {
       params: params,
       headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: true,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
     //根据返回的结果,封装原始数据为Bean/Entity对象
     if (result.isSuccess) {
       //重新赋值data或list
-      final json = result.getDataJson();
-      // var data = NewsfeedForyouEntity.fromJson(json!);
+      final listJson = result.getListJson();
+      var listData = listJson!.map((e) => ServiceCategoryEntity.fromJson(e!)).toList();
       //重新赋值data或list
-      return result.convert(data: json);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+      return result.convert(list: listData);
+    }else  {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
@@ -72,9 +84,9 @@ class ServicesRespository {
 
   // 付费服务 获取 列表
   Future<HttpResult<Object>> fetchPaidServiceDataList(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -82,13 +94,14 @@ class ServicesRespository {
     headers["Accept"] = "application/x.yyjobs-api.v1+json";
 
     final result = await dioEngine.requestNetResult(
-      // ApiConstants.apiServerTime, // api 地址
       '/api/v1/user/service/paid-service/index', // api 地址
       params: params,
       headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
@@ -96,60 +109,58 @@ class ServicesRespository {
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      var data = GarageSaleRentEntity.fromJson(json!);
+      var data = PaidServiceEntity.fromJson(json!);
       //重新赋值data或list
       return result.convert(data: data);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
     return result.convert();
   }
 
-
   // 付费/维修 服务 列表 点赞/取消点赞
   Future<HttpResult<Object>> fetchServiceLiked(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
-    headers["Content-Type"] = "application/x-www-form-urlencoded";
-    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+    // headers["Content-Type"] = "application/x-www-form-urlencoded";
+    // headers["Accept"] = "application/x.yyjobs-api.v1+json";
 
     final result = await dioEngine.requestNetResult(
-      // ApiConstants.apiServerTime, // api 地址
-      '/api/v1/user/service/paid-service/liked', // api 地址
+      '/api/v1/user/service/like/click', // api 地址
       params: params,
       headers: headers,
       method: HttpMethod.POST,
-      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: true,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
     //根据返回的结果,封装原始数据为Bean/Entity对象
     if (result.isSuccess) {
       //重新赋值data或list
-      final json = result.getDataDynamic();
-      // var data = NewsfeedForyouEntity.fromJson(json!);
+      final boolData = result.getDataDynamic();
       //重新赋值data或list
-      return result.convert(data: json);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+      return result.convert(data: boolData);
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
     return result.convert();
   }
 
-
   // 提交评价
   Future<HttpResult<Object>> fetchPublishEvaluation(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -174,8 +185,10 @@ class ServicesRespository {
       paths: files,
       headers: headers,
       method: HttpMethod.POST,
-      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: true,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
     //根据返回的结果,封装原始数据为Bean/Entity对象
@@ -185,20 +198,19 @@ class ServicesRespository {
       // var data = NewsfeedForyouEntity.fromJson(json!);
       //重新赋值data或list
       return result.convert(data: json);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
     return result.convert();
   }
 
-
   // 评价列表
   Future<HttpResult<Object>> fetchEvaluationDataList(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -211,8 +223,10 @@ class ServicesRespository {
       params: params,
       headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
@@ -220,11 +234,11 @@ class ServicesRespository {
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      var data = GarageSaleRentEntity.fromJson(json!);
+      var data = ServiceEvaluateListEntity.fromJson(json!);
       //重新赋值data或list
       return result.convert(data: data);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
@@ -233,9 +247,9 @@ class ServicesRespository {
 
   // 获取 付费服务 详情信息
   Future<HttpResult<Object>> fetchPaidServiceCleanDetailInfo(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -243,13 +257,14 @@ class ServicesRespository {
     // headers["Accept"] = "application/x.yyjobs-api.v1+json";
 
     final result = await dioEngine.requestNetResult(
-      // ApiConstants.apiServerTime, // api 地址
       '/api/v1/user/service/paid-service/detail', // api 地址
       params: params,
       headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
@@ -257,9 +272,9 @@ class ServicesRespository {
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      // var data = GarageSaleRentDetailEntity.fromJson(json!);
+      var data = PaidServiceDetailEntity.fromJson(json!);
       //重新赋值data或list
-      return result.convert(data: json);
+      return result.convert(data: data);
     }else {
       if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
         ToastEngine.show("${result.errorMsg}");
@@ -268,34 +283,34 @@ class ServicesRespository {
     return result.convert();
   }
 
-  // 付费服务 下单
-  Future<HttpResult<Object>> fetchPaidServiceBook(
+  // 获取 付费服务 时间段
+  Future<HttpResult<Object>> fetchPaidServiceTimePeriod(
       Map<String, dynamic>? data, {
         CancelToken? cancelToken,
       }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
-    headers["Content-Type"] = "application/x-www-form-urlencoded";
-    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+    // headers["Content-Type"] = "application/x-www-form-urlencoded";
+    // headers["Accept"] = "application/x.yyjobs-api.v1+json";
 
     final result = await dioEngine.requestNetResult(
-      // ApiConstants.apiServerTime, // api 地址
-      '/api/v1/user/service/paid-service-order/book', // api 地址
+      '/api/v1/user/service/paid-service/time-period', // api 地址
       params: params,
       headers: headers,
-      method: HttpMethod.POST,
-      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      method: HttpMethod.GET,
+      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
+      networkDebounce: false,   //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
+
     //根据返回的结果,封装原始数据为Bean/Entity对象
     if (result.isSuccess) {
       //重新赋值data或list
-      final json = result.getDataJson();
-      // var data = NewsfeedForyouEntity.fromJson(json!);
+      final list = result.getListJson();
+      List<ServiceTimePeriodEntity> listEntity= list!.map((e)=>ServiceTimePeriodEntity.fromJson(e)).toList();
       //重新赋值data或list
-      return result.convert(data: json);
+      return result.convert(list: listEntity);
     }else {
       if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
         ToastEngine.show("${result.errorMsg}");
@@ -304,12 +319,11 @@ class ServicesRespository {
     return result.convert();
   }
 
-
-  // 付费服务  订单列表
-  Future<HttpResult<Object>> fetchPaidServiceOrderList(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+  // 付费服务 下单
+  Future<HttpResult<Object>> fetchPaidServiceBook(
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -318,74 +332,93 @@ class ServicesRespository {
 
     final result = await dioEngine.requestNetResult(
       // ApiConstants.apiServerTime, // api 地址
-      '/api/v1/user/service/paid-service-order/index', // api 地址
+      '/api/v1/user/service/paid-service-order/book', // api 地址
       params: params,
       headers: headers,
-      method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      method: HttpMethod.POST,
+      isShowLoadingDialog: true,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
-
     //根据返回的结果,封装原始数据为Bean/Entity对象
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      var data = GarageSaleRentEntity.fromJson(json!);
+      var data = PaidServicePaySuccessInfoEntity.fromJson(json!);
       //重新赋值data或list
-      return result.convert(data: data);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+      return result.convert(data: json);
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
     return result.convert();
   }
 
+  // 付费服务  订单列表
+  Future<HttpResult<GarageSaleHistoryEntity>> fetchPaidServiceOrderList({
+    required String type,
+    required int curPage,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['type'] = type;
+    params['page'] = curPage.toString();
+    params['limit'] = "10";
+
+    final result = await dioEngine.requestNetResult(
+      '/api/v1/user/service/paid-service-order/index',
+      params: params,
+      method: HttpMethod.GET,
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = GarageSaleHistoryEntity.fromJson(json!);
+      return result.convert<GarageSaleHistoryEntity>(data: data);
+    }
+    return result.convert();
+  }
 
   // 获取 付费服务 订单详情
-  Future<HttpResult<Object>> fetchPaidServiceCleanOrderDetailInfo(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+  Future<HttpResult<ServiceOrderDetailEntity>> fetchPaidServiceCleanOrderDetail({
+    required String id,
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
-    params = data!;
-    Map<String, String> headers = {};
-    // headers["Content-Type"] = "application/x-www-form-urlencoded";
-    // headers["Accept"] = "application/x.yyjobs-api.v1+json";
+    params['id'] = id;
 
     final result = await dioEngine.requestNetResult(
-      // ApiConstants.apiServerTime, // api 地址
-      '/api/v1/user/service/paid-service-order/detail', // api 地址
+      '/api/v1/user/service/paid-service-order/detail',
       params: params,
-      headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
-    //根据返回的结果,封装原始数据为Bean/Entity对象
     if (result.isSuccess) {
-      //重新赋值data或list
       final json = result.getDataJson();
-      // var data = GarageSaleRentDetailEntity.fromJson(json!);
-      //重新赋值data或list
-      return result.convert(data: json);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
-        ToastEngine.show("${result.errorMsg}");
-      }
+      var data = ServiceOrderDetailEntity.fromJson(json!);
+      return result.convert<ServiceOrderDetailEntity>(data: data);
     }
     return result.convert();
   }
 
-
   // 获取 付费订单实际需要支付的价格
   Future<HttpResult<Object>> fetchPaidServiceCleanOrderPrice(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -398,8 +431,10 @@ class ServicesRespository {
       params: params,
       headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
@@ -410,60 +445,46 @@ class ServicesRespository {
       // var data = GarageSaleRentDetailEntity.fromJson(json!);
       //重新赋值data或list
       return result.convert(data: json);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
     return result.convert();
   }
 
-
   // 付费服务 取消订单
-  Future<HttpResult<Object>> fetchCancelPaidServiceOrder(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
-    Map<String, dynamic> params = {};
-    params = data!;
-    Map<String, String> headers = {};
-    headers["Content-Type"] = "application/x-www-form-urlencoded";
-    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+  Future<HttpResult> fetchCancelPaidServiceOrder({
+    required String? id,
+    required String? reason,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['id'] = id ?? "";
+    params['cancel_reason'] = reason ?? "";
 
     final result = await dioEngine.requestNetResult(
-      // ApiConstants.apiServerTime, // api 地址
-      '/api/v1/user/service/paid-service-order/cancel', // api 地址
+      '/api/v1/user/service/paid-service-order/cancel',
       params: params,
-      headers: headers,
       method: HttpMethod.POST,
-      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: true,
+      networkDebounce: true,
       cancelToken: cancelToken,
     );
-    //根据返回的结果,封装原始数据为Bean/Entity对象
+
     if (result.isSuccess) {
-      //重新赋值data或list
-      final json = result.getDataJson();
-      // var data = NewsfeedForyouEntity.fromJson(json!);
-      //重新赋值data或list
-      return result.convert(data: json);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
-        ToastEngine.show("${result.errorMsg}");
-      }
+      return result.convert();
     }
     return result.convert();
   }
 
-
   ///-------------------咨询类---------------------------------
 
-
   // 维修服务  列表
   Future<HttpResult<Object>> fetchRepairServiceList(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -476,8 +497,10 @@ class ServicesRespository {
       params: params,
       headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
@@ -485,11 +508,11 @@ class ServicesRespository {
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      var data = GarageSaleRentEntity.fromJson(json!);
+      var data = RepairServiceEntity.fromJson(json!);
       //重新赋值data或list
       return result.convert(data: data);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
@@ -498,9 +521,9 @@ class ServicesRespository {
 
   // 获取 repair 详情信息
   Future<HttpResult<Object>> fetchServiceRepairDetailInfo(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -513,8 +536,10 @@ class ServicesRespository {
       params: params,
       headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
@@ -522,23 +547,22 @@ class ServicesRespository {
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      var data = GarageSaleRentDetailEntity.fromJson(json!);
+      var data = ServiceRepairDetailEntity.fromJson(json!);
       //重新赋值data或list
       return result.convert(data: data);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
     return result.convert();
   }
 
-
   // 维修服务 提交咨询
   Future<HttpResult<Object>> fetchRepairServiceSubmit(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
+    Map<String, dynamic>? data, {
+    CancelToken? cancelToken,
+  }) async {
     Map<String, dynamic> params = {};
     params = data!;
     Map<String, String> headers = {};
@@ -551,8 +575,10 @@ class ServicesRespository {
       params: params,
       headers: headers,
       method: HttpMethod.POST,
-      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: true,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
     //根据返回的结果,封装原始数据为Bean/Entity对象
@@ -562,51 +588,41 @@ class ServicesRespository {
       // var data = NewsfeedForyouEntity.fromJson(json!);
       //重新赋值data或list
       return result.convert(data: json);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
+    } else {
+      if (result.errorMsg != null && result.errorMsg!.isNotEmpty) {
         ToastEngine.show("${result.errorMsg}");
       }
     }
     return result.convert();
   }
 
-
   // 维修服务  订单列表
-  Future<HttpResult<Object>> fetchRepairServiceOrderList(
-      Map<String, dynamic>? data, {
-        CancelToken? cancelToken,
-      }) async {
-    Map<String, dynamic> params = {};
-    params = data!;
-    Map<String, String> headers = {};
-    headers["Content-Type"] = "application/x-www-form-urlencoded";
-    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+  Future<HttpResult<ServiceInProgressEntity>> fetchRepairServiceOrderList({
+    required int status,
+    required int curPage,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['status'] = status.toString();
+    params['page'] = curPage.toString();
+    params['limit'] = "10";
 
     final result = await dioEngine.requestNetResult(
-      // ApiConstants.apiServerTime, // api 地址
-      '/api/v1/user/service/inquiry-service-order/index', // api 地址
+      '/api/v1/user/service/inquiry-service-order/index',
       params: params,
-      headers: headers,
       method: HttpMethod.GET,
-      isShowLoadingDialog: false,  //是否展示默认的Loading弹窗
-      networkDebounce: true,   //是否防抖防止重复请求
+      isShowLoadingDialog: false,
+      //是否展示默认的Loading弹窗
+      networkDebounce: true,
+      //是否防抖防止重复请求
       cancelToken: cancelToken,
     );
 
-    //根据返回的结果,封装原始数据为Bean/Entity对象
     if (result.isSuccess) {
-      //重新赋值data或list
       final json = result.getDataJson();
-      var data = GarageSaleRentEntity.fromJson(json!);
-      //重新赋值data或list
-      return result.convert(data: data);
-    }else {
-      if(result.errorMsg != null && result.errorMsg!.isNotEmpty){
-        ToastEngine.show("${result.errorMsg}");
-      }
+      var data = ServiceInProgressEntity.fromJson(json!);
+      return result.convert<ServiceInProgressEntity>(data: data);
     }
     return result.convert();
   }
-
-
 }

+ 93 - 99
packages/cpt_services/lib/router/page/services_page_router.gr.dart

@@ -26,7 +26,7 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
       final args = routeData.argsAs<CleanOrderDetailPageRouteArgs>(
           orElse: () => CleanOrderDetailPageRouteArgs(
                 id: pathParams.getInt('id'),
-                serviceTypeCode: pathParams.getInt('serviceTypeCode'),
+                cleanServiceType: pathParams.getString('cleanServiceType'),
                 serviesStatusCode: pathParams.getInt('serviesStatusCode'),
               ));
       return AutoRoutePage<dynamic>(
@@ -34,7 +34,7 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
         child: CleanOrderDetailPage(
           key: args.key,
           id: args.id,
-          serviceTypeCode: args.serviceTypeCode,
+          cleanServiceType: args.cleanServiceType,
           serviesStatusCode: args.serviesStatusCode,
         ),
       );
@@ -82,26 +82,25 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
       );
     },
     RepairPageRoute.name: (routeData) {
-      final args = routeData.argsAs<RepairPageRouteArgs>(
-          orElse: () => const RepairPageRouteArgs());
+      final args = routeData.argsAs<RepairPageRouteArgs>();
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: RepairPage(key: args.key),
+        child: RepairPage(
+          key: args.key,
+          parentCategoryId: args.parentCategoryId,
+        ),
       );
     },
     ServiceCleanDetailPageRoute.name: (routeData) {
-      final pathParams = routeData.inheritedPathParams;
-      final args = routeData.argsAs<ServiceCleanDetailPageRouteArgs>(
-          orElse: () => ServiceCleanDetailPageRouteArgs(
-                id: pathParams.getInt('id'),
-                serviceTypeCode: pathParams.getInt('serviceTypeCode'),
-              ));
+      final args = routeData.argsAs<ServiceCleanDetailPageRouteArgs>();
       return AutoRoutePage<dynamic>(
         routeData: routeData,
         child: ServiceCleanDetailPage(
           key: args.key,
           id: args.id,
-          serviceTypeCode: args.serviceTypeCode,
+          cleanServiceType: args.cleanServiceType,
+          liked: args.liked,
+          likesCount: args.likesCount,
         ),
       );
     },
@@ -112,7 +111,7 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
         child: ServiceEvaluateCreatePage(
           key: args.key,
           id: args.id,
-          serviceTypeCode: args.serviceTypeCode,
+          cleanServiceType: args.cleanServiceType,
         ),
       );
     },
@@ -123,7 +122,7 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
         child: ServiceEvaluateListPage(
           key: args.key,
           id: args.id,
-          serviceTypeCode: args.serviceTypeCode,
+          cleanServiceType: args.cleanServiceType,
         ),
       );
     },
@@ -134,19 +133,14 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
         child: ServiceOrderConfirmPage(
           key: args.key,
           id: args.id,
-          serviceTypeCode: args.serviceTypeCode,
+          cleanServiceType: args.cleanServiceType,
         ),
       );
     },
     ServicePaySuccessPageRoute.name: (routeData) {
-      final args = routeData.argsAs<ServicePaySuccessPageRouteArgs>();
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: ServicePaySuccessPage(
-          key: args.key,
-          id: args.id,
-          serviceTypeCode: args.serviceTypeCode,
-        ),
+        child: const ServicePaySuccessPage(),
       );
     },
     ServiceRepairDetailPageRoute.name: (routeData) {
@@ -154,14 +148,14 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
       final args = routeData.argsAs<ServiceRepairDetailPageRouteArgs>(
           orElse: () => ServiceRepairDetailPageRouteArgs(
                 id: pathParams.getInt('id'),
-                serviceTypeCode: pathParams.getInt('serviceTypeCode'),
+                cleanServiceType: pathParams.optString('cleanServiceType'),
               ));
       return AutoRoutePage<dynamic>(
         routeData: routeData,
         child: ServiceRepairDetailPage(
           key: args.key,
           id: args.id,
-          serviceTypeCode: args.serviceTypeCode,
+          cleanServiceType: args.cleanServiceType,
         ),
       );
     },
@@ -174,11 +168,13 @@ abstract class _$ServicesPageRouter extends RootStackRouter {
       );
     },
     ServicesPageRoute.name: (routeData) {
-      final args = routeData.argsAs<ServicesPageRouteArgs>(
-          orElse: () => const ServicesPageRouteArgs());
+      final args = routeData.argsAs<ServicesPageRouteArgs>();
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: ServicesPage(key: args.key),
+        child: ServicesPage(
+          key: args.key,
+          parentCategoryId: args.parentCategoryId,
+        ),
       );
     },
   };
@@ -205,7 +201,7 @@ class CleanOrderDetailPageRoute
   CleanOrderDetailPageRoute({
     Key? key,
     required int id,
-    required int serviceTypeCode,
+    required String cleanServiceType,
     required int serviesStatusCode,
     List<PageRouteInfo>? children,
   }) : super(
@@ -213,12 +209,12 @@ class CleanOrderDetailPageRoute
           args: CleanOrderDetailPageRouteArgs(
             key: key,
             id: id,
-            serviceTypeCode: serviceTypeCode,
+            cleanServiceType: cleanServiceType,
             serviesStatusCode: serviesStatusCode,
           ),
           rawPathParams: {
             'id': id,
-            'serviceTypeCode': serviceTypeCode,
+            'cleanServiceType': cleanServiceType,
             'serviesStatusCode': serviesStatusCode,
           },
           initialChildren: children,
@@ -234,7 +230,7 @@ class CleanOrderDetailPageRouteArgs {
   const CleanOrderDetailPageRouteArgs({
     this.key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
     required this.serviesStatusCode,
   });
 
@@ -242,13 +238,13 @@ class CleanOrderDetailPageRouteArgs {
 
   final int id;
 
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
   final int serviesStatusCode;
 
   @override
   String toString() {
-    return 'CleanOrderDetailPageRouteArgs{key: $key, id: $id, serviceTypeCode: $serviceTypeCode, serviesStatusCode: $serviesStatusCode}';
+    return 'CleanOrderDetailPageRouteArgs{key: $key, id: $id, cleanServiceType: $cleanServiceType, serviesStatusCode: $serviesStatusCode}';
   }
 }
 
@@ -355,10 +351,14 @@ class RepairInProgressPageRoute extends PageRouteInfo<void> {
 class RepairPageRoute extends PageRouteInfo<RepairPageRouteArgs> {
   RepairPageRoute({
     Key? key,
+    required int parentCategoryId,
     List<PageRouteInfo>? children,
   }) : super(
           RepairPageRoute.name,
-          args: RepairPageRouteArgs(key: key),
+          args: RepairPageRouteArgs(
+            key: key,
+            parentCategoryId: parentCategoryId,
+          ),
           initialChildren: children,
         );
 
@@ -369,13 +369,18 @@ class RepairPageRoute extends PageRouteInfo<RepairPageRouteArgs> {
 }
 
 class RepairPageRouteArgs {
-  const RepairPageRouteArgs({this.key});
+  const RepairPageRouteArgs({
+    this.key,
+    required this.parentCategoryId,
+  });
 
   final Key? key;
 
+  final int parentCategoryId;
+
   @override
   String toString() {
-    return 'RepairPageRouteArgs{key: $key}';
+    return 'RepairPageRouteArgs{key: $key, parentCategoryId: $parentCategoryId}';
   }
 }
 
@@ -386,18 +391,22 @@ class ServiceCleanDetailPageRoute
   ServiceCleanDetailPageRoute({
     Key? key,
     required int id,
-    required int serviceTypeCode,
+    required String cleanServiceType,
+    required bool liked,
+    required int likesCount,
     List<PageRouteInfo>? children,
   }) : super(
           ServiceCleanDetailPageRoute.name,
           args: ServiceCleanDetailPageRouteArgs(
             key: key,
             id: id,
-            serviceTypeCode: serviceTypeCode,
+            cleanServiceType: cleanServiceType,
+            liked: liked,
+            likesCount: likesCount,
           ),
           rawPathParams: {
             'id': id,
-            'serviceTypeCode': serviceTypeCode,
+            'cleanServiceType': cleanServiceType,
           },
           initialChildren: children,
         );
@@ -412,18 +421,24 @@ class ServiceCleanDetailPageRouteArgs {
   const ServiceCleanDetailPageRouteArgs({
     this.key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
+    required this.liked,
+    required this.likesCount,
   });
 
   final Key? key;
 
   final int id;
 
-  final int serviceTypeCode;
+  final String cleanServiceType;
+
+  final bool liked;
+
+  final int likesCount;
 
   @override
   String toString() {
-    return 'ServiceCleanDetailPageRouteArgs{key: $key, id: $id, serviceTypeCode: $serviceTypeCode}';
+    return 'ServiceCleanDetailPageRouteArgs{key: $key, id: $id, cleanServiceType: $cleanServiceType, liked: $liked, likesCount: $likesCount}';
   }
 }
 
@@ -434,14 +449,14 @@ class ServiceEvaluateCreatePageRoute
   ServiceEvaluateCreatePageRoute({
     Key? key,
     required int id,
-    required int serviceTypeCode,
+    required String cleanServiceType,
     List<PageRouteInfo>? children,
   }) : super(
           ServiceEvaluateCreatePageRoute.name,
           args: ServiceEvaluateCreatePageRouteArgs(
             key: key,
             id: id,
-            serviceTypeCode: serviceTypeCode,
+            cleanServiceType: cleanServiceType,
           ),
           initialChildren: children,
         );
@@ -456,18 +471,18 @@ class ServiceEvaluateCreatePageRouteArgs {
   const ServiceEvaluateCreatePageRouteArgs({
     this.key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
   });
 
   final Key? key;
 
   final int id;
 
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
   @override
   String toString() {
-    return 'ServiceEvaluateCreatePageRouteArgs{key: $key, id: $id, serviceTypeCode: $serviceTypeCode}';
+    return 'ServiceEvaluateCreatePageRouteArgs{key: $key, id: $id, cleanServiceType: $cleanServiceType}';
   }
 }
 
@@ -478,14 +493,14 @@ class ServiceEvaluateListPageRoute
   ServiceEvaluateListPageRoute({
     Key? key,
     required int id,
-    required int serviceTypeCode,
+    required String cleanServiceType,
     List<PageRouteInfo>? children,
   }) : super(
           ServiceEvaluateListPageRoute.name,
           args: ServiceEvaluateListPageRouteArgs(
             key: key,
             id: id,
-            serviceTypeCode: serviceTypeCode,
+            cleanServiceType: cleanServiceType,
           ),
           initialChildren: children,
         );
@@ -500,18 +515,18 @@ class ServiceEvaluateListPageRouteArgs {
   const ServiceEvaluateListPageRouteArgs({
     this.key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
   });
 
   final Key? key;
 
   final int id;
 
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
   @override
   String toString() {
-    return 'ServiceEvaluateListPageRouteArgs{key: $key, id: $id, serviceTypeCode: $serviceTypeCode}';
+    return 'ServiceEvaluateListPageRouteArgs{key: $key, id: $id, cleanServiceType: $cleanServiceType}';
   }
 }
 
@@ -522,14 +537,14 @@ class ServiceOrderConfirmPageRoute
   ServiceOrderConfirmPageRoute({
     Key? key,
     required int id,
-    required int serviceTypeCode,
+    required String cleanServiceType,
     List<PageRouteInfo>? children,
   }) : super(
           ServiceOrderConfirmPageRoute.name,
           args: ServiceOrderConfirmPageRouteArgs(
             key: key,
             id: id,
-            serviceTypeCode: serviceTypeCode,
+            cleanServiceType: cleanServiceType,
           ),
           initialChildren: children,
         );
@@ -544,63 +559,33 @@ class ServiceOrderConfirmPageRouteArgs {
   const ServiceOrderConfirmPageRouteArgs({
     this.key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
   });
 
   final Key? key;
 
   final int id;
 
-  final int serviceTypeCode;
+  final String cleanServiceType;
 
   @override
   String toString() {
-    return 'ServiceOrderConfirmPageRouteArgs{key: $key, id: $id, serviceTypeCode: $serviceTypeCode}';
+    return 'ServiceOrderConfirmPageRouteArgs{key: $key, id: $id, cleanServiceType: $cleanServiceType}';
   }
 }
 
 /// generated route for
 /// [ServicePaySuccessPage]
-class ServicePaySuccessPageRoute
-    extends PageRouteInfo<ServicePaySuccessPageRouteArgs> {
-  ServicePaySuccessPageRoute({
-    Key? key,
-    required int id,
-    required int serviceTypeCode,
-    List<PageRouteInfo>? children,
-  }) : super(
+class ServicePaySuccessPageRoute extends PageRouteInfo<void> {
+  const ServicePaySuccessPageRoute({List<PageRouteInfo>? children})
+      : super(
           ServicePaySuccessPageRoute.name,
-          args: ServicePaySuccessPageRouteArgs(
-            key: key,
-            id: id,
-            serviceTypeCode: serviceTypeCode,
-          ),
           initialChildren: children,
         );
 
   static const String name = 'ServicePaySuccessPageRoute';
 
-  static const PageInfo<ServicePaySuccessPageRouteArgs> page =
-      PageInfo<ServicePaySuccessPageRouteArgs>(name);
-}
-
-class ServicePaySuccessPageRouteArgs {
-  const ServicePaySuccessPageRouteArgs({
-    this.key,
-    required this.id,
-    required this.serviceTypeCode,
-  });
-
-  final Key? key;
-
-  final int id;
-
-  final int serviceTypeCode;
-
-  @override
-  String toString() {
-    return 'ServicePaySuccessPageRouteArgs{key: $key, id: $id, serviceTypeCode: $serviceTypeCode}';
-  }
+  static const PageInfo<void> page = PageInfo<void>(name);
 }
 
 /// generated route for
@@ -610,18 +595,18 @@ class ServiceRepairDetailPageRoute
   ServiceRepairDetailPageRoute({
     Key? key,
     required int id,
-    required int serviceTypeCode,
+    required String? cleanServiceType,
     List<PageRouteInfo>? children,
   }) : super(
           ServiceRepairDetailPageRoute.name,
           args: ServiceRepairDetailPageRouteArgs(
             key: key,
             id: id,
-            serviceTypeCode: serviceTypeCode,
+            cleanServiceType: cleanServiceType,
           ),
           rawPathParams: {
             'id': id,
-            'serviceTypeCode': serviceTypeCode,
+            'cleanServiceType': cleanServiceType,
           },
           initialChildren: children,
         );
@@ -636,18 +621,18 @@ class ServiceRepairDetailPageRouteArgs {
   const ServiceRepairDetailPageRouteArgs({
     this.key,
     required this.id,
-    required this.serviceTypeCode,
+    required this.cleanServiceType,
   });
 
   final Key? key;
 
   final int id;
 
-  final int serviceTypeCode;
+  final String? cleanServiceType;
 
   @override
   String toString() {
-    return 'ServiceRepairDetailPageRouteArgs{key: $key, id: $id, serviceTypeCode: $serviceTypeCode}';
+    return 'ServiceRepairDetailPageRouteArgs{key: $key, id: $id, cleanServiceType: $cleanServiceType}';
   }
 }
 
@@ -685,10 +670,14 @@ class ServicesMainPageRouteArgs {
 class ServicesPageRoute extends PageRouteInfo<ServicesPageRouteArgs> {
   ServicesPageRoute({
     Key? key,
+    required int parentCategoryId,
     List<PageRouteInfo>? children,
   }) : super(
           ServicesPageRoute.name,
-          args: ServicesPageRouteArgs(key: key),
+          args: ServicesPageRouteArgs(
+            key: key,
+            parentCategoryId: parentCategoryId,
+          ),
           initialChildren: children,
         );
 
@@ -699,12 +688,17 @@ class ServicesPageRoute extends PageRouteInfo<ServicesPageRouteArgs> {
 }
 
 class ServicesPageRouteArgs {
-  const ServicesPageRouteArgs({this.key});
+  const ServicesPageRouteArgs({
+    this.key,
+    required this.parentCategoryId,
+  });
 
   final Key? key;
 
+  final int parentCategoryId;
+
   @override
   String toString() {
-    return 'ServicesPageRouteArgs{key: $key}';
+    return 'ServicesPageRouteArgs{key: $key, parentCategoryId: $parentCategoryId}';
   }
 }

+ 75 - 0
packages/cs_domain/lib/entity/garage_sale_history_entity.dart

@@ -0,0 +1,75 @@
+import 'package:domain/entity/id_name_entity.dart';
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/garage_sale_history_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/garage_sale_history_entity.g.dart';
+
+@JsonSerializable()
+class GarageSaleHistoryEntity {
+	int count = 0;
+	int page = 0;
+	int limit = 0;
+	@JSONField(name: "count_page")
+	int countPage = 0;
+	List<GarageSaleHistoryList> list = [];
+
+	GarageSaleHistoryEntity();
+
+	factory GarageSaleHistoryEntity.fromJson(Map<String, dynamic> json) => $GarageSaleHistoryEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $GarageSaleHistoryEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class GarageSaleHistoryList {
+	String? id;
+	String? sn;
+	@JSONField(name: "order_status")
+	String? orderStatus;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	IdNameEntity? service;
+	IdNameEntity? merchant;
+	@JSONField(name: "order_products")
+	List<GarageSaleHistoryListOrderProducts> orderProducts = [];
+
+	GarageSaleHistoryList();
+
+	factory GarageSaleHistoryList.fromJson(Map<String, dynamic> json) => $GarageSaleHistoryListFromJson(json);
+
+	Map<String, dynamic> toJson() => $GarageSaleHistoryListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+
+@JsonSerializable()
+class GarageSaleHistoryListOrderProducts {
+	String? id;
+	@JSONField(name: "product_name")
+	String? productName;
+	int quantity = 0;
+	@JSONField(name: "total_amount")
+	String? totalAmount;
+	@JSONField(name: "planned_service_at")
+	String? plannedServiceAt;
+
+	GarageSaleHistoryListOrderProducts();
+
+	factory GarageSaleHistoryListOrderProducts.fromJson(Map<String, dynamic> json) => $GarageSaleHistoryListOrderProductsFromJson(json);
+
+	Map<String, dynamic> toJson() => $GarageSaleHistoryListOrderProductsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 47 - 47
packages/cs_domain/lib/entity/garage_sale_rent_detail_entity.dart

@@ -1,48 +1,48 @@
-import 'package:domain/generated/json/base/json_field.dart';
-import 'package:domain/generated/json/garage_sale_rent_detail_entity.g.dart';
-import 'dart:convert';
-export 'package:domain/generated/json/garage_sale_rent_detail_entity.g.dart';
-
-@JsonSerializable()
-class GarageSaleRentDetailEntity {
-	int? id;
-	String? title;
-	int? price;
-	String? description;
-	List<String>? resources;
-	@JSONField(name: "created_at")
-	String? createdAt;
-	@JSONField(name: "likes_count")
-	int? likesCount;
-	String? contact;
-	GarageSaleRentDetailAccount? account;
-
-	GarageSaleRentDetailEntity();
-
-	factory GarageSaleRentDetailEntity.fromJson(Map<String, dynamic> json) => $GarageSaleRentDetailEntityFromJson(json);
-
-	Map<String, dynamic> toJson() => $GarageSaleRentDetailEntityToJson(this);
-
-	@override
-	String toString() {
-		return jsonEncode(this);
-	}
-}
-
-@JsonSerializable()
-class GarageSaleRentDetailAccount {
-	int? id;
-	String? name;
-	String? avatar;
-
-	GarageSaleRentDetailAccount();
-
-	factory GarageSaleRentDetailAccount.fromJson(Map<String, dynamic> json) => $GarageSaleRentDetailAccountFromJson(json);
-
-	Map<String, dynamic> toJson() => $GarageSaleRentDetailAccountToJson(this);
-
-	@override
-	String toString() {
-		return jsonEncode(this);
-	}
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/garage_sale_rent_detail_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/garage_sale_rent_detail_entity.g.dart';
+
+@JsonSerializable()
+class GarageSaleRentDetailEntity {
+	int? id;
+	String? title;
+	int? price;
+	String? description;
+	List<String>? resources;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "likes_count")
+	int? likesCount;
+	String? contact;
+	GarageSaleRentDetailAccount? account;
+
+	GarageSaleRentDetailEntity();
+
+	factory GarageSaleRentDetailEntity.fromJson(Map<String, dynamic> json) => $GarageSaleRentDetailEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $GarageSaleRentDetailEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class GarageSaleRentDetailAccount {
+	int? id;
+	String? name;
+	String? avatar;
+
+	GarageSaleRentDetailAccount();
+
+	factory GarageSaleRentDetailAccount.fromJson(Map<String, dynamic> json) => $GarageSaleRentDetailAccountFromJson(json);
+
+	Map<String, dynamic> toJson() => $GarageSaleRentDetailAccountToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
 }

+ 139 - 0
packages/cs_domain/lib/entity/paid_service_detail_entity.dart

@@ -0,0 +1,139 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/paid_service_detail_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/paid_service_detail_entity.g.dart';
+
+@JsonSerializable()
+class PaidServiceDetailEntity {
+	int? id;
+	List<String>? resources;
+	String? name;
+	@JSONField(name: "evaluations_avg_score")
+	int? evaluationsAvgScore;
+	String? highlight;
+	@JSONField(name: "urgent_price")
+	int? urgentPrice;
+	@JSONField(name: "holiday_price")
+	int? holidayPrice;
+	@JSONField(name: "night_price")
+	int? nightPrice;
+	@JSONField(name: "service_period_start")
+	String? servicePeriodStart;
+	@JSONField(name: "service_period_end")
+	String? servicePeriodEnd;
+	@JSONField(name: "service_period_interval")
+	int? servicePeriodInterval;
+	String? description;
+	PaidServiceDetailMerchant? merchant;
+	PaidServiceDetailCategory? category;
+	List<PaidServiceDetailProducts>? products;
+	List<PaidServiceDetailEvaluations>? evaluations;
+
+	PaidServiceDetailEntity();
+
+	factory PaidServiceDetailEntity.fromJson(Map<String, dynamic> json) => $PaidServiceDetailEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceDetailEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceDetailMerchant {
+	int? id;
+	String? name;
+	@JSONField(name: "contact_phone")
+	String? contactPhone;
+
+	PaidServiceDetailMerchant();
+
+	factory PaidServiceDetailMerchant.fromJson(Map<String, dynamic> json) => $PaidServiceDetailMerchantFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceDetailMerchantToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceDetailCategory {
+	int? id;
+	String? name;
+	String? type;
+
+	PaidServiceDetailCategory();
+
+	factory PaidServiceDetailCategory.fromJson(Map<String, dynamic> json) => $PaidServiceDetailCategoryFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceDetailCategoryToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceDetailProducts {
+	int? id;
+	String? name;
+	@JSONField(name: "short_description")
+	String? shortDescription;
+	int? price;
+
+	PaidServiceDetailProducts();
+
+	factory PaidServiceDetailProducts.fromJson(Map<String, dynamic> json) => $PaidServiceDetailProductsFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceDetailProductsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceDetailEvaluations {
+	int? id;
+	int? score;
+	String? comment;
+	List<dynamic>? resources;
+	PaidServiceDetailEvaluationsAccount? account;
+	@JSONField(name: "created_at")
+	String? createdAt;
+
+	PaidServiceDetailEvaluations();
+
+	factory PaidServiceDetailEvaluations.fromJson(Map<String, dynamic> json) => $PaidServiceDetailEvaluationsFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceDetailEvaluationsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceDetailEvaluationsAccount {
+	int? id;
+	String? name;
+	String? avatar;
+
+	PaidServiceDetailEvaluationsAccount();
+
+	factory PaidServiceDetailEvaluationsAccount.fromJson(Map<String, dynamic> json) => $PaidServiceDetailEvaluationsAccountFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceDetailEvaluationsAccountToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 85 - 0
packages/cs_domain/lib/entity/paid_service_entity.dart

@@ -0,0 +1,85 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/paid_service_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/paid_service_entity.g.dart';
+
+@JsonSerializable()
+class PaidServiceEntity {
+	int? count;
+	int? page;
+	int? limit;
+	@JSONField(name: "count_page")
+	int? countPage;
+	List<PaidServiceList>? list;
+
+	PaidServiceEntity();
+
+	factory PaidServiceEntity.fromJson(Map<String, dynamic> json) => $PaidServiceEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceList {
+	int? id;
+	String? name;
+	List<String>? resources;
+	@JSONField(name: "lowest_price")
+	int? lowestPrice;
+	@JSONField(name: "likes_count")
+	int? likesCount;
+	bool? liked;
+	PaidServiceListMerchant? merchant;
+	PaidServiceListCategory? category;
+
+	PaidServiceList();
+
+	factory PaidServiceList.fromJson(Map<String, dynamic> json) => $PaidServiceListFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceListMerchant {
+	int? id;
+	String? name;
+
+	PaidServiceListMerchant();
+
+	factory PaidServiceListMerchant.fromJson(Map<String, dynamic> json) => $PaidServiceListMerchantFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceListMerchantToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServiceListCategory {
+	int? id;
+	String? name;
+	String? type;
+
+	PaidServiceListCategory();
+
+	factory PaidServiceListCategory.fromJson(Map<String, dynamic> json) => $PaidServiceListCategoryFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServiceListCategoryToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 169 - 0
packages/cs_domain/lib/entity/paid_service_pay_success_info_entity.dart

@@ -0,0 +1,169 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/paid_service_pay_success_info_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/paid_service_pay_success_info_entity.g.dart';
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoEntity {
+	String? id;
+	String? sn;
+	@JSONField(name: "total_amount")
+	int? totalAmount;
+	@JSONField(name: "paid_at")
+	String? paidAt;
+	String? notes;
+	PaidServicePaySuccessInfoAccount? account;
+	@JSONField(name: "order_service")
+	PaidServicePaySuccessInfoOrderService? orderService;
+	PaidServicePaySuccessInfoMerchant? merchant;
+	PaidServicePaySuccessInfoStaff? staff;
+	@JSONField(name: "order_products")
+	PaidServicePaySuccessInfoOrderProducts? orderProducts;
+	PaidServicePaySuccessInfoEstate? estate;
+	@JSONField(name: "estate_unit")
+	PaidServicePaySuccessInfoEstateUnit? estateUnit;
+
+	PaidServicePaySuccessInfoEntity();
+
+	factory PaidServicePaySuccessInfoEntity.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoAccount {
+	String? id;
+	String? name;
+	String? avatar;
+	String? phone;
+
+	PaidServicePaySuccessInfoAccount();
+
+	factory PaidServicePaySuccessInfoAccount.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoAccountFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoAccountToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoOrderService {
+	String? id;
+	String? name;
+	@JSONField(name: "evaluations_avg_score")
+	int? evaluationsAvgScore;
+
+	PaidServicePaySuccessInfoOrderService();
+
+	factory PaidServicePaySuccessInfoOrderService.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoOrderServiceFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoOrderServiceToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoMerchant {
+	String? id;
+	String? name;
+	@JSONField(name: "contact_phone")
+	String? contactPhone;
+
+	PaidServicePaySuccessInfoMerchant();
+
+	factory PaidServicePaySuccessInfoMerchant.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoMerchantFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoMerchantToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoStaff {
+	String? id;
+	String? name;
+	String? phone;
+
+	PaidServicePaySuccessInfoStaff();
+
+	factory PaidServicePaySuccessInfoStaff.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoStaffFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoStaffToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoOrderProducts {
+	String? id;
+	@JSONField(name: "product_name")
+	String? productName;
+	int? quantity;
+	@JSONField(name: "total_amount")
+	int? totalAmount;
+	@JSONField(name: "planned_service_at")
+	String? plannedServiceAt;
+
+	PaidServicePaySuccessInfoOrderProducts();
+
+	factory PaidServicePaySuccessInfoOrderProducts.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoOrderProductsFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoOrderProductsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoEstate {
+	String? id;
+	String? name;
+
+	PaidServicePaySuccessInfoEstate();
+
+	factory PaidServicePaySuccessInfoEstate.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoEstateFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoEstateToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class PaidServicePaySuccessInfoEstateUnit {
+	String? id;
+	String? unit;
+	String? address;
+
+	PaidServicePaySuccessInfoEstateUnit();
+
+	factory PaidServicePaySuccessInfoEstateUnit.fromJson(Map<String, dynamic> json) => $PaidServicePaySuccessInfoEstateUnitFromJson(json);
+
+	Map<String, dynamic> toJson() => $PaidServicePaySuccessInfoEstateUnitToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 0 - 0
packages/cs_domain/lib/entity/repair_service_entity.dart


Some files were not shown because too many files changed in this diff