glglove 1 месяц назад
Родитель
Сommit
2f6ef14a41
100 измененных файлов с 10389 добавлено и 1964 удалено
  1. 1 0
      .fvm/flutter_sdk
  2. 3 0
      .fvm/fvm_config.json
  3. 1 0
      .fvm/release
  4. 1 0
      .fvm/version
  5. 1 0
      .fvm/versions/3.24.5
  6. 3 0
      .fvmrc
  7. 1 1
      app/lib/main.dart
  8. 156 57
      packages/cpt_uk/lib/modules/job/job_applied/applied_staff_item.dart
  9. 74 11
      packages/cpt_uk/lib/modules/job/job_applied/job_applied_controller.dart
  10. 31 1
      packages/cpt_uk/lib/modules/job/job_applied/job_applied_page.dart
  11. 5 2
      packages/cpt_uk/lib/modules/job/job_applied/job_applied_state.dart
  12. 183 0
      packages/cpt_uk/lib/modules/job/job_applied/widget/applied_set_tip.dart
  13. 74 0
      packages/cpt_uk/lib/modules/job/job_applied/widget/status_popup_menu.dart
  14. 5 0
      packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_controller.dart
  15. 38 33
      packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_page.dart
  16. 2 0
      packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_state.dart
  17. 287 0
      packages/cpt_uk/lib/modules/job/job_applied_revise_list/job_applied_revise_list_controller.dart
  18. 144 0
      packages/cpt_uk/lib/modules/job/job_applied_revise_list/job_applied_revise_list_page.dart
  19. 13 0
      packages/cpt_uk/lib/modules/job/job_applied_revise_list/job_applied_revise_list_state.dart
  20. 323 0
      packages/cpt_uk/lib/modules/job/job_applied_revise_list/revise_list_item.dart
  21. 40 6
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_controller.dart
  22. 42 33
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_page.dart
  23. 5 4
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_state.dart
  24. 180 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/certification_dialog_widget.dart
  25. 214 160
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_detail_widget.dart
  26. 2 3
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_labour_history_item.dart
  27. 1 1
      packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_page.dart
  28. 2 1
      packages/cpt_uk/lib/modules/job/job_list/job_list_item.dart
  29. 219 30
      packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_controller.dart
  30. 766 375
      packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_page.dart
  31. 94 3
      packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_state.dart
  32. 912 0
      packages/cpt_uk/lib/modules/job/labour_request_add/widget/lab_request_and_request_review_form.dart
  33. 112 0
      packages/cpt_uk/lib/modules/job/labour_request_add/widget/labour_request_interface.dart
  34. 197 49
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_item.dart
  35. 89 11
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_controller.dart
  36. 6 0
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_page.dart
  37. 2 2
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_state.dart
  38. 227 0
      packages/cpt_uk/lib/modules/job/labour_request_list/widget/quick_copy_dialog_widget.dart
  39. 128 0
      packages/cpt_uk/lib/modules/job/labour_request_list/widget/quick_copy_dialog_widget_controller.dart
  40. 14 0
      packages/cpt_uk/lib/modules/job/labour_request_list/widget/quick_copy_dialog_widget_state.dart
  41. 243 0
      packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request-preselected_item.dart
  42. 264 0
      packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request_preselected_list_controller.dart
  43. 139 0
      packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request_preselected_list_page.dart
  44. 10 0
      packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request_preselected_list_state.dart
  45. 349 0
      packages/cpt_uk/lib/modules/job/labour_request_preselected_list/widget/preselected_add_staff.dart
  46. 136 0
      packages/cpt_uk/lib/modules/job/labour_request_preselected_list/widget/preselected_add_staff_controller.dart
  47. 108 0
      packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_controller.dart
  48. 70 0
      packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_item.dart
  49. 220 0
      packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_page.dart
  50. 40 0
      packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_state.dart
  51. 101 0
      packages/cpt_uk/lib/modules/job/revise_log/revise_log_controller.dart
  52. 156 0
      packages/cpt_uk/lib/modules/job/revise_log/revise_log_item.dart
  53. 102 0
      packages/cpt_uk/lib/modules/job/revise_log/revise_log_page.dart
  54. 11 0
      packages/cpt_uk/lib/modules/job/revise_log/revise_log_state.dart
  55. 302 19
      packages/cpt_uk/lib/modules/job/template_add/template_add_controller.dart
  56. 157 25
      packages/cpt_uk/lib/modules/job/template_add/template_add_page.dart
  57. 32 3
      packages/cpt_uk/lib/modules/job/template_add/template_add_state.dart
  58. 46 0
      packages/cpt_uk/lib/modules/job/template_list/item_template.dart
  59. 37 34
      packages/cpt_uk/lib/modules/main/main_controller.dart
  60. 107 37
      packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_controller.dart
  61. 107 142
      packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_item.dart
  62. 102 77
      packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_page.dart
  63. 3 5
      packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_state.dart
  64. 45 88
      packages/cpt_uk/lib/modules/report/casual_report/casual_report_controller.dart
  65. 228 108
      packages/cpt_uk/lib/modules/report/casual_report/casual_report_item.dart
  66. 49 43
      packages/cpt_uk/lib/modules/report/casual_report/casual_report_page.dart
  67. 6 5
      packages/cpt_uk/lib/modules/report/casual_report/casual_report_state.dart
  68. 23 35
      packages/cpt_uk/lib/modules/report/outlet_staff_report/outlet_staff_report_controller.dart
  69. 2 2
      packages/cpt_uk/lib/modules/report/outlet_staff_report/outlet_staff_report_item.dart
  70. 7 3
      packages/cpt_uk/lib/modules/report/outlet_staff_report/outlet_staff_report_state.dart
  71. 1 0
      packages/cpt_uk/lib/modules/report/report_list/report_list_controller.dart
  72. 49 12
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_controller.dart
  73. 69 63
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_item.dart
  74. 4 1
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_page.dart
  75. 219 0
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_remark_dialog.dart
  76. 2 2
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_state.dart
  77. 296 67
      packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_controller.dart
  78. 4 257
      packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_page.dart
  79. 93 2
      packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_state.dart
  80. 94 62
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_controller.dart
  81. 107 20
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_item.dart
  82. 2 1
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_state.dart
  83. 32 4
      packages/cpt_uk/lib/router/uk_router.dart
  84. 66 0
      packages/cs_domain/lib/constants/api_constants.dart
  85. 0 64
      packages/cs_domain/lib/entity/response/u_k_template_detail_entity.dart
  86. 4 0
      packages/cs_domain/lib/entity/response/u_k_template_entity.dart
  87. 72 0
      packages/cs_domain/lib/entity/response/uk_attendance_review_entity.dart
  88. 25 0
      packages/cs_domain/lib/entity/response/uk_attendance_review_remark_entity.dart
  89. 176 0
      packages/cs_domain/lib/entity/response/uk_job_applied_revise_add_detail_entity.dart
  90. 362 0
      packages/cs_domain/lib/entity/response/uk_job_applied_revise_edit_detail_entity.dart
  91. 54 0
      packages/cs_domain/lib/entity/response/uk_job_applied_revise_info_entity.dart
  92. 119 0
      packages/cs_domain/lib/entity/response/uk_job_applied_revise_log_entity.dart
  93. 165 0
      packages/cs_domain/lib/entity/response/uk_job_applied_staff_list_entity.dart
  94. 44 0
      packages/cs_domain/lib/entity/response/uk_job_template_detail_by_select_title_entity.dart
  95. 158 0
      packages/cs_domain/lib/entity/response/uk_labour_request_detail_entity.dart
  96. 46 0
      packages/cs_domain/lib/entity/response/uk_labour_request_preselect_addstatff_list_entity.dart
  97. 44 0
      packages/cs_domain/lib/entity/response/uk_labour_request_preselected_list_entity.dart
  98. 213 0
      packages/cs_domain/lib/entity/response/uk_labour_request_review_detail_entity.dart
  99. 69 0
      packages/cs_domain/lib/entity/response/uk_labour_request_review_list_entity.dart
  100. 0 0
      packages/cs_domain/lib/entity/response/uk_labour_request_table_entity.dart

+ 1 - 0
.fvm/flutter_sdk

@@ -0,0 +1 @@
+I:/programInstall/fvm/versions/3.24.5

+ 3 - 0
.fvm/fvm_config.json

@@ -0,0 +1,3 @@
+{
+  "flutterSdkVersion": "3.24.5"
+}

+ 1 - 0
.fvm/release

@@ -0,0 +1 @@
+3.24.5

+ 1 - 0
.fvm/version

@@ -0,0 +1 @@
+3.24.5

+ 1 - 0
.fvm/versions/3.24.5

@@ -0,0 +1 @@
+I:/programInstall/fvm/versions/3.24.5

+ 3 - 0
.fvmrc

@@ -0,0 +1,3 @@
+{
+  "flutter": "3.24.5"
+}

+ 1 - 1
app/lib/main.dart

@@ -104,7 +104,7 @@ class MyApp extends StatelessWidget {
         usePenetrate: false,
       )
       ..loading = SmartConfigLoading(
-        backDismiss: true,
+        // backDismiss: true,
         clickMaskDismiss: true,
       )
       ..toast = SmartConfigToast(

+ 156 - 57
packages/cpt_uk/lib/modules/job/job_applied/applied_staff_item.dart

@@ -2,6 +2,7 @@ import 'package:cs_resources/constants/color_constants.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/response/job_list_applied_info_entity.dart';
 import 'package:domain/entity/response/job_list_applied_staff_list_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_staff_list_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
@@ -12,18 +13,23 @@ import 'package:widgets/my_button.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 
+import 'widget/status_popup_menu.dart';
+
 /**
  * 已申请的员工列表Item
  */
 class AppliedStaffItem extends StatelessWidget {
   final int index;
   final JobListAppliedInfoEntity? jobInfo;
-  final JobListAppliedStaffListRows item;
+  final UkJobAppliedStaffListRows item;
   final VoidCallback? onStatusAction;
   final VoidCallback? onEditAction;
+  final VoidCallback? onReviseAction;
   final VoidCallback? onRemarkAction;
   final VoidCallback? onItemAction;
   final VoidCallback? onMemberAction;
+  final VoidCallback? onTipAction;
+  final Function(String? statusText, String? status, String? toChangeStatusText, String? toChangeStatus)? onChangeStatusAction;
 
   AppliedStaffItem({
     required this.index,
@@ -32,8 +38,11 @@ class AppliedStaffItem extends StatelessWidget {
     this.onStatusAction,
     this.onRemarkAction,
     this.onEditAction,
+    this.onReviseAction,
     this.onItemAction,
     this.onMemberAction,
+    this.onTipAction,
+    this.onChangeStatusAction,
   });
 
   @override
@@ -80,9 +89,9 @@ class AppliedStaffItem extends StatelessWidget {
 
               //是否选中
               Visibility(
-                visible: item.status == 3,
+                visible: item.status == 3,  // 1 Pending 2 Rejected 3 applied 4 Cancelled 5 No Show 6 Approve 7 Completed
                 child: MyAssetImage(
-                  item.isSelected ? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedIcon,
+                  item.isSelected??item.isSelected!? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedIcon,
                   width: 20.5,
                   height: 20.5,
                 ),
@@ -90,8 +99,10 @@ class AppliedStaffItem extends StatelessWidget {
             ],
           ),
 
-          // 工作开始时间
-          Row(
+          // 开始时间   结束时间
+          _buildRowItems(
+              context,
+              leftWidget: Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
@@ -111,15 +122,12 @@ class AppliedStaffItem extends StatelessWidget {
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 12),
-
-          // 门卫签到时间
-          Row(
+          ), rightWidget:Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Security In:".tr,
+                "End Time:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
@@ -127,22 +135,22 @@ class AppliedStaffItem extends StatelessWidget {
 
               //时间
               MyTextView(
-                item.securityIn?.time ?? "-",
+                item.endTime ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: item.securityIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                textColor: Colors.white,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 12),
+          )).marginOnly(top: 12),
 
-          // 工作地签到时
-          Row(
+          // 门卫签到时间  门卫签出时
+          _buildRowItems(context, leftWidget: Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Work In:".tr,
+                "Security In:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
@@ -150,22 +158,19 @@ class AppliedStaffItem extends StatelessWidget {
 
               //时间
               MyTextView(
-                item.workIn?.time ?? "-",
+                item.securityIn?.time ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: item.workIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                textColor: item.securityIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 12),
-
-          //工作结束时间
-          Row(
+          ), rightWidget: Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "End Time:".tr,
+                "Security Out:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
@@ -173,22 +178,22 @@ class AppliedStaffItem extends StatelessWidget {
 
               //时间
               MyTextView(
-                item.endTime ?? "-",
+                item.securityOut?.time ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: Colors.white,
+                textColor: item.securityOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 12),
+          )).marginOnly(top: 12),
 
-          // 工作地签出时间
-          Row(
+          // 工作地签到时间  工作地签出时间
+          _buildRowItems(context, leftWidget: Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Work Out:".tr,
+                "Work In:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
@@ -196,22 +201,19 @@ class AppliedStaffItem extends StatelessWidget {
 
               //时间
               MyTextView(
-                item.workOut?.time ?? "-",
+                item.workIn?.time ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: item.workOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                textColor: item.workIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 12),
-
-          // 门卫签出时间
-          Row(
+          ), rightWidget: Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Security Out:".tr,
+                "Work Out:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
@@ -219,17 +221,20 @@ class AppliedStaffItem extends StatelessWidget {
 
               //时间
               MyTextView(
-                item.securityOut?.time ?? "-",
+                item.workOut?.time ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: item.securityOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                textColor: item.workOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 12),
+          )).marginOnly(top: 12),
 
-          // + - Hours
-          Visibility(
+
+          // + - Hours  Total Hours
+          _buildRowItems(context,
+              showLeftWidget: jobInfo?.jobUnit == "hour",
+              leftWidget: Visibility(
             visible: jobInfo?.jobUnit == "hour",
             child: Row(
               mainAxisSize: MainAxisSize.max,
@@ -251,11 +256,10 @@ class AppliedStaffItem extends StatelessWidget {
                   fontSize: 14,
                 ).expanded(),
               ],
-            ).marginOnly(top: 12),
+            ),
           ),
-
-          // Total Hours
-          Visibility(
+              showRightWidget: jobInfo?.jobUnit == "hour",
+              rightWidget: Visibility(
             visible: jobInfo?.jobUnit == "hour",
             child: Row(
               mainAxisSize: MainAxisSize.max,
@@ -277,8 +281,77 @@ class AppliedStaffItem extends StatelessWidget {
                   fontSize: 14,
                 ).expanded(),
               ],
-            ).marginOnly(top: 12),
+            ),
           ),
+          ).marginOnly(top: 12),
+
+          // tip  status
+          _buildRowItems(context,
+            showLeftWidget: true,
+            leftWidget: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                MyTextView(
+                  "Tip:".tr,
+                  isFontRegular: true,
+                  textColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                ),
+
+                //小费
+                MyTextView(
+                  item.gratuity ?? "0.00",
+                  marginLeft: 5,
+                  isFontRegular: true,
+                  textColor: ColorConstants.textBlue06D9FF,  //默认蓝色
+                  fontSize: 14,
+                  onClick: (){
+                    onTipAction?.call();
+                  },
+                ).expanded(),
+              ],
+            ),
+            showRightWidget: true,
+            rightWidget: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                MyTextView(
+                  "Status:".tr,
+                  isFontRegular: true,
+                  textColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                ),
+
+                //发布状态
+                MyTextView(
+                  onClick: (){
+                    onChangeStatusAction?.call(item.statusShow, item.status.toString(), '2', '2');
+                  },
+                  item.statusShow ?? "-",
+                  marginLeft: 5,
+                  isFontRegular: true,
+                  textColor: "Completed" == item.statusShow
+                      ? ColorConstants.textGreen05DC82
+                      : "Cancelled" == item.statusShow || "Rejected" == item.statusShow
+                      ? ColorConstants.textRedFF6262
+                      : "Revised" == item.statusShow || "Pending" == item.statusShow || "Approve" == item.statusShow
+                      ? ColorConstants.textYellowFFBB1B
+                      : ColorConstants.textBlue06D9FF,  //默认蓝色
+                  fontSize: 14,
+                ).expanded(),
+
+                // StatusPopupMenu(
+                //   statusShow: item.statusShow,
+                //   status: item.status,
+                //   onChangeStatusAction: (String? statusText, String? status, String? toChangeStatusText, String? toChangeStatus){
+                //         onChangeStatusAction?.call(statusText, status.toString(), toChangeStatusText, toChangeStatus);
+                //   },
+                // )
+              ],
+            ),
+          ).marginOnly(top: 12),
 
           // Total Rooms
           Visibility(
@@ -329,30 +402,23 @@ class AppliedStaffItem extends StatelessWidget {
             ],
           ).marginOnly(top: 12),
 
-          // 状态
+          // Reason
           Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Status:".tr,
+                "Reason:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
               ),
 
-              //发布状态
               MyTextView(
-                item.statusShow ?? "-",
+                item.rejectRemark??"-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: "Completed" == item.statusShow
-                    ? ColorConstants.textGreen05DC82
-                    : "Cancelled" == item.statusShow || "Rejected" == item.statusShow
-                        ? ColorConstants.textRedFF6262
-                        : "Revised" == item.statusShow || "Pending" == item.statusShow || "Approve" == item.statusShow
-                            ? ColorConstants.textYellowFFBB1B
-                            : ColorConstants.textBlue06D9FF,  //默认蓝色
+                textColor: Colors.white,
                 fontSize: 14,
               ).expanded(),
             ],
@@ -385,6 +451,24 @@ class AppliedStaffItem extends StatelessWidget {
                   ).marginOnly(left: 12),
                 ),
 
+                // revise 按钮
+                Visibility(
+                  visible: item.actionList?.contains("revise") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onReviseAction?.call();
+                    },
+                    text: "Revise".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#FFFFBB1B"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+
+
                 //状态工作流按钮
                 Visibility(
                   visible: item.actionList?.contains("status") ?? false,
@@ -427,4 +511,19 @@ class AppliedStaffItem extends StatelessWidget {
       }),
     );
   }
+
+
+  Widget _buildRowItems(BuildContext? context, {
+    bool showLeftWidget = true,
+    bool showRightWidget = true,
+    Widget? leftWidget,
+    Widget? rightWidget,
+  }){
+    return Row(
+      children: [
+        showLeftWidget && leftWidget!=null ? Expanded(flex:1, child: leftWidget ?? const SizedBox.shrink(),): const SizedBox.shrink(),
+        showRightWidget && rightWidget!=null ? Expanded(flex:1,child: rightWidget ?? const SizedBox.shrink()): const SizedBox.shrink(),
+      ],
+    );
+  }
 }

+ 74 - 11
packages/cpt_uk/lib/modules/job/job_applied/job_applied_controller.dart

@@ -1,5 +1,9 @@
+import 'dart:ui';
+
 import 'package:domain/entity/response/job_list_applied_staff_list_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_staff_list_entity.dart';
 import 'package:domain/repository/job_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
 import 'package:get/get.dart';
 import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
@@ -8,20 +12,24 @@ import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/util.dart';
 import 'package:widgets/dialog/app_default_dialog.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 import '../job_applied_edit/job_applied_edit_page.dart';
+import '../job_applied_revise_list/job_applied_revise_list_page.dart';
 import '../job_applied_staff_detail/applied_staff_detail_page.dart';
 import '../job_applied_workflow/applied_workflow_page.dart';
 import 'job_applied_state.dart';
 import 'widget/applied_add_staff.dart';
 import 'widget/applied_butch_modify.dart';
+import 'widget/applied_set_tip.dart';
 import 'widget/applied_staff_reviews.dart';
 
 class JobAppliedController extends GetxController with DioCancelableMixin {
   final JobRepository _jobRepository = Get.find();
+  final UKJobRepository _ukjobRepository = Get.find();
   final JobAppliedState state = JobAppliedState();
 
   var _curPage = 1;
@@ -86,7 +94,7 @@ class JobAppliedController extends GetxController with DioCancelableMixin {
     }
 
     // 获取 Applied 列表
-    var listResult = await _jobRepository.fetchJobAppliedStaffs(
+    var listResult = await _ukjobRepository.fetchJobAppliedStaffs(
       state.jobId,
       state.keyword,
       curPage: _curPage,
@@ -106,7 +114,7 @@ class JobAppliedController extends GetxController with DioCancelableMixin {
   }
 
   // 处理数据与展示的逻辑
-  void handleList(List<JobListAppliedStaffListRows>? list) {
+  void handleList(List<UkJobAppliedStaffListRows>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_curPage == 1) {
@@ -210,6 +218,7 @@ class JobAppliedController extends GetxController with DioCancelableMixin {
             .toList();
       }
 
+
       if (filteredMessages.isNotEmpty) {
         //有错误信息
         NotifyEngine.showFailure(filteredMessages.join(" , "));
@@ -225,13 +234,25 @@ class JobAppliedController extends GetxController with DioCancelableMixin {
     }
   }
 
+  // 修改状态
+  void changeStatus(String? statusText, String? status, String? toChangeStatusText, String? toChangeStatus) async {
+    // 修改状态   只有applied 状态才能修改 成 Rejected 和 No Show
+    Log.d("修改前的 statusText: ${statusText}, 修改前的 status: ${status}, 要修改的 statusText: ${toChangeStatusText}, 要修改的 status: ${toChangeStatus}");
+  }
+
+  // 去Revise 页面
+  void gotoRevisePage(UkJobAppliedStaffListRows data) {
+    UKJobAppliedRevisePage.startInstance(data.appliedId.toString());
+  }
+
+
   /// 去编辑员工信息页面
-  void gotoAppliedEditPage(JobListAppliedStaffListRows data) {
+  void gotoAppliedEditPage(UkJobAppliedStaffListRows data) {
     UKJobAppliedEditPage.startInstance(data.appliedId.toString());
   }
 
   /// 展示评论的弹窗
-  void showRemarkDialog(JobListAppliedStaffListRows data) async {
+  void showRemarkDialog(UkJobAppliedStaffListRows data) async {
     //请求接口获取到已评论的数据
     var result = await _jobRepository.fetchAppliedStaffReviewView(data.appliedId.toString());
 
@@ -266,20 +287,62 @@ class JobAppliedController extends GetxController with DioCancelableMixin {
   }
 
   /// 去展示员工状态的审核流程页面
-  void gotoAppliedWorkflowPage(JobListAppliedStaffListRows data) {
+  void gotoAppliedWorkflowPage(UkJobAppliedStaffListRows data) {
     UKAppliedWorkflowPage.startInstance(data.appliedId.toString());
   }
 
   /// 去查看员工详情页面
-  void gotoStaffDetailPage(JobListAppliedStaffListRows data) {
+  void gotoStaffDetailPage(UkJobAppliedStaffListRows data) {
     UKAppliedStaffDetailPage.startInstance(data.memberId.toString());
   }
 
+  // 设置小费
+  void showTipDialog(UkJobAppliedStaffListRows data){
+    // 只有 statusShow 不为 Approve 或者不为Completed 的状态才能设置小费
+    DialogEngine.show(
+      tag: 'AppliedSetTip',
+      widget: SetTip(
+        settedTip: '',
+        isConfirmAutoClose: false,
+        confirmAction: (tipNum) {
+          Log.d("设置的小费为----  ${tipNum}");
+          if(Utils.isNotEmpty(tipNum)){
+            //调用接口设置小费
+            _requestSetTip(tipNum, data.appliedId.toString(), callback: (){
+              SmartDialog.dismiss(tag: 'AppliedSetTip');
+            });
+          }else {
+            ToastEngine.show("Please enter the tip amount".tr);
+          }
+        },
+      ),
+    );
+  }
+
+  Future<void> _requestSetTip(String tipNum, String appliedId, {VoidCallback? callback}) async {
+    final result = await _ukjobRepository.appliedStaffBatchSetTipSubmit(
+      appliedIds: appliedId,
+      gratuity: tipNum,
+    );
+    if(result.isSuccess){
+      // 更新当前员工的小费
+      // 找到 当前员工
+      var appliedStaff = state.datas.where((element) => element.appliedId?.toString() == appliedId)?.first;
+      appliedStaff?.gratuity = tipNum;
+      update();
+      NotifyEngine.showSuccess("Successful".tr);
+      callback?.call();
+    }else{
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
   /// Item选中与未选中设置
-  void doSelectedOrNot(JobListAppliedStaffListRows data) {
+  void doSelectedOrNot(UkJobAppliedStaffListRows data) {
+    // 1 Pending 2 Rejected 3 applied 4 Cancelled 5 No Show 6 Approve 7 Completed
     //只有 Approve = 3 的状态才能选中
     if (data.status == 3) {
-      data.isSelected = !data.isSelected;
+      data.isSelected = !(data.isSelected??false);
       update();
     }
   }
@@ -363,7 +426,7 @@ class JobAppliedController extends GetxController with DioCancelableMixin {
 
   /// 根据ID获取Item对象,用于刷新
   void fetchItemByIdAndRefreshItem(String appliedIds) async {
-    var result = await _jobRepository.fetchItemByAppliedIds(
+    var result = await _ukjobRepository.fetchItemByAppliedIds(
       state.jobId,
       appliedIds,
       cancelToken: cancelToken,
@@ -373,10 +436,10 @@ class JobAppliedController extends GetxController with DioCancelableMixin {
     if (result.isSuccess) {
       var data = result.data;
       if (data != null && data.rows != null && data.rows!.isNotEmpty) {
-        List<JobListAppliedStaffListRows> newItem = data.rows!;
+        List<UkJobAppliedStaffListRows> newItem = data.rows!;
 
         // 创建一个 Map 来加速查找
-        Map<int, JobListAppliedStaffListRows> newItemMap = {for (var item in newItem) item.appliedId: item};
+        Map<int, UkJobAppliedStaffListRows> newItemMap = {for (var item in newItem) item.appliedId!: item};
 
         // 遍历 state.datas 进行替换
         for (int i = 0; i < state.datas.length; i++) {

+ 31 - 1
packages/cpt_uk/lib/modules/job/job_applied/job_applied_page.dart

@@ -2,6 +2,7 @@ import 'package:cs_resources/constants/color_constants.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
+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';
@@ -144,9 +145,15 @@ class _JobAppliedState extends BaseState<UKJobAppliedPage, JobAppliedController>
                             index: index,
                             jobInfo: state.jobInfo,
                             item: state.datas[index],
+                            onChangeStatusAction: (String? statusText, String? status, String? toChangeStatusText, String? toChangeStatus) {
+                              controller.changeStatus(statusText, status, toChangeStatusText, toChangeStatus );
+                            },
                             onEditAction: () {
                               controller.gotoAppliedEditPage(state.datas[index]);
                             },
+                            onReviseAction: (){
+                              controller.gotoRevisePage(state.datas[index]);
+                            },
                             onRemarkAction: () {
                               controller.showRemarkDialog(state.datas[index]);
                             },
@@ -159,6 +166,9 @@ class _JobAppliedState extends BaseState<UKJobAppliedPage, JobAppliedController>
                             onMemberAction: (){
                               controller.gotoStaffDetailPage(state.datas[index]);
                             },
+                            onTipAction: () {
+                              controller.showTipDialog(state.datas[index]);
+                            },
                           );
                         },
                         childCount: state.datas.length,
@@ -167,6 +177,26 @@ class _JobAppliedState extends BaseState<UKJobAppliedPage, JobAppliedController>
                   ),
                 ).expanded(),
 
+                // 小费 (批量设置小费 和 批量审核/拒绝 能设置的状态不一致 导致公用同一个选项选择有问题 故先不批量设置小费 单独进行设置小费)
+                // Row(
+                //   mainAxisSize: MainAxisSize.max,
+                //   children: [
+                //     MyTextView(
+                //       "Tip".tr,
+                //       fontSize: 17,
+                //       isFontMedium: true,
+                //       boxHeight: 48,
+                //       onClick: () {
+                //         controller.showTipDialog();
+                //       },
+                //       alignment: Alignment.center,
+                //       textAlign: TextAlign.center,
+                //       textColor: Colors.white,
+                //       backgroundColor: Color(0XFFCA28E4),
+                //     ).expanded(),
+                //
+                //   ],
+                // ),
                 Row(
                   mainAxisSize: MainAxisSize.max,
                   children: [
@@ -185,7 +215,7 @@ class _JobAppliedState extends BaseState<UKJobAppliedPage, JobAppliedController>
                       backgroundColor: Color(0XFF0AC074),
                     ).expanded(),
 
-                    //批量修改时间
+                    //批量reject
                     MyTextView(
                       "Batch Modify".tr,
                       fontSize: 17,

+ 5 - 2
packages/cpt_uk/lib/modules/job/job_applied/job_applied_state.dart

@@ -1,5 +1,7 @@
 import 'package:domain/entity/response/job_list_applied_info_entity.dart';
 import 'package:domain/entity/response/job_list_applied_staff_list_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_staff_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_review_list_entity.dart';
 import 'package:flutter/material.dart';
 
 class JobAppliedState {
@@ -8,7 +10,8 @@ class JobAppliedState {
   String keyword = "";
 
   String? jobId;
-  JobListAppliedInfoEntity? jobInfo; //指定工作的简短信息
+  JobListAppliedInfoEntity? jobInfo;
 
-  List<JobListAppliedStaffListRows> datas = []; //Applied的员工列表
+
+  List<UkJobAppliedStaffListRows> datas = []; //Applied的员工列表
 }

+ 183 - 0
packages/cpt_uk/lib/modules/job/job_applied/widget/applied_set_tip.dart

@@ -0,0 +1,183 @@
+import 'dart:typed_data';
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/round_my_text_field.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 设置小费的弹窗
+ */
+class SetTip extends StatefulWidget {
+  String? settedTip;
+  bool? isConfirmAutoClose = true;
+  TextInputType? textInputType = TextInputType.numberWithOptions(decimal: true);
+  void Function(String settedTip)? confirmAction;
+
+  SetTip({this.settedTip,this.isConfirmAutoClose, this.confirmAction});
+
+  @override
+  State<SetTip> createState() => _SetTipState();
+}
+
+class _SetTipState extends State<SetTip> {
+  String? settedTip;
+
+  //表单的校验与数据
+  Map<String, Map<String, dynamic>> formData = {
+    'setted_tip': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+  };
+
+  @override
+  void initState() {
+    super.initState();
+    settedTip = widget.settedTip;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        //Title (如果使用 Container 为最外层容器则默认为 match_parent 的效果,除非我们限制宽度和最大高度最小高度)
+        Container(
+          padding: const EdgeInsets.symmetric(horizontal: 16.5),
+          width: double.infinity,
+          decoration: const BoxDecoration(
+            color: Colors.white,
+            borderRadius: BorderRadius.all(Radius.circular(15)),
+          ),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Center(
+                child: MyTextView(
+                  "Tip".tr,
+                  fontSize: 19,
+                  isFontMedium: true,
+                  textColor: ColorConstants.black,
+                  marginTop: 20,
+                  marginBottom: 20,
+                ),
+              ),
+
+              FormRequireText(
+                fontSize: 14,
+                textColor: ColorConstants.black33,
+                fontWeight: FontWeight.w400,
+                text: "Tip".tr,
+              ),
+
+              //输入框(只允许输入带小数的数字)
+              CustomTextField(
+                formKey: "setted_tip",
+                marginLeft: 0,
+                marginRight: 0,
+                paddingTop: 0,
+                paddingBottom: 0,
+                height: 45,
+                fillBackgroundColor: Color(0xFFF0F0F0),
+                enabled: true,
+                inputFormatters: <TextInputFormatter>[ FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*'))],
+                textInputType: widget.textInputType??TextInputType.numberWithOptions(decimal: true),
+                formData: formData,
+                textInputAction: TextInputAction.done,
+                textColor:  ColorConstants.black,
+                onSubmit: (key, value) {
+                  FocusScope.of(context).unfocus();
+                  var tipNumController = formData['setted_tip']!['controller'];
+                  settedTip = tipNumController.text;
+                },
+                marginTop: 10,
+              ),
+
+              Container(
+                margin: const EdgeInsets.only(top: 25),
+                color: const Color(0XFFCECECE),
+                height: 0.5,
+              ),
+              Row(
+                children: [
+                  Expanded(
+                      flex: 1,
+                      child: InkWell(
+                        onTap: () {
+                          onCancel();
+                        },
+                        child: MyTextView(
+                          "Cancel".tr,
+                          fontSize: 17.5,
+                          isFontMedium: true,
+                          textAlign: TextAlign.center,
+                          textColor: Color(0XFF0085C4),
+                          cornerRadius: 3,
+                          borderWidth: 1,
+                        ),
+                      )),
+                  Container(
+                    color: Color(0xff09141F).withOpacity(0.13),
+                    width: 0.5,
+                  ),
+                  Expanded(
+                      flex: 1,
+                      child: InkWell(
+                        onTap: () async {
+                          var tipNumController = formData['setted_tip']!['controller'];
+                          String tipNum = tipNumController.text;
+                          settedTip = tipNum;
+                          if (settedTip == null) {
+                            ToastEngine.show("Enter Tip".tr);
+                            return;
+                          }
+
+                          widget.confirmAction?.call(settedTip!);
+                          if(widget.isConfirmAutoClose??true){
+                            onCancel();
+                          }
+                        },
+                        child: MyTextView(
+                          "Submit".tr,
+                          marginLeft: 10,
+                          fontSize: 17.5,
+                          isFontMedium: true,
+                          textAlign: TextAlign.center,
+                          textColor: const Color(0XFF0085C4),
+                          cornerRadius: 3,
+                        ),
+                      )),
+                ],
+              ).constrained(height: 46),
+            ],
+          ),
+        ),
+      ],
+    ).constrained(width: 285);
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+}

+ 74 - 0
packages/cpt_uk/lib/modules/job/job_applied/widget/status_popup_menu.dart

@@ -0,0 +1,74 @@
+import 'dart:ui';
+
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:flutter/material.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+
+class StatusPopupMenu extends StatelessWidget {
+  final String? statusShow;
+  final int? status;
+  final Function(String? statusText, String? status, String? toChangeStatusText, String? toChangeStatus)? onChangeStatusAction;
+
+  const StatusPopupMenu({
+    Key? key,
+    required this.statusShow,
+    required this.status,
+    this.onChangeStatusAction,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return PopupMenuButton<String>(
+        offset: Offset(50, 20),
+      onSelected: (String result) {
+        Log.d("选取的 result: ${result}");
+        // 根据选择的结果调用onChangeStatusAction
+        // 1 Pending 2 Rejected 3 applied 4 Cancelled 5 No Show 6 Approve 7 Completed
+        if (result == 'Rejected') {
+          onChangeStatusAction?.call(statusShow, status?.toString(), 'Rejected', '2');
+        } else if (result == 'No Show') {
+          onChangeStatusAction?.call(statusShow, status?.toString(), 'No Show', '5');
+        }
+      },
+      itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
+        PopupMenuItem<String>(
+          height: 40,
+          value: 'Rejected',
+          child: MyTextView(
+            'Rejected',
+            textColor: ColorConstants.textRedFF6262,
+          ),
+        ),
+        PopupMenuItem<String>(
+          height: 40,
+          value: 'No Show',
+          child: MyTextView(
+            'No Show',
+            textColor: ColorConstants.textYellowFFBB1B,
+          ),
+        ),
+      ],
+      child: MyTextView(
+        statusShow ?? "-",
+        marginLeft: 5,
+        isFontRegular: true,
+        textColor: _getStatusColor(statusShow),
+        fontSize: 14,
+      ),
+    );
+  }
+
+  Color _getStatusColor(String? statusShow) {
+    if (statusShow == "Completed") {
+      return ColorConstants.textGreen05DC82;
+    } else if (statusShow == "Cancelled" || statusShow == "Rejected") {
+      return ColorConstants.textRedFF6262;
+    } else if (statusShow == "Revised" || statusShow == "Pending" || statusShow == "Approve") {
+      return ColorConstants.textYellowFFBB1B;
+    } else {
+      return ColorConstants.textBlue06D9FF;
+    }
+  }
+}

+ 5 - 0
packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_controller.dart

@@ -141,6 +141,11 @@ class JobAppliedEditController extends GetxController with DioCancelableMixin {
     TextEditingController totalRoomController = state.formData['total_room']!['controller'];
     TextEditingController addHourController = state.formData['add_hours']!['controller'];
     TextEditingController reasonController = state.formData['reason']!['controller'];
+    // 当 选择的 reason 选项的value 为 3 时 需要必须填写原因
+    if (state.appliedEditView!.reasonType == 3 && reasonController.text.isEmpty) {
+      ToastEngine.show("Please fill in the reason".tr);
+      return;
+    }
     // 获取文本并尝试转换为整数
     String totalRoomText = totalRoomController.text;
     if (totalRoomText.isNotEmpty) {

+ 38 - 33
packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_page.dart

@@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:get/get.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_load_image.dart';
@@ -159,16 +160,12 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                         controller.pickStartTime();
                       }),
 
-                      //门卫签到时间
-                      MyTextView(
-                        "Security In".tr,
-                        textColor: Colors.white,
-                        fontSize: 15,
-                        marginTop: 15,
-                        isFontRegular: true,
-                      ),
+                      //结束时间
+                      FormRequireText(
+                        text: "End Time".tr,
+                      ).marginOnly(top: 15),
 
-                      //门卫签到时间
+                      //结束时间
                       Container(
                         padding: EdgeInsets.only(left: 16, right: 10),
                         margin: EdgeInsets.only(top: 10),
@@ -183,32 +180,33 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                           mainAxisAlignment: MainAxisAlignment.start,
                           children: [
                             MyTextView(
-                              state.appliedEditView?.securityIn ?? "-",
+                              state.appliedEditView?.endTime ?? "-",
                               fontSize: 14,
-                              hint: "Security In".tr,
+                              hint: "Job End Time".tr,
                               textHintColor: ColorConstants.textGrayAECAE5,
                               isFontMedium: true,
                               textColor: ColorConstants.white,
                             ).expanded(),
+
                             //下拉选图标
                             MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
                           ],
                         ),
                       ).onTap(() {
                         FocusScope.of(context).unfocus();
-                        controller.pickSecurityInTime();
+                        controller.pickEndTime();
                       }),
 
-                      //工作地签到时间
+                      //门卫签到时间
                       MyTextView(
-                        "Work In".tr,
+                        "Security In".tr,
                         textColor: Colors.white,
                         fontSize: 15,
                         marginTop: 15,
                         isFontRegular: true,
                       ),
 
-                      //工作地签到时间
+                      //门卫签到时间
                       Container(
                         padding: EdgeInsets.only(left: 16, right: 10),
                         margin: EdgeInsets.only(top: 10),
@@ -223,9 +221,9 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                           mainAxisAlignment: MainAxisAlignment.start,
                           children: [
                             MyTextView(
-                              state.appliedEditView?.workIn ?? "-",
+                              state.appliedEditView?.securityIn ?? "-",
                               fontSize: 14,
-                              hint: "Work In".tr,
+                              hint: "Security In".tr,
                               textHintColor: ColorConstants.textGrayAECAE5,
                               isFontMedium: true,
                               textColor: ColorConstants.white,
@@ -236,15 +234,19 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                         ),
                       ).onTap(() {
                         FocusScope.of(context).unfocus();
-                        controller.pickWorkInTime();
+                        controller.pickSecurityInTime();
                       }),
 
-                      //结束时间
-                      FormRequireText(
-                        text: "End Time".tr,
-                      ).marginOnly(top: 15),
+                      //门卫签出时间
+                      MyTextView(
+                        "Security Out".tr,
+                        textColor: Colors.white,
+                        fontSize: 15,
+                        marginTop: 15,
+                        isFontRegular: true,
+                      ),
 
-                      //结束时间
+                      //门卫签出时间
                       Container(
                         padding: EdgeInsets.only(left: 16, right: 10),
                         margin: EdgeInsets.only(top: 10),
@@ -259,33 +261,32 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                           mainAxisAlignment: MainAxisAlignment.start,
                           children: [
                             MyTextView(
-                              state.appliedEditView?.endTime ?? "-",
+                              state.appliedEditView?.securityOut ?? "-",
                               fontSize: 14,
-                              hint: "Job End Time".tr,
+                              hint: "Security Out".tr,
                               textHintColor: ColorConstants.textGrayAECAE5,
                               isFontMedium: true,
                               textColor: ColorConstants.white,
                             ).expanded(),
-
                             //下拉选图标
                             MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
                           ],
                         ),
                       ).onTap(() {
                         FocusScope.of(context).unfocus();
-                        controller.pickEndTime();
+                        controller.pickSecurityOutTime();
                       }),
 
-                      //门卫签出时间
+                      //工作地签到时间
                       MyTextView(
-                        "Security Out".tr,
+                        "Work In".tr,
                         textColor: Colors.white,
                         fontSize: 15,
                         marginTop: 15,
                         isFontRegular: true,
                       ),
 
-                      //门卫签出时间
+                      //工作地签到时间
                       Container(
                         padding: EdgeInsets.only(left: 16, right: 10),
                         margin: EdgeInsets.only(top: 10),
@@ -300,9 +301,9 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                           mainAxisAlignment: MainAxisAlignment.start,
                           children: [
                             MyTextView(
-                              state.appliedEditView?.securityOut ?? "-",
+                              state.appliedEditView?.workIn ?? "-",
                               fontSize: 14,
-                              hint: "Security Out".tr,
+                              hint: "Work In".tr,
                               textHintColor: ColorConstants.textGrayAECAE5,
                               isFontMedium: true,
                               textColor: ColorConstants.white,
@@ -313,9 +314,10 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                         ),
                       ).onTap(() {
                         FocusScope.of(context).unfocus();
-                        controller.pickSecurityOutTime();
+                        controller.pickWorkInTime();
                       }),
 
+
                       //工作地签出时间
                       MyTextView(
                         "Work Out".tr,
@@ -440,6 +442,9 @@ class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEdi
                               options: state.appliedEditView!.reasonList!.map((e) => e.txt).whereType<String>().toList(), //后台返回的数据展示,并且根据后台的数据匹配索引
                               selectedPosition: state.appliedEditView!.reasonList!.indexWhere((element) => element.value == state.appliedEditView!.reasonType),
                               onOptionSelected: (index, text) {
+                                // Log.d("00003  ${index} ${text}");
+                                state.selectedReasonItem = state.appliedEditView!.reasonList![index];
+                                // Log.d("${state.appliedEditView!.reasonList![index]}");
                                 //修改内存的值
                                 state.appliedEditView!.reasonType = state.appliedEditView!.reasonList![index].value;
                               },

+ 2 - 0
packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_state.dart

@@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
 import 'package:plugin_basic/basic_export.dart';
 
 class JobAppliedEditState {
+  // reason 当前选中的选项
+  JobListAppliedEditReasonList? selectedReasonItem;
   //表单的校验与数据
   Map<String, Map<String, dynamic>> formData = {
     'add_hours': {

+ 287 - 0
packages/cpt_uk/lib/modules/job/job_applied_revise_list/job_applied_revise_list_controller.dart

@@ -0,0 +1,287 @@
+import 'dart:ui';
+
+import 'package:domain/entity/response/uk_job_applied_revise_info_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_staff_list_entity.dart';
+import 'package:domain/repository/job_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/dialog/app_default_dialog.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+import '../job_applied_edit/job_applied_edit_page.dart';
+import '../job_applied_staff_detail/applied_staff_detail_page.dart';
+import '../job_applied_workflow/applied_workflow_page.dart';
+import '../revise_add_edit/revise_add_edit_page.dart';
+import '../revise_log/revise_log_page.dart';
+import 'job_applied_revise_list_state.dart';
+
+
+class JobAppliedReviseListController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final UKJobRepository _ukjobRepository = Get.find();
+  final JobAppliedReviseListState state = JobAppliedReviseListState();
+
+  var _curPage = 1;
+  var _needShowPlaceholder = true;
+
+  //页面PlaceHolder的展示
+  LoadState loadingState = LoadState.State_Success;
+  String? errorMessage;
+
+  //刷新页面状态
+  void changeLoadingState(LoadState state) {
+    loadingState = state;
+    update();
+  }
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,
+    controlFinishLoad: true,
+  );
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchListData();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchListData();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchListData();
+  }
+
+  /// 获取服务器数据,通知消息列表
+  Future fetchListData() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+
+    // 获取  列表
+    var listResult = await _ukjobRepository.fetchJobAppliedReviseList(
+        appliedId: state.appliedId,
+        curPage: _curPage,
+        cancelToken: cancelToken,
+    );
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<UkJobAppliedReviseInfoRows>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      if (_curPage == 1) {
+        //刷新的方式
+        state.datas.clear();
+        state.datas.addAll(list);
+        refreshController.finishRefresh();
+
+        //更新展示的状态
+        changeLoadingState(LoadState.State_Success);
+      } else {
+        //加载更多
+        state.datas.addAll(list);
+        refreshController.finishLoad();
+        update();
+      }
+    } else {
+      if (_curPage == 1) {
+        //展示无数据的布局
+        state.datas.clear();
+        changeLoadingState(LoadState.State_Empty);
+        refreshController.finishRefresh();
+      } else {
+        //展示加载完成,没有更多数据了
+        refreshController.finishLoad(IndicatorResult.noMore);
+      }
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchListData();
+    registerEventBus();
+  }
+
+  @override
+  void onClose() {
+    unregisterEventBus();
+    state.datas.clear();
+    super.onClose();
+  }
+
+  // EventBus 的事件接收
+  Subscription? subscribe;
+
+  void registerEventBus() {
+    // subscribe = bus.on(AppConstant.eventAppliedListRefresh, (arg) {
+    //   var appliedId = arg as String;
+    //   if (Utils.isNotEmpty(appliedId)) {
+    //     fetchItemByIdAndRefreshItem(appliedId);
+    //   } else {
+    //     refreshController.callRefresh();
+    //   }
+    // });
+  }
+
+  void unregisterEventBus() {
+    // bus.off(AppConstant.eventAppliedListRefresh, subscribe);
+  }
+
+  /// 搜索员工
+  void doSearch(String keyword) {
+    state.keyword = keyword;
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  /// 清空筛选条件
+  void resetFiltering() {
+    state.keyword = "";
+    state.searchController.text = "";
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  /// 展示添加员工的弹窗
+  void showAddStaffDialog() {
+
+  }
+
+  //调用接口添加员工
+  void _requestAddStaff2Applied(String selectedIds) async {
+    var result = await _jobRepository.addStaff2Job(state.appliedId, selectedIds, cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+      var addStaffEntity = result.data;
+      List<String> filteredMessages = [];
+      if (addStaffEntity != null && addStaffEntity.resultList?.isNotEmpty == true) {
+        filteredMessages = addStaffEntity.resultList!
+            .where((resultList) => resultList.result == false && Utils.isNotEmpty(resultList.msg))
+            .map((resultList) => '${resultList.name} : ${resultList.msg!}')
+            .toList();
+      }
+
+
+      if (filteredMessages.isNotEmpty) {
+        //有错误信息
+        NotifyEngine.showFailure(filteredMessages.join(" , "));
+      } else {
+        //无错误信息
+        NotifyEngine.showSuccess("Successful".tr);
+        //添加成功之后刷新页面
+        refreshController.callRefresh();
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+
+  /// 去编辑员工信息页面   0 新增  1 编辑 2 详情
+  void gotoReviseDetailPage(int? index, String appliedId, int type) {
+    Log.d("appliedId   $appliedId --- type  $type");
+    if(index != null){
+      Log.d("编辑 时 id: ${state.datas[index].id!.toString()}");
+      UKReviseAddEditPage.startInstance(type, state.datas[index].id!.toString(), (value){});
+    }else {
+      UKReviseAddEditPage.startInstance(type, appliedId, (value){});
+    }
+  }
+  /// 去logs 页面
+  void gotoReviseLogsPage(int? index, String appliedId){
+    if(index != null){
+      UKReviseLogPage.startInstance(state.datas[index].id!.toString());
+    }
+  }
+
+  /// recall 操作
+  void doRecallAction(int index) {
+    DialogEngine.show(
+      tag: 'recallActionTag',
+        widget: AppDefaultDialog(
+          title: "Confirmation".tr,
+          message: "Are you sure you want to recall this revise?".tr,
+          confirmAction: () {
+            _requestRecall(index);
+          },
+        ));
+  }
+
+  void _requestRecall(int index) async {
+    var result = await _ukjobRepository.reviseRecall(reviseId: state.datas[index].id!.toString(), cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      fetchItemByIdAndRefreshItem(state.datas[index].id!.toString());
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  /// 去展示员工状态的审核流程页面
+  void gotoAppliedWorkflowPage(UkJobAppliedStaffListRows data) {
+    UKAppliedWorkflowPage.startInstance(data.appliedId.toString());
+  }
+  
+
+  /// 根据ID获取Item对象,用于刷新
+  void fetchItemByIdAndRefreshItem(String appliedIds) async {
+    var result = await _ukjobRepository.fetchJobAppliedReviseListById(
+      appliedId: state.appliedId,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      var data = result.data;
+      if (data != null && data.rows != null && data.rows!.isNotEmpty) {
+        List<UkJobAppliedReviseInfoRows> newItem = data.rows!;
+
+        // 创建一个 Map 来加速查找
+        Map<int, UkJobAppliedReviseInfoRows> newItemMap = {for (var item in newItem) item.id!: item};
+
+        // 遍历 state.datas 进行替换
+        for (int i = 0; i < state.datas.length; i++) {
+          if (newItemMap.containsKey(state.datas[i].id)) {
+            state.datas[i] = newItemMap[state.datas[i].id]!;
+          }
+        }
+
+        //刷新
+        update();
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+}

+ 144 - 0
packages/cpt_uk/lib/modules/job/job_applied_revise_list/job_applied_revise_list_page.dart

@@ -0,0 +1,144 @@
+import 'package:cpt_uk/modules/job/job_applied_revise_list/revise_list_item.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.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_text_view.dart';
+import 'package:widgets/search_app_bar.dart';
+import 'package:widgets/widget_export.dart';
+
+
+import 'package:plugin_basic/base/base_state.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:plugin_basic/utils/ext_get_nav.dart';
+import 'package:router/path/router_path.dart';
+import 'package:shared/utils/screen_util.dart';
+import 'package:widgets/my_appbar.dart';
+
+import 'job_applied_revise_list_controller.dart';
+import 'job_applied_revise_list_state.dart';
+
+/*
+ * 已申请的页面,可以签到签出、加人、修改状态、评论等操作
+ */
+class UKJobAppliedRevisePage extends BaseStatefulPage<JobAppliedReviseListController> {
+  UKJobAppliedRevisePage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? appliedId) {
+    return Get.start(RouterPath.UKJobAppliedReviseList, arguments: {'appliedId': appliedId});
+  }
+
+  @override
+  JobAppliedReviseListController createRawController() {
+    return JobAppliedReviseListController();
+  }
+
+  @override
+  State<UKJobAppliedRevisePage> createState() => _JobAppliedState();
+}
+
+class _JobAppliedState extends BaseState<UKJobAppliedRevisePage, JobAppliedReviseListController> {
+  late JobAppliedReviseListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.appliedId = Get.arguments['appliedId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return  SafeArea(
+        bottom: MediaQuery.of(context).padding.bottom > 38,
+        top: false,
+        child: Container(
+          width: double.infinity,
+          height: double.infinity,
+          padding: EdgeInsets.only(top: ScreenUtil.getStatusBarH(context)),
+          decoration: const BoxDecoration(
+            gradient: LinearGradient(
+              colors: [
+                Color(0xFF091D44),
+                Color(0xFF245A8A),
+                Color(0xFF7F7CEC),
+              ],
+              begin: Alignment.topCenter,
+              end: Alignment.bottomCenter,
+            ),
+          ),
+          child: Column(
+            children: [
+              MyAppBar.titleBar(
+                context,
+                "Revise".tr,
+                // subTitle: "",
+                subTitleColor: ColorConstants.textGrayAECAE5,
+              ),
+              // 添加按钮
+              MyButton(
+                type: ClickType.throttle,
+                milliseconds: 500,
+                onPressed: () {
+                  FocusScope.of(context).unfocus();
+                  controller.gotoReviseDetailPage(null, state.appliedId.toString(), 0);
+                },
+                text: "Add Revise".tr,
+                textColor: ColorConstants.white,
+                fontSize: 16,
+                radius: 20,
+                backgroundColor: hexToColor("#855EF5"),
+                fontWeight: FontWeight.w500,
+              ).marginOnly(left: 15, right: 15, top: 5, bottom: 10),
+
+              //底部的列表
+              EasyRefresh(
+                controller: controller.refreshController,
+                onRefresh: controller.onRefresh,
+                onLoad: controller.loadMore,
+                child: LoadStateLayout(
+                  state: controller.loadingState,
+                  errorMessage: controller.errorMessage,
+                  errorRetry: () {
+                    controller.retryRequest();
+                  },
+                  successSliverWidget: [
+                    SliverList(
+                        delegate: SliverChildBuilderDelegate(
+                              (context, index) {
+                            return ReviseListItem(
+                              index: index,
+                              item: state.datas[index],
+                              onDetailAction: () {
+                                controller.gotoReviseDetailPage(index, state.appliedId.toString(), 2);
+                              },
+                              onEditAction: () {
+                                controller.gotoReviseDetailPage(index, state.appliedId.toString(), 1);
+                              },
+                              onLogsAction: () {
+                                controller.gotoReviseLogsPage(index, state.appliedId.toString());
+                              },
+                              onRecallAction: () {
+                                controller.doRecallAction(index);
+                              },
+                              onDeleteAction: () {
+                              },
+                            );
+                          },
+                          childCount: state.datas.length,
+                        ))
+                  ],
+                ),
+              ).expanded(),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}

+ 13 - 0
packages/cpt_uk/lib/modules/job/job_applied_revise_list/job_applied_revise_list_state.dart

@@ -0,0 +1,13 @@
+import 'package:domain/entity/response/uk_job_applied_revise_info_entity.dart';
+import 'package:flutter/material.dart';
+
+class JobAppliedReviseListState {
+  //筛选条件
+  final TextEditingController searchController = TextEditingController();
+  String keyword = "";
+
+  String? appliedId;
+
+
+  List<UkJobAppliedReviseInfoRows> datas = []; //Revised的列表
+}

+ 323 - 0
packages/cpt_uk/lib/modules/job/job_applied_revise_list/revise_list_item.dart

@@ -0,0 +1,323 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/uk_job_applied_revise_info_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_text_view.dart';
+
+/*
+ * Revise的Item布局
+ */
+class ReviseListItem extends StatelessWidget {
+  final int index;
+  final UkJobAppliedReviseInfoRows item;
+  final VoidCallback? onDetailAction;
+  final VoidCallback? onLogsAction;
+  final VoidCallback? onDeleteAction;
+  final VoidCallback? onRecallAction;
+  final VoidCallback? onEditAction;
+
+  ReviseListItem({
+    required this.index,
+    required this.item,
+    this.onDetailAction,
+    this.onLogsAction,
+    this.onDeleteAction,
+    this.onRecallAction,
+    this.onEditAction,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.symmetric(vertical: 23, horizontal: 21),
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
+      decoration: BoxDecoration(
+        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(5), // 设置圆角
+      ),
+      child: Column(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          // 姓名
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Name:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                 item.staffName??"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 身份证
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Nric".tr + ":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期时间
+              MyTextView(
+                 item.staffNric??"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 工作时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Job Time".tr + ":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                 item.jobTime??"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // // 加减小时
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   crossAxisAlignment: CrossAxisAlignment.center,
+          //   children: [
+          //     MyTextView(
+          //       "+/- Hours".tr + ":",
+          //       isFontRegular: true,
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //     ),
+          //     MyTextView(
+          //       '0',
+          //       marginLeft: 5,
+          //       isFontRegular: true,
+          //       textColor: Colors.white,
+          //       fontSize: 14,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(top: 15),
+
+          // 总小时
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Total Hours:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.totalHours != null? item.totalHours!.toString():"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 修改小时
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Revise Hours".tr + ":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.reviseHours != null? item.reviseHours!.toString():"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Status:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //状态
+              MyTextView(
+                item.statusShow == null ? "" : item.statusShow!.tr,
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 修改小时
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Create At".tr + ":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.createdAt??"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          //按钮组
+          Visibility(
+            visible: item.actionList?.isNotEmpty ?? false,
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                //编辑按钮
+                Visibility(
+                  visible: item.actionList?.contains("edit") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onEditAction?.call();
+                    },
+                    text: "Edit".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor(
+                      "#FFBB1B",
+                    ),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 5,right: 5),
+                ),
+
+                //状态工作流按钮
+                Visibility(
+                  visible: item.actionList?.contains("recall") ?? false,
+                  child: MyButton(
+                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onRecallAction?.call();
+                    },
+                    text: "Recall".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: ColorConstants.textYellowF8AE00,
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 5,right: 5),
+                ),
+
+                //状态工作流按钮
+                Visibility(
+                  visible: item.actionList?.contains("delete") ?? false,
+                  child: MyButton(
+                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onDeleteAction?.call();
+                    },
+                    text: "Delete".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: ColorConstants.textRedFF6262,
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 5,right: 5),
+                ),
+
+                //详情按钮
+                Visibility(
+                  visible: item.actionList?.contains("detail") ?? false,
+                  child: MyButton(
+                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onDetailAction?.call();
+                    },
+                    text: "Detail".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: ColorConstants.textBlue56AAFF,
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 5,right: 5),
+                ),
+
+                //日志
+                Visibility(
+                  visible: item.actionList?.contains("logs") ?? false,
+                  child: MyButton(
+                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onLogsAction?.call();
+                    },
+                    text: "Logs".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: ColorConstants.textGreen0AC074,
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 5,right: 5),
+                ),
+              ],
+            ).marginOnly(top: 18, bottom: 2),
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 40 - 6
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_controller.dart

@@ -1,18 +1,28 @@
 import 'package:domain/entity/response/staff_detail_entity.dart';
 import 'package:domain/entity/response/staff_labour_history_entity.dart';
+import 'package:domain/entity/response/uk_staff_detail_entity.dart';
+import 'package:domain/entity/response/uk_staff_labour_history_entity.dart';
 import 'package:domain/repository/job_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
+import 'package:plugin_basic/modules/preview_photo_page.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/image/image_preview.dart';
 import 'package:plugin_platform/engine/loading/loading_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:plugin_platform/http/http_result.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
 import '../job_applied_staff_reviews/applied_staff_reviews_page.dart';
 import 'applied_staff_detail_state.dart';
+import 'certification_dialog_widget.dart';
 
 class AppliedStaffDetailController extends GetxController with DioCancelableMixin {
   final JobRepository _jobRepository = Get.find();
+  final UKJobRepository _ukJobRepository = Get.find();
   final AppliedStaffDetailState state = AppliedStaffDetailState();
 
   var _curPage = 1;
@@ -64,21 +74,21 @@ class AppliedStaffDetailController extends GetxController with DioCancelableMixi
 
     // 并发执行两个请求
     var futures = [
-      _jobRepository.fetchStaffLabourHistory(
+      _ukJobRepository.fetchStaffLabourHistory(
         state.memberId,
         state.keyword,
         curPage: _curPage,
         cancelToken: cancelToken,
       ),
       state.detail == null
-          ? _jobRepository.fetchStaffDetail(state.memberId, cancelToken: cancelToken)
+          ? _ukJobRepository.fetchStaffDetail(state.memberId, cancelToken: cancelToken)
           : Future(() => HttpResult(isSuccess: true).convert(data: state.detail!)),
     ];
 
     //拿到结果
     var results = await Future.wait(futures);
-    var listResult = results[0] as HttpResult<StaffLabourHistoryEntity>;
-    var detailResult = results[1] as HttpResult<StaffDetailEntity>;
+    var listResult = results[0] as HttpResult<UkStaffLabourHistoryEntity>;
+    var detailResult = results[1] as HttpResult<UkStaffDetailEntity>;
 
     //详情数据
     if (state.detail == null && detailResult.isSuccess) {
@@ -100,7 +110,7 @@ class AppliedStaffDetailController extends GetxController with DioCancelableMixi
   }
 
   // 处理数据与展示的逻辑
-  void handleList(List<StaffLabourHistoryRows>? list) {
+  void handleList(List<UkStaffLabourHistoryRows>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_curPage == 1) {
@@ -119,6 +129,16 @@ class AppliedStaffDetailController extends GetxController with DioCancelableMixi
       }
     } else {
       if (_curPage == 1) {
+        // if(_isSearch){
+        //   // // 只需要将  job History list 展示为 空
+        //   // state.datas = [];
+        //   // update();
+        // }else {
+        //   //展示无数据的布局
+        //   state.datas.clear();
+        //   changeLoadingState(LoadState.State_Empty);
+        //   refreshController.finishRefresh();
+        // }
         //展示无数据的布局
         state.datas.clear();
         changeLoadingState(LoadState.State_Empty);
@@ -133,6 +153,7 @@ class AppliedStaffDetailController extends GetxController with DioCancelableMixi
   // 执行搜索
   void doSearch(String keyword) {
     state.keyword = keyword;
+    _curPage = 1;
     //赋值之后刷新
     // refreshController.callRefresh();
     _isSearch = true;
@@ -150,9 +171,22 @@ class AppliedStaffDetailController extends GetxController with DioCancelableMixi
     super.onClose();
   }
 
+  // 显示 证书弹框
+  void showCertificateDialog(BuildContext? context, UkStaffDetailCertificates certificateItem) {
+    DialogEngine.show(
+      tag: 'CertificateDialogTag',
+      widget: certificationDialog(
+        certificateItem: certificateItem,
+          onPreviewImageAction: (String url, List<String> urls, int?  index){
+            ImagePreviewEngine.singleImagePreview(context!, url);
+            // PreviewPhotoPage.startInstance(urls!, index??0);
+        }
+      ),
+    );
+  }
   // 去员工的评论列表页面
   void gotoRemarkHistoryPage() {
-    UKAppliedStaffReviewsPage.startInstance(state.memberId,state.detail?.name,state.detail?.remRate,state.detail?.remNum.toString());
+    UKAppliedStaffReviewsPage.startInstance(state.memberId,state.detail?.name,state.detail?.remRate?.toDouble(),state.detail?.remNum.toString());
   }
 
 }

+ 42 - 33
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_page.dart

@@ -1,4 +1,5 @@
 import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/uk_staff_detail_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:widgets/ext/ex_widget.dart';
@@ -68,43 +69,51 @@ class _AppliedStaffDetailState extends BaseState<UKAppliedStaffDetailPage, Appli
               ),
             ),
             child: Column(
+              mainAxisSize: MainAxisSize.max,
               children: [
                 MyAppBar.titleBar(context, "Staff Detail".tr),
 
-                EasyRefresh(
-                  controller: controller.refreshController,
-                  onRefresh: controller.onRefresh,
-                  onLoad: controller.loadMore,
-                  child: LoadStateLayout(
-                    state: controller.loadingState,
-                    errorMessage: controller.errorMessage,
-                    errorRetry: () {
-                      controller.retryRequest();
-                    },
-                    successSliverWidget: [
-                      //顶部用户信息
-                      SliverToBoxAdapter(
-                        child: StaffDetailWidget(detail: state.detail,onRemarkAction: (){
-                          controller.gotoRemarkHistoryPage();
-                        }),
-                      ),
+                Expanded(
+                  child: EasyRefresh(
+                    controller: controller.refreshController,
+                    onRefresh: controller.onRefresh,
+                    onLoad: controller.loadMore,
+                    child: LoadStateLayout(
+                      state: controller.loadingState,
+                      errorMessage: controller.errorMessage,
+                      errorRetry: () {
+                        controller.retryRequest();
+                      },
+                      successSliverWidget: [
+                        //顶部用户信息
+                        SliverToBoxAdapter(
+                          child: StaffDetailWidget(detail: state.detail,
+                            onRemarkAction: (){
+                              controller.gotoRemarkHistoryPage();
+                            },
+                            onScanCertificateAction: (BuildContext context, UkStaffDetailCertificates certificateItem){
+                              controller.showCertificateDialog(context, certificateItem);
+                            }
+                          ),
+                        ),
 
-                      //中间搜索布局
-                      SliverToBoxAdapter(
-                        child: _buildSearchWidget(),
-                      ),
-
-                      //底部工作历史列表
-                      SliverList(
-                          delegate: SliverChildBuilderDelegate(
-                        (context, index) {
-                          return StaffLabourHistoryItem(index: index, item: state.datas[index]);
-                        },
-                        childCount: state.datas.length,
-                      ))
-                    ],
-                  ),
-                ).marginOnly(top: 5,bottom: 5).expanded(),
+                        //中间搜索布局
+                        SliverToBoxAdapter(
+                          child: _buildSearchWidget(),
+                        ),
+                  
+                        //底部工作历史列表
+                        SliverList(
+                            delegate: SliverChildBuilderDelegate(
+                          (context, index) {
+                            return StaffLabourHistoryItem(index: index, item: state.datas[index]);
+                          },
+                          childCount: state.datas.length,
+                        ))
+                      ],
+                    ),
+                  ).marginOnly(top: 5,bottom: 5).expanded(),
+                ),
               ],
             ),
           ),

+ 5 - 4
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_state.dart

@@ -1,5 +1,6 @@
-import 'package:domain/entity/response/staff_detail_entity.dart';
-import 'package:domain/entity/response/staff_labour_history_entity.dart';
+
+import 'package:domain/entity/response/uk_staff_detail_entity.dart';
+import 'package:domain/entity/response/uk_staff_labour_history_entity.dart';
 import 'package:flutter/cupertino.dart';
 
 class AppliedStaffDetailState {
@@ -9,7 +10,7 @@ class AppliedStaffDetailState {
   String? memberId;
   String keyword = "";
 
-  StaffDetailEntity? detail;
-  List<StaffLabourHistoryRows> datas = [];
+  UkStaffDetailEntity? detail;
+  List<UkStaffLabourHistoryRows> datas = [];
 
 }

+ 180 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/certification_dialog_widget.dart

@@ -0,0 +1,180 @@
+import 'dart:typed_data';
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/uk_staff_detail_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/image/image_preview.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/round_my_text_field.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 证书查看弹窗
+ */
+class certificationDialog extends StatefulWidget {
+  UkStaffDetailCertificates certificateItem;
+  bool? isConfirmAutoClose = true;
+  final Function(String url, List<String> urls, int? index)? onPreviewImageAction;
+
+  certificationDialog({required this.certificateItem,required this.onPreviewImageAction, this.isConfirmAutoClose});
+
+  @override
+  State<certificationDialog> createState() => _certificationDialogState();
+}
+
+class _certificationDialogState extends State<certificationDialog> {
+
+
+  @override
+  void initState() {
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Stack(
+          children: [
+            //Title (如果使用 Container 为最外层容器则默认为 match_parent 的效果,除非我们限制宽度和最大高度最小高度)
+            Container(
+              padding: const EdgeInsets.symmetric(horizontal: 16.5),
+              width: double.infinity,
+              decoration: const BoxDecoration(
+                color: Colors.white,
+                borderRadius: BorderRadius.all(Radius.circular(15)),
+              ),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Center(
+                    child: MyTextView(
+                      "Show Certificate".tr,
+                      fontSize: 19,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black,
+                      marginTop: 20,
+                    ),
+                  ),
+                  Column(
+                    children: [
+                      SizedBox.fromSize(size: Size(0, 20)),
+                      Row(
+                        children: [
+                          MyTextView(
+                            "Type".tr,
+                            fontSize: 15,
+                            isFontMedium: true,
+                            textColor: const Color(0xFF666666),
+                          ),
+                          Expanded(
+                            child: MyTextView(
+                              widget.certificateItem.type.toString()??'-',
+                              fontSize: 15,
+                              isFontMedium: true,
+                              textColor: const Color(0xFF666666),
+                              marginLeft: 20,
+                            ),
+                          ),
+                        ],
+                      ),
+                      SizedBox.fromSize(size: Size(0, 10)),
+                      Row(
+                        children: [
+                          MyTextView(
+                            "Images".tr,
+                            fontSize: 15,
+                            isFontMedium: true,
+                            textColor: const Color(0xFF666666),
+                            marginRight: 20,
+                          ),
+
+                          Wrap(
+                            spacing: 2,
+                            runSpacing: 2,
+                            children: [
+                              if ((widget.certificateItem.url ?? []).isNotEmpty)
+                                ...widget.certificateItem.url!.asMap().entries.map((entry) {
+                                  int index = entry.key;
+                                  String itemUrl = entry.value;
+                                  return MyLoadImage(
+                                    itemUrl,
+                                    width: 80,
+                                    height: 80,
+                                  ).onTap(() {
+                                    widget.onPreviewImageAction?.call(itemUrl, widget.certificateItem.url!, index);});
+                                }).toList()
+                              else ...[
+                                  MyTextView(
+                                    '\\',
+                                    fontSize: 15,
+                                    isFontMedium: true,
+                                    textColor: const Color(0xFF666666),
+                                  )
+                                ]
+                            ],
+                          )
+                        ],
+                      ),
+                      SizedBox.fromSize(size: Size(0, 10)),
+                      Row(
+                        children: [
+                          MyTextView(
+                            "Status".tr,
+                            fontSize: 15,
+                            isFontMedium: true,
+                            textColor: const Color(0xFF666666),
+                          ),
+                          Expanded(
+                            child: MyTextView(
+                              widget.certificateItem.status.toString()??'-',
+                              fontSize: 15,
+                              isFontMedium: true,
+                              textColor: const Color(0xFF666666),
+                              marginLeft: 20,
+                            ),
+                          ),
+                        ],
+                      ),
+                      SizedBox.fromSize(size: Size(0, 30)),
+                    ],
+                  ),
+                ],
+              ),
+            ),
+
+            // 关闭按钮
+            Positioned(
+              right: 15,
+              top: 15,
+              child: const MyAssetImage(Assets.baseLibDialogCloseRed, width: 20.5, height: 20.5).onTap((){
+                SmartDialog.dismiss();
+              }),
+            ),
+          ]
+        )
+      ],
+    ).constrained(width: 285);
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+}

+ 214 - 160
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_detail_widget.dart

@@ -1,10 +1,12 @@
+
 import 'package:cs_resources/constants/color_constants.dart';
-import 'package:domain/entity/response/staff_detail_entity.dart';
+import 'package:domain/entity/response/uk_staff_detail_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:plugin_basic/basic_export.dart';
 import 'package:plugin_platform/engine/image/image_preview.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_load_image.dart';
@@ -14,12 +16,14 @@ import 'package:widgets/my_text_view.dart';
  * 员工的信息
  */
 class StaffDetailWidget extends StatelessWidget {
-  final StaffDetailEntity? detail;
+  final UkStaffDetailEntity? detail;
   final void Function() onRemarkAction;
+  final void Function(BuildContext context, UkStaffDetailCertificates  certItem ) onScanCertificateAction;
 
   StaffDetailWidget({
     required this.detail,
     required this.onRemarkAction,
+    required this.onScanCertificateAction,
   });
 
   @override
@@ -43,7 +47,7 @@ class StaffDetailWidget extends StatelessWidget {
               height: 100,
             ),
           )).onTap(() {
-            if (Utils.isNotEmpty(detail?.avatar)) {
+            if (detail!=null && detail!.avatar != null && Utils.isNotEmpty(detail!.avatar)) {
               ImagePreviewEngine.singleImagePreview(context, detail!.avatar!, heroTag: '112cc8a34e13');
             }
           }).marginOnly(top: 25, bottom: 15),
@@ -68,46 +72,6 @@ class StaffDetailWidget extends StatelessWidget {
             ],
           ).marginOnly(left: 22, right: 22),
 
-          //性别
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              MyTextView(
-                "${"Gender".tr}:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.sex ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
-            ],
-          ).marginOnly(left: 22, right: 22, top: 10),
-
-          //生日
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              MyTextView(
-                "DOB:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.dob ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
-            ],
-          ).marginOnly(left: 22, right: 22, top: 10),
-
           //身份证
           Row(
             mainAxisSize: MainAxisSize.max,
@@ -128,58 +92,18 @@ class StaffDetailWidget extends StatelessWidget {
             ],
           ).marginOnly(left: 22, right: 22, top: 10),
 
-          //电话号码
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              MyTextView(
-                "${"Mobile".tr}:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.mobile ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
-            ],
-          ).marginOnly(left: 22, right: 22, top: 10),
-
-          //邮箱
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              MyTextView(
-                "${"Email".tr}:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.email ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
-            ],
-          ).marginOnly(left: 22, right: 22, top: 10),
-
-          //国籍
+          //生日
           Row(
             mainAxisSize: MainAxisSize.max,
             children: [
               MyTextView(
-                "Nationality:",
+                "DOB:",
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
                 isFontRegular: true,
               ),
               MyTextView(
-                detail?.natl ?? "-",
+                detail?.dob ?? "-",
                 marginLeft: 5,
                 textColor: ColorConstants.white,
                 fontSize: 14,
@@ -188,85 +112,179 @@ class StaffDetailWidget extends StatelessWidget {
             ],
           ).marginOnly(left: 22, right: 22, top: 10),
 
-          //语言
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              MyTextView(
-                "Language:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.lang ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
-            ],
-          ).marginOnly(left: 22, right: 22, top: 10),
+          // //性别
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "${"Gender".tr}:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       detail?.sex ?? "-",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
+          //
+          // //电话号码
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "${"Mobile".tr}:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       detail?.mobile ?? "-",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
+          //
+          // //邮箱
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "${"Email".tr}:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       detail?.email ?? "-",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
+          //
+          // //国籍
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "Nationality:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       detail?.natl ?? "-",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
+          //
+          // //语言
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "Language:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       detail?.lang ?? "-",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
+          //
+          // //地址
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "Address:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       detail?.address ?? "-",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
+          //
+          // //紧急联系人
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "Emergency Name:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       detail?.emerName ?? "-",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
+          //
+          // //紧急联系人电话
+          // Row(
+          //   mainAxisSize: MainAxisSize.max,
+          //   children: [
+          //     MyTextView(
+          //       "Emergency Phone:",
+          //       textColor: ColorConstants.textGrayAECAE5,
+          //       fontSize: 14,
+          //       isFontRegular: true,
+          //     ),
+          //     MyTextView(
+          //       "----",
+          //       marginLeft: 5,
+          //       textColor: ColorConstants.white,
+          //       fontSize: 14,
+          //       isFontMedium: true,
+          //     ).expanded(),
+          //   ],
+          // ).marginOnly(left: 22, right: 22, top: 10),
 
-          //地址
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              MyTextView(
-                "Address:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.address ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
-            ],
-          ).marginOnly(left: 22, right: 22, top: 10),
+          // 	Insurance Certificate
 
-          //紧急联系人
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            children: [
-              MyTextView(
-                "Emergency Name:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.emerName ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
-            ],
-          ).marginOnly(left: 22, right: 22, top: 10),
 
-          //紧急联系人电话
-          Row(
-            mainAxisSize: MainAxisSize.max,
+          // 循环显示证书 detail.certificates
+          Column(
             children: [
-              MyTextView(
-                "Emergency Phone:",
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-                isFontRegular: true,
-              ),
-              MyTextView(
-                detail?.emerPhone ?? "-",
-                marginLeft: 5,
-                textColor: ColorConstants.white,
-                fontSize: 14,
-                isFontMedium: true,
-              ).expanded(),
+              ...(detail?.certificates?.asMap().entries.map((entry) {
+                int index = entry.key;
+                UkStaffDetailCertificates certificate = entry.value;
+                return _buildCertificateWidget(context, certificate, index);
+              }).toList() ?? []),
             ],
-          ).marginOnly(left: 22, right: 22, top: 10),
+          ),
 
           //评分
           Row(
@@ -293,4 +311,40 @@ class StaffDetailWidget extends StatelessWidget {
       ),
     );
   }
+
+  Widget _buildCertificateWidget(BuildContext context,UkStaffDetailCertificates certificateItem, int index ){
+    return Row(
+      children: [
+          MyTextView(
+            '${certificateItem.type!}:',
+            textColor: ColorConstants.textGrayAECAE5,
+            fontSize: 14,
+            isFontRegular: true,
+          ),
+          MyTextView(
+            certificateItem.status?? "",
+            textColor: _getStatusColor(certificateItem.statusColor?? ''),
+            fontSize: 14,
+            isFontRegular: true,
+            marginLeft: 5,
+          ).onTap((){
+            onScanCertificateAction?.call(context, certificateItem);
+          }),
+      ]
+    ).marginOnly(left: 22, right: 22,top: 10);
+  }
+
+  Color _getStatusColor(String statusColor) {
+    switch (statusColor) {
+      case 'springgreen':
+        return Color(0xFF0AC074);
+      case 'red':
+        return Color(0xFFFF6262);
+      case 'dodgerblue':
+        return Colors.blue;
+      default:
+        return Color(0xFFEA9F0D);
+    }
+  }
+
 }

+ 2 - 3
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_labour_history_item.dart

@@ -1,6 +1,5 @@
 import 'package:cs_resources/constants/color_constants.dart';
-import 'package:cs_resources/generated/assets.dart';
-import 'package:domain/entity/response/staff_labour_history_entity.dart';
+import 'package:domain/entity/response/uk_staff_labour_history_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
@@ -16,7 +15,7 @@ import 'package:widgets/my_text_view.dart';
  */
 class StaffLabourHistoryItem extends StatelessWidget {
   final int index;
-  final StaffLabourHistoryRows item;
+  final UkStaffLabourHistoryRows item;
 
   StaffLabourHistoryItem({
     required this.index,

+ 1 - 1
packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_page.dart

@@ -81,7 +81,7 @@ class _AppliedStaffReviewsState extends BaseState<UKAppliedStaffReviewsPage, App
             crossAxisAlignment: CrossAxisAlignment.start,
             mainAxisSize: MainAxisSize.max,
             children: [
-              MyAppBar.titleBar(context, "Staff Detail".tr),
+              MyAppBar.titleBar(context, "Remark Detail".tr),
               EasyRefresh(
                 controller: controller.refreshController,
                 onRefresh: controller.onRefresh,

+ 2 - 1
packages/cpt_uk/lib/modules/job/job_list/job_list_item.dart

@@ -51,6 +51,7 @@ class JobListItem extends StatelessWidget {
             decorationStyle: TextDecorationStyle.solid, // 可选,设置下划线的样式
           ),
 
+
           // 部门
           Row(
             mainAxisSize: MainAxisSize.max,
@@ -80,7 +81,7 @@ class JobListItem extends StatelessWidget {
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Datetime:".tr,
+                "DateTime:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,

+ 219 - 30
packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_controller.dart

@@ -1,6 +1,10 @@
-import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'dart:io';
+
+import 'package:cpt_uk/modules/job/labour_request_add/widget/labour_request_interface.dart';
+import 'package:domain/entity/response/uk_labour_request_detail_entity.dart';
 import 'package:domain/repository/labour_repository.dart';
 import 'package:domain/repository/uk_job_repository.dart';
+import 'package:domain/repository/uk_labour_repository.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
 import 'package:plugin_basic/constants/app_constant.dart';
@@ -8,29 +12,41 @@ import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
 import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/http_result.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/event_bus.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/util.dart';
 import 'package:widgets/picker/date_picker_util.dart';
 import 'package:widgets/picker/option_pick_util.dart';
+import 'package:file_picker/file_picker.dart';
 
 import '../../../widget/date_range_picker_dialog.dart';
+import '../labour_request_preselected_list/widget/preselected_add_staff.dart';
 import 'labour_request_add_state.dart';
 
-class LabourRequestAddController extends GetxController {
+class LabourRequestAddController extends GetxController with DioCancelableMixin implements CommonLabourRequestController {
   final LabourRepository _labourRepository = Get.find();
   final UKJobRepository _ukJobRepository = Get.find();
+  final UkLabourRepository _ukLabourRepository = Get.find();
   final LabourRequestAddState state = LabourRequestAddState();
 
+  late PlatformFile? _selectedPlatFormFile;
+
+
+  @override
+  CommonLabourRequestState get commonState => state;
+
   /// 获取首页的数据
   void fetchRequestDetail() async {
     //获取到数据
-    Future<HttpResult<LabourRequestEditIndexEntity>> taskFuture;
+    Future<HttpResult<UkLabourRequestDetailEntity>> taskFuture;
+    // Log.d("请求的state.appliedId  ${state.appliedId}");
     if (Utils.isNotEmpty(state.appliedId) && state.appliedId != "0") {
-      taskFuture = _labourRepository.fetchLabourRequestEditDetail(state.appliedId);
+      // Log.d("请求的state.appliedId3333  ${state.appliedId}");
+      taskFuture = _ukLabourRepository.fetchLabourRequestDetail(state.appliedId);
     } else {
-      taskFuture = _labourRepository.fetchLabourRequestAddOption();
+      taskFuture = _ukLabourRepository.fetchLabourRequestAddOption();
     }
 
     var result = await taskFuture;
@@ -41,15 +57,51 @@ class LabourRequestAddController extends GetxController {
       state.selectedDate = state.labReqOption?.jobStart == null ? null : DateTimeUtils.getDateTime(state.labReqOption!.jobStart!);
       state.selectedStartTime = state.labReqOption?.jobStart == null ? null : DateTimeUtils.getDateTime(state.labReqOption!.jobStart!);
       state.selectedEndTime = state.labReqOption?.jobEnd == null ? null : DateTimeUtils.getDateTime(state.labReqOption!.jobEnd!);
-      state.noStaff = state.labReqOption?.needNum.toString() == "0" ? "" : state.labReqOption?.needNum.toString();
+
+      Log.d("获取到的 atturl  ${state.labReqOption?.attUrl}");
+
+      state.attFilePath = state.labReqOption?.attUrl?? '';
+      state.selectedTypeId = state.labReqOption?.employmentType.toString() ?? '';
+
+      state.jobSelectJobStart = state.labReqOption?.jobStart?? '';
+      state.jobSelectJobEnd = state.labReqOption?.jobEnd?? '';
+
+      if(state.pageType == 0){
+        // 新增
+        state.noStaff = '';
+        state.amount =  '';
+      }else {
+        // 编辑/详情
+        state.noStaff = state.labReqOption?.needNum?.toString() == "0" ? "" : state.labReqOption?.needNum.toString();
+        state.amount = state.labReqOption?.amount?.toString() == "0" ? "" : state.labReqOption?.amount.toString();
+
+      }
+
       var needNumController = state.formData['no_of_staff']!['controller'];
-      needNumController.text = state.noStaff;
+      needNumController.text = state.noStaff??state.noStaff!='null'??"0";
       var amountController = state.formData['amount']!['controller'];
-      amountController.text = state.labReqOption?.amount ?? "";
-      state.selectedTemplateId = state.labReqOption?.templateId;
-      state.selectedDepartmentId = state.labReqOption?.departmentId;
+      amountController.text = state.amount??state.amount!='null'??"0";
+
+      var remarkController = state.formData['remark']!['controller'];
+      var eventController = state.formData['event']!['controller'];
+      var eventTypeController = state.formData['event_type']!['controller'];
+      var eventPaxController = state.formData['event_pax']!['controller'];
+      var revenueController = state.formData['revenue']!['controller'];
+      var positionController = state.formData['position']!['controller'];
+      var totalCostController = state.formData['total_cost']!['controller'];
+      remarkController.text = state.labReqOption?.description ?? '';
+      eventController.text = state.labReqOption?.eventName ?? "";
+      eventTypeController.text = state.labReqOption?.eventType ?? "";
+      eventPaxController.text = state.labReqOption?.passengers.toString() ?? "";
+      revenueController.text = state.labReqOption?.estRevenue ?? "";
+      positionController.text = state.labReqOption?.position ?? "";
+      totalCostController.text = state.labReqOption?.estCost ?? "";
+
+
+      state.selectedTemplateId = state.labReqOption?.templateId.toString();
+      state.selectedDepartmentId = state.labReqOption?.departmentId.toString();
       //时薪还是房间计费
-      state.chargeOptionId = state.labReqOption?.chargeList.firstWhere((element) => element.checked == "checked").value;
+      state.chargeOptionId = state.labReqOption?.chargeList!.firstWhere((element) => element.checked == "checked").value;
 
       update();
     } else {
@@ -65,10 +117,29 @@ class LabourRequestAddController extends GetxController {
 
   /// 提交
   void doSubmit() async {
+
     var needNumController = state.formData['no_of_staff']!['controller'];
     var amountController = state.formData['amount']!['controller'];
     String needNum = needNumController.text.toString();
     String amount = amountController.text.toString();
+    String? jobApplyPreId = state.preSelectedIds;
+
+    var remarkController = state.formData['remark']!['controller'];
+    var eventController = state.formData['event']!['controller'];
+    var eventTypeController = state.formData['event_type']!['controller'];
+    var eventPaxController = state.formData['event_pax']!['controller'];
+    var revenueController = state.formData['revenue']!['controller'];
+    var positionController = state.formData['position']!['controller'];
+    var totalCostController = state.formData['total_cost']!['controller'];
+
+    String event = eventController.text.toString();
+    String eventType = eventTypeController.text.toString();
+    String eventPax = eventPaxController.text.toString();
+    String revenue = revenueController.text.toString();
+    String position = positionController.text.toString();
+    String totalCost = totalCostController.text.toString();
+    String remark = remarkController.text.toString();
+
 
     if (Utils.isEmpty(state.selectedTemplateId)) {
       ToastEngine.show("Choose Job Title".tr);
@@ -92,30 +163,54 @@ class LabourRequestAddController extends GetxController {
 
     Future<HttpResult> taskFuture;
     if (state.pageType != 0 && Utils.isNotEmpty(state.appliedId) && state.appliedId != "0") {
-      taskFuture = _labourRepository.editLabourRequestSubmit(
-        state.appliedId,
-        state.selectedTemplateId,
-        "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm')}:00",
-        "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm')}:00",
-        state.selectedDepartmentId,
-        needNum,
-        'hour',
-        state.labReqOption?.serviceType == 1 ? amount : null,
+      // 编辑
+      taskFuture = _ukLabourRepository.editLabourRequestSubmit(
+        requestId: state.appliedId,
+        templateId: state.selectedTemplateId,
+        jobStart: "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm')}:00",
+        jobEnd: "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm')}:00",
+        departmentId: state.selectedDepartmentId,
+        needNum: needNum,
+        salaryBy: 'hour',
+        amount: state.labReqOption?.serviceType == 1 ? amount : null,
+        description: remark,
+        employmentType: state.selectedTypeId,
+        eventName: event,
+        eventType: eventType,
+        passengers: eventPax,
+        estRevenue: revenue,
+        position: position,
+        estCost: totalCost,
+        attUrl: state.attFilePath,
+        cancelToken: cancelToken
       );
     } else {
-      taskFuture = _ukJobRepository.addLabourRequestSubmit(
+      // 新增
+      taskFuture = _ukLabourRepository.addLabourRequestSubmit(
         templateId: state.selectedTemplateId,
         jobDate: DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd'),
-        startTime: DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm'),
-        endTime: DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm'),
+        jobStart: "${DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm')}",
+        jobEnd: "${DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm')}",
         departmentId: state.selectedDepartmentId,
         needNum: needNum,
         salaryBy: 'hour',
-        repeatDate: state.repeatDateStr,
+        repeatDateStr: state.repeatDateStr,
         amount: state.labReqOption?.serviceType == 1 ? amount : null,
+        jobApplyPreId: state.preSelectedIds,
+        description: remark,
+        employmentType: state.selectedTypeId,
+        eventName: event,
+        eventType: eventType,
+        passengers: eventPax,
+        estRevenue: revenue,
+        position: position,
+        estCost: totalCost,
+        attUrl: state.attFilePath,
+        cancelToken: cancelToken,
       );
     }
 
+
     var result = await taskFuture;
 
     //处理数据
@@ -147,7 +242,7 @@ class LabourRequestAddController extends GetxController {
     if (state.selectedTemplateId == null) {
       selectedTemplateIndex = 0;
     } else {
-      selectedTemplateIndex = state.labReqOption!.templateList.indexWhere((department) => department.value.toString() == state.selectedTemplateId);
+      selectedTemplateIndex = state.labReqOption!.templateList!.indexWhere((department) => department.value.toString() == state.selectedTemplateId);
     }
 
     if (selectedTemplateIndex < 0) {
@@ -155,10 +250,10 @@ class LabourRequestAddController extends GetxController {
     }
 
     OptionPickerUtil.showCupertinoOptionPicker(
-      items: state.labReqOption!.templateList.map((e) => e.txt!).toList(growable: false),
+      items: state.labReqOption!.templateList!.map((e) => e.txt!).toList(growable: false),
       initialSelectIndex: selectedTemplateIndex,
       onPickerChanged: (_, index) {
-        state.selectedTemplateId = state.labReqOption!.templateList[index].value!.toString();
+        state.selectedTemplateId = state.labReqOption!.templateList![index].value!.toString();
         update();
       },
     );
@@ -215,6 +310,40 @@ class LabourRequestAddController extends GetxController {
     );
   }
 
+  // 筛选 employ ment type
+  void pickEmploymentType() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    int selectedEmploymentTypeIndex;
+    if (state.selectedTypeId == null) {
+      selectedEmploymentTypeIndex = 0;
+    } else {
+      if (state.labReqOption?.employmentList != null && state.labReqOption!.employmentList!.isNotEmpty) {
+        selectedEmploymentTypeIndex = state.labReqOption!.employmentList!.indexWhere(
+                (employment) => employment.value.toString() == state.selectedTypeId
+        );
+      } else {
+        // 处理 departmentList 为空或 null 的情况
+        selectedEmploymentTypeIndex = 0;
+      }
+    }
+
+    if (selectedEmploymentTypeIndex < 0) {
+      selectedEmploymentTypeIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.labReqOption!.employmentList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedEmploymentTypeIndex,
+      onPickerChanged: (_, index) {
+        state.selectedTypeId = state.labReqOption!.employmentList![index].value!.toString();
+        update();
+      },
+    );
+  }
+
   // 筛选部门
   void pickDepartment() {
     if (state.labReqOption == null || state.pageType == 2) {
@@ -225,7 +354,14 @@ class LabourRequestAddController extends GetxController {
     if (state.selectedDepartmentId == null) {
       selectedDepartmentIndex = 0;
     } else {
-      selectedDepartmentIndex = state.labReqOption!.departmentList.indexWhere((department) => department.value.toString() == state.selectedDepartmentId);
+      if (state.labReqOption?.departmentList != null && state.labReqOption!.departmentList!.isNotEmpty) {
+        selectedDepartmentIndex = state.labReqOption!.departmentList!.indexWhere(
+                (department) => department.value.toString() == state.selectedDepartmentId
+        );
+      } else {
+        // 处理 departmentList 为空或 null 的情况
+        selectedDepartmentIndex = 0;
+      }
     }
 
     if (selectedDepartmentIndex < 0) {
@@ -233,10 +369,10 @@ class LabourRequestAddController extends GetxController {
     }
 
     OptionPickerUtil.showCupertinoOptionPicker(
-      items: state.labReqOption!.departmentList.map((e) => e.txt!).toList(growable: false),
+      items: state.labReqOption!.departmentList!.map((e) => e.txt!).toList(growable: false),
       initialSelectIndex: selectedDepartmentIndex,
       onPickerChanged: (_, index) {
-        state.selectedDepartmentId = state.labReqOption!.departmentList[index].value!.toString();
+        state.selectedDepartmentId = state.labReqOption!.departmentList![index].value!.toString();
         update();
       },
     );
@@ -254,4 +390,57 @@ class LabourRequestAddController extends GetxController {
       },
     ));
   }
+
+  // 选择预选人
+  void handlerSelectPreSelect(){
+    DialogEngine.show(
+      widget: PreselectedAddStaff(
+        jobId: '0',
+        selectedStaffIds: state.preSelectedIds,
+        confirmAction: (selectedIds, [selectedList]) {
+          state.preSelectedIds = selectedIds;
+          state.preSelectedList = selectedList;
+          state.preSelectedNames = selectedList?.map((item) => item.name).join(',');
+          update();
+        },
+      ),
+    );
+  }
+
+  // 选择单个文件
+  void pickAttFile() async {
+
+    FilePickerResult? result = await FilePicker.platform.pickFiles(
+      allowMultiple: false,
+      type: FileType.custom,
+      allowedExtensions: ['jpg', 'png', 'jpeg', 'pdf', 'docx'],
+    );
+
+    if (result != null) {
+      PlatformFile selectedPlatformFile = result.files.first;
+      Log.d("选取的文件的path:${selectedPlatformFile.path} name:${selectedPlatformFile.name}");
+      _selectedPlatFormFile = selectedPlatformFile;
+      state.attFilePath = selectedPlatformFile.path;
+
+      update();
+
+      // final fileResult = await _thRepository.uploadFile(file.path);
+      // if (fileResult.isSuccess) {
+      //   state.attFilePath = fileResult.data?.path;
+      //   update();
+      // } else {
+      //   ToastEngine.show(fileResult.errorMsg ?? "Network Load Error".tr);
+      // }
+    }
+  }
+
+  @override
+  void pickJobEnd() {
+    // TODO: implement pickJobEnd
+  }
+
+  @override
+  void pickJobStart() {
+    // TODO: implement pickJobStart
+  }
 }

Разница между файлами не показана из-за своего большого размера
+ 766 - 375
packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_page.dart


+ 94 - 3
packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_state.dart

@@ -1,14 +1,32 @@
-import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'dart:io';
+
+import 'package:cpt_uk/modules/job/labour_request_add/widget/labour_request_interface.dart';
+import 'package:domain/entity/response/uk_labour_request_detail_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_preselect_addstatff_list_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_basic/basic_export.dart';
+import 'package:shared/utils/date_time_utils.dart';
+
+class LabourRequestAddState implements CommonLabourRequestState {
 
-class LabourRequestAddState {
+  @override
+  String useInSence = 'labour_request';  // labour_request 、 labour_request_review
 
   int pageType = 0;  //页面的状态 0 是新增  1是编辑  2是详情
   String? appliedId;  //编辑和详情需要用到ID
 
   //页面对应的详情数据
-  LabourRequestEditIndexEntity? labReqOption;
+  UkLabourRequestDetailEntity? labReqOption;
+
+  @override
+  DateTime? get jobEnd => labReqOption?.jobEnd != null? DateTimeUtils.getDateTime(labReqOption!.jobEnd!): null;
+
+  @override
+  DateTime? get jobStart => labReqOption?.jobStart !=null? DateTimeUtils.getDateTime(labReqOption!.jobStart!): null;
+  @override
+  String? jobSelectJobStart;
+  @override
+  String? jobSelectJobEnd;
 
   //页面对应的选择的条件
   DateTime? selectedDate;
@@ -18,6 +36,23 @@ class LabourRequestAddState {
   String? selectedTemplateId;
   String? selectedDepartmentId;
   String? noStaff;  //成员数量
+  String? amount;
+
+  String? preSelectedNames; // 预选人姓名
+  String? preSelectedIds; // 预选人ids
+  List<UkLabourRequestPreselectAddstatffListRows>? preSelectedList = []; // 预选人列表
+
+  String? selectedTypeId;
+  String? selectedType;
+
+  String? event;
+  String? eventType;
+  String? eventPax;
+  String? estimatedRevenue;
+  String? position;
+  String? estimatedTotalCost;
+  String? remark; //备注
+  String? attFilePath; // 附件地址
 
   String? chargeOptionId;
 
@@ -37,6 +72,62 @@ class LabourRequestAddState {
       'hintText': 'Enter Amount'.tr,
       'obsecure': false,
     },
+    'remark': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event_type': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event_pax': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'revenue': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'position': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'total_cost': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
   };
 
+  int get serviceType => labReqOption?.serviceType ?? 0;
+  List<UkLabourRequestDetailLocationList>? get locationList => labReqOption?.locationList;
+  List<UkLabourRequestDetailTemplateList>? get templateList => labReqOption?.templateList;
+  List<UkLabourRequestDetailDepartmentList>? get departmentList => labReqOption?.departmentList;
+  List<UkLabourRequestDetailChargeList>? get chargeList => labReqOption?.chargeList;
+  List<UkLabourRequestDetailEmploymentList>? get employmentList => labReqOption?.employmentList;
+
 }

+ 912 - 0
packages/cpt_uk/lib/modules/job/labour_request_add/widget/lab_request_and_request_review_form.dart

@@ -0,0 +1,912 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/uk_labour_request_detail_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/log_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';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/round_my_text_field.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'labour_request_interface.dart';
+
+class CommonLabourRequestFormFields extends StatelessWidget {
+  final CommonLabourRequestController controller;
+
+  const CommonLabourRequestFormFields({Key? key, required this.controller}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final state = controller.commonState;
+    Log.d("--当前的useInSence---  ${state.useInSence}");
+    Log.d("--当前的pageType(0新增 1编辑 2详情)---  ${state.pageType}");
+
+    bool? isLabourRequestModule = state.useInSence == 'labour_request' ? true : false;
+    bool? isLabourRequestReviewModule = state.useInSence == 'labour_request_review' ? true : false;
+    bool? isAddAction = state.pageType == 0 ? true : false;
+    bool? isEditAction = state.pageType == 1 ? true : false;
+    bool? isDetailAction = state.pageType == 2 ? true : false;
+
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+        //工作标题,选择模板
+        FormRequireText(
+          text: "Job Title".tr,
+        ).marginOnly(top: 15),
+
+        //工作标题
+        Container(
+          padding: const EdgeInsets.only(left: 16, right: 10),
+          margin: const EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                state.selectedTemplateId == null || state.selectedTemplateId == "0"
+                    ? ""
+                    : state.templateList!
+                            .firstWhere((element) => element.value.toString() == state.selectedTemplateId,
+                                orElse: () => UkLabourRequestDetailTemplateList())
+                            .txt ??
+                        "",
+                fontSize: 14,
+                hint: "Choose Job Title".tr,
+                textHintColor: ColorConstants.textGrayAECAE5,
+                isFontMedium: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+
+              //下拉选图标
+              Visibility(
+                visible: state.pageType != 2,
+                child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ),
+            ],
+          ),
+        ).onTap(() {
+          FocusScope.of(context).unfocus();
+          controller.pickJobTitle();
+        }),
+
+        if(isAddAction)
+          // 新增时 工作时间筛选
+          _getAddChooseDateAndTimeWidget(context, controller, true)
+        else
+          // 编辑 和 详情时 工作时间筛选
+          _getEditOrDetailDateAndTimeWidget(context, controller, isEditAction, isDetailAction),
+
+        //工作选择部门
+        FormRequireText(
+          text: "Outlet".tr,
+        ).marginOnly(top: 15),
+
+        //选择部门
+        Container(
+          padding: const EdgeInsets.only(left: 16, right: 10),
+          margin: const EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                state.selectedDepartmentId == null || state.selectedDepartmentId == "0"
+                    ? ""
+                    : state.departmentList!
+                            .firstWhere((element) => element.value.toString() == state.selectedDepartmentId,
+                                orElse: () => UkLabourRequestDetailDepartmentList())
+                            .txt ??
+                        "",
+                fontSize: 14,
+                hint: "Choose Outlet".tr,
+                textHintColor: ColorConstants.textGrayAECAE5,
+                isFontMedium: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+              //下拉选图标
+              Visibility(
+                visible: state.pageType != 2,
+                child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ),
+            ],
+          ),
+        ).onTap(() {
+          FocusScope.of(context).unfocus();
+          controller.pickDepartment();
+        }),
+
+        //需要的人数
+        FormRequireText(
+          text: "No. of Staff".tr,
+        ).marginOnly(top: 15),
+
+        //输入框(只允许输入数字)
+        CustomTextField(
+          formKey: "no_of_staff",
+          marginLeft: 0,
+          marginRight: 0,
+          paddingTop: 0,
+          paddingBottom: 0,
+          height: 45,
+          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+          enabled: state.pageType != 2,
+          inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
+          textInputType: TextInputType.number,
+          formData: state.formData,
+          textInputAction: TextInputAction.done,
+          onSubmit: (key, value) {
+            FocusScope.of(context).unfocus();
+          },
+          marginTop: 10,
+        ),
+
+        //选择是否需要输入金额
+        Visibility(
+          visible: state.labReqOption?.serviceType == 1,
+          child: FormRequireText(
+            text: "Amount".tr,
+          ).marginOnly(top: 15),
+        ),
+
+        Visibility(
+          visible: state.labReqOption?.serviceType == 1,
+          child: CustomTextField(
+            formKey: "amount",
+            marginLeft: 0,
+            marginRight: 0,
+            paddingTop: 0,
+            paddingBottom: 0,
+            height: 45,
+            fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+            enabled: state.pageType != 2,
+            textInputType: TextInputType.number,
+            formData: state.formData,
+            textInputAction: TextInputAction.done,
+            onSubmit: (key, value) {
+              FocusScope.of(context).unfocus();
+            },
+            marginTop: 10,
+          ),
+        ),
+
+
+        // 选择预选人
+        Visibility(
+          visible: isAddAction,
+          child: FormRequireText(
+            text: "Pre Selectd".tr,
+            isRequired: false,
+          ).marginOnly(top: 15),
+        ),
+
+        //重复的预选人
+        Visibility(
+          visible: isAddAction,
+          child: Container(
+            padding: const EdgeInsets.only(left: 16, right: 10, top: 5, bottom: 5),
+            margin: const EdgeInsets.only(top: 10),
+            decoration: BoxDecoration(
+              color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+              borderRadius: const BorderRadius.all(Radius.circular(5)),
+            ),
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              mainAxisAlignment: MainAxisAlignment.start,
+              children: [
+                //横向的流式布局
+                Expanded(
+                  child: Wrap(
+                    spacing: 8.0, // 子组件之间的水平间距
+                    runSpacing: 5.0, // 子组件之间的垂直间距
+                    children: state.preSelectedNames == null
+                        ? [
+                      MyTextView(
+                        "",
+                        textColor: Colors.white,
+                        isFontRegular: true,
+                        fontSize: 14,
+                        hint: "Choose Pre Selected".tr,
+                        textHintColor: ColorConstants.textGrayAECAE5,
+                        paddingTop: 5,
+                        paddingBottom: 5,
+                        paddingLeft: 7.5,
+                        paddingRight: 7.5,
+                      )
+                    ]
+                        : List.generate(state.preSelectedNames!.split(",").length, (index) {
+                      return MyTextView(
+                        state.preSelectedNames!.split(",")[index],
+                        textColor: Colors.white,
+                        isFontRegular: true,
+                        fontSize: 14,
+                        hint: "Choose Pre Selected".tr,
+                        backgroundColor: ColorConstants.string2Color('#0AC074'),
+                        paddingTop: 5,
+                        paddingBottom: 5,
+                        paddingLeft: 7.5,
+                        paddingRight: 7.5,
+                        cornerRadius: 5.0,
+                      );
+                    }),
+                  ),
+                ),
+
+                const SizedBox(width: 10),
+
+                //下拉选图标
+                Visibility(
+                  visible: !isDetailAction,
+                  child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                ),
+              ],
+            ),
+          ).constrained(minHeight: 60).onTap(() {
+            FocusScope.of(context).unfocus();
+            controller.handlerSelectPreSelect();
+          }),
+        ),
+
+
+        // Type 选项  employment list
+        FormRequireText(
+          text: "Choose Type".tr,
+          isRequired: false,
+        ).marginOnly(top: 15),
+        Container(
+          padding: const EdgeInsets.only(left: 16, right: 10),
+          margin: const EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(isDetailAction ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                state.selectedTypeId == null || state.selectedTypeId == "0"
+                    ? ""
+                    : state.employmentList!
+                    .firstWhere((element) => element.value.toString() == state.selectedTypeId,
+                    orElse: () => UkLabourRequestDetailEmploymentList())
+                    .txt ??
+                    "",
+                fontSize: 14,
+                hint: "Choose Type".tr,
+                textHintColor: ColorConstants.textGrayAECAE5,
+                isFontMedium: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+              //下拉选图标
+              Visibility(
+                visible: !isDetailAction,
+                child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ),
+            ],
+          ),
+        ).onTap(() {
+          FocusScope.of(context).unfocus();
+          controller.pickEmploymentType();
+        }),
+
+        //Event
+        MyTextView(
+          "I.Event".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        CustomTextField(
+          formKey: "event",
+          marginLeft: 0,
+          marginRight: 0,
+          paddingTop: 0,
+          paddingBottom: 0,
+          marginTop: 10,
+          height: 45,
+          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(isDetailAction? 0.5 : 0.2),
+          enabled: !isDetailAction,
+          textInputType: TextInputType.text,
+          formData: state.formData,
+          textInputAction: TextInputAction.next,
+          onSubmit: (key, value) {
+            state.formData[key]!['focusNode'].unfocus();
+            FocusScope.of(context).requestFocus(state.formData['event_type']!['focusNode']);
+          },
+        ),
+
+        //Event Type
+        MyTextView(
+          "II.Event Type".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        CustomTextField(
+          formKey: "event_type",
+          marginLeft: 0,
+          marginRight: 0,
+          paddingTop: 0,
+          paddingBottom: 0,
+          marginTop: 10,
+          height: 45,
+          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(isDetailAction? 0.5 : 0.2),
+          enabled: !isDetailAction,
+          textInputType: TextInputType.text,
+          formData: state.formData,
+          textInputAction: TextInputAction.next,
+          onSubmit: (key, value) {
+            state.formData[key]!['focusNode'].unfocus();
+            FocusScope.of(context).requestFocus(state.formData['event_pax']!['focusNode']);
+          },
+        ),
+
+        //Event Pax
+        MyTextView(
+          "III.Event Pax".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        CustomTextField(
+          formKey: "event_pax",
+          marginLeft: 0,
+          marginRight: 0,
+          paddingTop: 0,
+          paddingBottom: 0,
+          marginTop: 10,
+          height: 45,
+          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(isDetailAction? 0.5 : 0.2),
+          enabled: !isDetailAction,
+          textInputType: TextInputType.number,
+          formData: state.formData,
+          textInputAction: TextInputAction.next,
+          onSubmit: (key, value) {
+            state.formData[key]!['focusNode'].unfocus();
+            FocusScope.of(context).requestFocus(state.formData['revenue']!['focusNode']);
+          },
+        ),
+
+        //Revenue
+        MyTextView(
+          "IV.Estimated Revenue".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        CustomTextField(
+          formKey: "revenue",
+          marginLeft: 0,
+          marginRight: 0,
+          paddingTop: 0,
+          paddingBottom: 0,
+          marginTop: 10,
+          height: 45,
+          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(isDetailAction ? 0.5 : 0.2),
+          enabled: !isDetailAction,
+          textInputType: TextInputType.number,
+          formData: state.formData,
+          textInputAction: TextInputAction.next,
+          onSubmit: (key, value) {
+            state.formData[key]!['focusNode'].unfocus();
+            FocusScope.of(context).requestFocus(state.formData['position']!['focusNode']);
+          },
+        ),
+
+        //Position
+        MyTextView(
+          "V.Position".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        CustomTextField(
+          formKey: "position",
+          marginLeft: 0,
+          marginRight: 0,
+          paddingTop: 0,
+          paddingBottom: 0,
+          marginTop: 10,
+          height: 45,
+          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(isDetailAction ? 0.5 : 0.2),
+          enabled: !isDetailAction,
+          textInputType: TextInputType.text,
+          formData: state.formData,
+          textInputAction: TextInputAction.next,
+          onSubmit: (key, value) {
+            state.formData[key]!['focusNode'].unfocus();
+            FocusScope.of(context).requestFocus(state.formData['total_cost']!['focusNode']);
+          },
+        ),
+
+        //total_cost
+        MyTextView(
+          "VI.Estimated Total Cost".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        CustomTextField(
+          formKey: "total_cost",
+          marginLeft: 0,
+          marginRight: 0,
+          paddingTop: 0,
+          paddingBottom: 0,
+          marginTop: 10,
+          height: 45,
+          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(isDetailAction? 0.5 : 0.2),
+          enabled: !isDetailAction,
+          textInputType: TextInputType.number,
+          formData: state.formData,
+          textInputAction: TextInputAction.done,
+          onSubmit: (key, value) {
+            FocusScope.of(context).unfocus();
+          },
+        ),
+
+        //输入Remark
+        MyTextView(
+          "Remark".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        IgnoreKeyboardDismiss(
+          child: Container(
+            height: 160,
+            margin: const EdgeInsets.only(top: 10),
+            padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
+            decoration: BoxDecoration(
+              color: const Color(0xFF4DCFF6).withOpacity(isDetailAction == 2 ? 0.5 : 0.2),
+              borderRadius: const BorderRadius.all(Radius.circular(5)),
+            ),
+            child: TextField(
+              cursorColor: ColorConstants.white,
+              cursorWidth: 1.5,
+              autofocus: false,
+              enabled: isAddAction || isEditAction,
+              focusNode: state.formData["remark"]!['focusNode'],
+              controller: state.formData["remark"]!['controller'],
+              // 装饰
+              decoration: InputDecoration(
+                isDense: true,
+                isCollapsed: true,
+                border: InputBorder.none,
+                hintText: state.formData["remark"]!['hintText'],
+                hintStyle: const TextStyle(
+                  color: ColorConstants.textGrayAECAE5,
+                  fontSize: 15.0,
+                  fontWeight: FontWeight.w400,
+                ),
+              ),
+              style: const TextStyle(
+                color: ColorConstants.white,
+                fontSize: 15.0,
+                fontWeight: FontWeight.w400,
+              ),
+              // 键盘动作右下角图标
+              textInputAction: TextInputAction.done,
+              onSubmitted: (value) {
+                FocusScope.of(context).unfocus();
+              },
+            ),
+          ),
+        ),
+
+        // 附件
+        _buildAttachFileWidget(context, controller, isAddAction, isEditAction, isDetailAction),
+
+        const SizedBox(height: 30),
+
+        //提交按钮
+        Visibility(
+          visible: !isDetailAction,
+          child: MyButton(
+            type: ClickType.throttle,
+            milliseconds: 500,
+            onPressed: () {
+              FocusScope.of(context).unfocus();
+              controller.doSubmit();
+            },
+            text: "Submit".tr,
+            textColor: ColorConstants.white,
+            fontSize: 16,
+            radius: 22.5,
+            backgroundColor: hexToColor("#FFBB1B"),
+            fontWeight: FontWeight.w500,
+          ).marginSymmetric(horizontal: 0, vertical: 30),
+        ),
+      ],
+    );
+  }
+
+  // 新增 时 的 选择日期 选择开始时间 选择结束时间
+  Widget _getAddChooseDateAndTimeWidget(BuildContext context, CommonLabourRequestController controller, bool isAdd){
+    final state = controller.commonState;
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        //开始时间
+        FormRequireText(
+          text: "Job Date".tr,
+        ).marginOnly(top: 15),
+        //选择开始日期
+        Container(
+          padding: const EdgeInsets.only(left: 16, right: 10),
+          margin: const EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                state.selectedDate == null ? "" : DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd'),
+                fontSize: 14,
+                hint: "Job Date".tr,
+                textHintColor: ColorConstants.textGrayAECAE5,
+                isFontMedium: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+              //下拉选图标
+              Visibility(
+                visible: state.pageType != 2,
+                child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ),
+            ],
+          ),
+        ).onTap(() {
+          FocusScope.of(context).unfocus();
+          controller.pickJobDate();
+        }),
+        // 开始时间 - 结束时间
+        Row(
+          children: [
+            Container(
+              padding: const EdgeInsets.only(left: 16, right: 10),
+              margin: const EdgeInsets.only(top: 10),
+              height: 45,
+              decoration: BoxDecoration(
+                color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+                borderRadius: const BorderRadius.all(Radius.circular(5)),
+              ),
+              child: Row(
+                mainAxisSize: MainAxisSize.max,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                mainAxisAlignment: MainAxisAlignment.start,
+                children: [
+                  MyTextView(
+                    state.selectedStartTime == null ? "" : DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm'),
+                    fontSize: 14,
+                    hint: "Job Start Time".tr,
+                    textHintColor: ColorConstants.textGrayAECAE5,
+                    isFontMedium: true,
+                    textColor: ColorConstants.white,
+                  ).expanded(),
+                  //下拉选图标
+                  Visibility(
+                    visible: state.pageType != 2,
+                    child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ),
+                ],
+              ),
+            ).onTap(() {
+              FocusScope.of(context).unfocus();
+              controller.pickStartTime();
+            }).expanded(),
+
+            //分割线
+            MyTextView(
+              "-",
+              textColor: Colors.white,
+              marginLeft: 10,
+              marginRight: 10,
+              fontSize: 14,
+              isFontRegular: true,
+            ),
+
+            //结束时间
+            Container(
+              padding: const EdgeInsets.only(left: 16, right: 10),
+              margin: const EdgeInsets.only(top: 10),
+              height: 45,
+              decoration: BoxDecoration(
+                color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+                borderRadius: const BorderRadius.all(Radius.circular(5)),
+              ),
+              child: Row(
+                mainAxisSize: MainAxisSize.max,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                mainAxisAlignment: MainAxisAlignment.start,
+                children: [
+                  MyTextView(
+                    state.selectedEndTime == null ? "" : DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm'),
+                    fontSize: 14,
+                    hint: "Job End Time".tr,
+                    textHintColor: ColorConstants.textGrayAECAE5,
+                    isFontMedium: true,
+                    textColor: ColorConstants.white,
+                  ).expanded(),
+                  //下拉选图标
+                  Visibility(
+                    visible: state.pageType != 2,
+                    child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ),
+                ],
+              ),
+            ).onTap(() {
+              FocusScope.of(context).unfocus();
+              controller.pickEndTime();
+            }).expanded(),
+          ],
+        ),
+
+
+        //重复的日期
+        MyTextView(
+          "Repeat Date".tr,
+          fontSize: 15,
+          textColor: Colors.white,
+          isFontRegular: true,
+          marginTop: 15,
+        ),
+
+        //重复的日期区间
+        Container(
+          padding: const EdgeInsets.only(left: 16, right: 10, top: 5, bottom: 5),
+          margin: const EdgeInsets.only(top: 10),
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              //横向的流式布局
+              Expanded(
+                child: Wrap(
+                  spacing: 8.0, // 子组件之间的水平间距
+                  runSpacing: 5.0, // 子组件之间的垂直间距
+                  children: state.repeatDateStr == null
+                      ? [
+                    MyTextView(
+                      "",
+                      textColor: Colors.white,
+                      isFontRegular: true,
+                      fontSize: 14,
+                      hint: "Choose Repeat Date".tr,
+                      textHintColor: ColorConstants.textGrayAECAE5,
+                      paddingTop: 5,
+                      paddingBottom: 5,
+                      paddingLeft: 7.5,
+                      paddingRight: 7.5,
+                    )
+                  ]
+                      : List.generate(state.repeatDateStr!.split(",").length, (index) {
+                    return MyTextView(
+                      state.repeatDateStr!.split(",")[index],
+                      textColor: Colors.white,
+                      isFontRegular: true,
+                      fontSize: 14,
+                      hint: "Choose Repeat Date".tr,
+                      backgroundColor: ColorConstants.string2Color('#0AC074'),
+                      paddingTop: 5,
+                      paddingBottom: 5,
+                      paddingLeft: 7.5,
+                      paddingRight: 7.5,
+                      cornerRadius: 5.0,
+                    );
+                  }),
+                ),
+              ),
+
+              const SizedBox(width: 10),
+
+              //下拉选图标
+              Visibility(
+                visible: state.pageType != 2,
+                child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ),
+            ],
+          ),
+        ).constrained(minHeight: 60).onTap(() {
+          FocusScope.of(context).unfocus();
+          controller.pickDateRange();
+        }),
+      ],
+    );
+  }
+
+  // 编辑/详情 的 时间区域
+  Widget _getEditOrDetailDateAndTimeWidget(BuildContext context, CommonLabourRequestController controller, bool isEdit, bool isDetail){
+    final state = controller.commonState;
+    // Log.d("-------${state.jobStart}---${state.jobEnd}");
+    // String jobSelectJobStart = state.jobStart !=null? DateTimeUtils.formatDate(state.jobStart!, format: 'yyyy-MM-dd HH:mm'):"";
+    // String jobSelectJobEnd = state.jobEnd !=null? DateTimeUtils.formatDate(state.jobEnd!, format: 'yyyy-MM-dd HH:mm'):"";
+
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        FormRequireText(
+          text: "Start Time".tr,
+        ).marginOnly(top: 15),
+        //开始时间
+        Container(
+          padding: const EdgeInsets.only(left: 16, right: 10),
+          margin: const EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(isDetail ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                state.jobSelectJobStart?? "",
+                fontSize: 14,
+                hint: "Start Time".tr,
+                textHintColor: ColorConstants.textGrayAECAE5,
+                isFontMedium: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+              //下拉选图标
+              Visibility(
+                visible: state.pageType != 2,
+                child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ),
+            ],
+          ),
+        ).onTap(() {
+          FocusScope.of(context).unfocus();
+          controller.pickJobStart();
+        }),
+
+
+        FormRequireText(
+          text: "End Time".tr,
+        ).marginOnly(top: 15),
+        //结束时间
+        Container(
+          padding: const EdgeInsets.only(left: 16, right: 10),
+          margin: const EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(isDetail ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                state.jobSelectJobEnd?? "",
+                fontSize: 14,
+                hint: "End Time".tr,
+                textHintColor: ColorConstants.textGrayAECAE5,
+                isFontMedium: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+              //下拉选图标
+              Visibility(
+                visible: state.pageType != 2,
+                child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ),
+            ],
+          ),
+        ).onTap(() {
+          FocusScope.of(context).unfocus();
+          controller.pickJobEnd();
+        }),
+      ]
+     );
+  }
+
+  // 附件
+  Widget _buildAttachFileWidget(BuildContext context, CommonLabourRequestController controller,bool isAdd, bool isEdit, bool isDetail){
+    final state = controller.commonState;
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        //附件文件
+        MyTextView(
+          "Attachment".tr,
+          fontSize: 15,
+          isFontRegular: true,
+          textColor: Colors.white,
+          marginTop: 15,
+        ),
+
+        // 显示和选择附件
+        Container(
+          padding: const EdgeInsets.only(left: 16),
+          margin: const EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: const Color(0xFF4DCFF6).withOpacity(isDetail == 2 ? 0.5 : 0.2),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                Utils.isNotEmpty(state.attFilePath) ? Uri.parse(state.attFilePath!).pathSegments.last : "",
+                fontSize: 14,
+                hint: "Choose Attachment".tr,
+                textHintColor: ColorConstants.textGrayAECAE5,
+                isFontMedium: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+
+              // 上传附件的图标
+              Visibility(
+                visible: !isDetail,
+                child: MyTextView(
+                  'Upload'.tr,
+                  boxHeight: 45,
+                  textAlign: TextAlign.center,
+                  boxWidth: 90,
+                  cornerRadius: 5,
+                  onClick: controller.pickAttFile,
+                  textColor: Colors.white,
+                  fontSize: 15,
+                  fontWeight: FontWeight.w400,
+                  backgroundColor: ColorConstants.textGreen0AC074,
+                ),
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}

+ 112 - 0
packages/cpt_uk/lib/modules/job/labour_request_add/widget/labour_request_interface.dart

@@ -0,0 +1,112 @@
+import 'package:domain/entity/response/uk_labour_request_detail_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+abstract class CommonLabourRequestState {
+  String? get useInSence; // labour_request  labour_request_review
+  int get pageType;  //页面的状态 0 是新增  1是编辑  2是详情
+  int get serviceType;
+  String? get selectedTemplateId;
+  dynamic get labReqOption;
+  String? get selectedDepartmentId;
+  DateTime? get selectedDate;
+  DateTime? get selectedStartTime;
+  DateTime? get selectedEndTime;
+  DateTime? get jobStart;
+  DateTime? get jobEnd;
+  String?  jobSelectJobStart;
+  String?  jobSelectJobEnd;
+  String? get repeatDateStr;
+  String? get selectedTypeId;
+  String? get preSelectedNames;
+  String? get attFilePath;
+
+  List<UkLabourRequestDetailLocationList>? get locationList;
+  List<UkLabourRequestDetailTemplateList>? get templateList;
+  List<UkLabourRequestDetailDepartmentList>? get departmentList;
+  List<UkLabourRequestDetailChargeList>? get chargeList;
+  List<UkLabourRequestDetailEmploymentList>? get employmentList;
+
+  Map<String, Map<String, dynamic>> formData = {
+    'no_of_staff': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter No. of Staff'.tr,
+      'obsecure': false,
+    },
+    'amount': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter Amount'.tr,
+      'obsecure': false,
+    },
+    'remark': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event_type': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event_pax': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'revenue': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'position': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'total_cost': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+  };
+}
+
+abstract class CommonLabourRequestController {
+  CommonLabourRequestState get commonState;
+
+  void pickJobTitle();
+  void pickJobDate();
+  void pickStartTime();
+  void pickEndTime();
+  void pickJobStart();  // 编辑状态时 修改的开始日期  YYYY-MM-DD HH:mm
+  void pickJobEnd();  // 编辑状态时 修改的结束日期  YYYY-MM-DD HH:mm
+  void pickDepartment();
+  void pickDateRange();
+  void pickAttFile();
+  void pickEmploymentType();
+  void handlerSelectPreSelect();
+  void doSubmit();
+}

+ 197 - 49
packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_item.dart

@@ -1,9 +1,10 @@
 import 'package:cs_resources/constants/color_constants.dart';
-import 'package:domain/entity/response/labour_request_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_table_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:plugin_basic/basic_export.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_text_view.dart';
@@ -13,12 +14,14 @@ import 'package:widgets/my_text_view.dart';
  */
 class LabourRequestItem extends StatelessWidget {
   final int index;
-  final LabourRequestListRows item;
+  final UkLabourRequestTableRows item;
   final VoidCallback? onStatusAction;
   final VoidCallback? onRecallAction;
   final VoidCallback? onDetailAction;
   final VoidCallback? onEditAction;
   final VoidCallback? onCopyAction;
+  final VoidCallback? onQuickCopyAction;
+  final VoidCallback? onPreSelectedClickAction;
 
   LabourRequestItem({
     required this.index,
@@ -28,6 +31,8 @@ class LabourRequestItem extends StatelessWidget {
     this.onDetailAction,
     this.onEditAction,
     this.onCopyAction,
+    this.onQuickCopyAction,
+    this.onPreSelectedClickAction,
   });
 
   @override
@@ -57,6 +62,28 @@ class LabourRequestItem extends StatelessWidget {
             decorationStyle: TextDecorationStyle.solid, // 可选,设置下划线的样式
           ),
 
+          // Event
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Event:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.eventName?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
           // 部门
           Row(
             mainAxisSize: MainAxisSize.max,
@@ -126,52 +153,177 @@ class LabourRequestItem extends StatelessWidget {
             ],
           ).marginOnly(top: 15),
 
-          // 人数
+          // 人数 、 薪水
           Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
-              MyTextView(
-                "No. of Staff:".tr,
-                isFontRegular: true,
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
+              Expanded(
+                flex: 1,
+                child:
+                  Row(
+                    children: [
+                      MyTextView(
+                        "No. of Staff:".tr,
+                        isFontRegular: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 14,
+                      ),
+                      //人数
+                      MyTextView(
+                        item.needNum?.toString()??'-',
+                        marginLeft: 5,
+                        isFontRegular: true,
+                        textColor: Colors.white,
+                        fontSize: 14,
+                      ),
+                  ],
+                )
               ),
 
-              //人数
-              MyTextView(
-                item.needNum.toString(),
-                marginLeft: 5,
-                isFontRegular: true,
-                textColor: Colors.white,
-                fontSize: 14,
-              ).expanded(),
+              // 薪水
+              Expanded(
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    MyTextView(
+                      "${"Salary".tr}:",
+                      isFontRegular: true,
+                      textColor: ColorConstants.textGrayAECAE5,
+                      fontSize: 14,
+                    ),
+
+                    //薪水
+                    MyTextView(
+                      item.salary ?? "-",
+                      marginLeft: 5,
+                      isFontRegular: true,
+                      textColor: Colors.white,
+                      fontSize: 14,
+                    ),
+                  ]
+                ),
+              )
             ],
           ).marginOnly(top: 15),
 
-          // 薪水
+          // pre select 、 job hours
           Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
+
+              Expanded(
+                flex: 1,
+                child: (
+                  Row(
+                    children: [
+                      MyTextView(
+                        "Pre Selected:".tr,
+                        isFontRegular: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 14,
+                      ),
+                      // preNum
+                      Padding(
+                        padding: const EdgeInsets.all(8.0),
+                        child: MyTextView(
+                          item.preNum?.toString()??'-',
+                          marginLeft: 5,
+                          isFontRegular: true,
+                          textColor: Colors.yellow,
+                          fontSize: 14,
+                          textDecoration: TextDecoration.underline,
+                          decorationColor: ColorConstants.textYellowFFBB1B,
+                          // 可选,设置下划线的颜色
+                          decorationThickness: 2.0,
+                          // 可选,设置下划线的粗细
+                          decorationStyle: TextDecorationStyle.solid, // 可选,设置下划线的样式
+                        ),
+                      ).onTap((){
+                        Log.d("去预选人列表页面");
+                        // 去 预选人列表页面
+                        onPreSelectedClickAction?.call();
+                      })
+                    ],
+                  )
+                )
+              ),
+
+              // job hours
+              Expanded(
+                flex: 1,
+                child: Row(
+                    mainAxisAlignment: MainAxisAlignment.start,
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      MyTextView(
+                        "${"Job Hours".tr}:",
+                        isFontRegular: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 14,
+                      ),
+
+                      //薪水
+                      MyTextView(
+                        item.jobHours ?? "-",
+                        marginLeft: 5,
+                        isFontRegular: true,
+                        textColor: Colors.white,
+                        fontSize: 14,
+                      ),
+                    ]
+                ),
+              )
+            ],
+          ).marginOnly(top: 15),
+
+          // Est Amount 、 Publish Status
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+
               MyTextView(
-                "${"Salary".tr}:",
+                "Est Amount:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
               ),
-
-              //薪水
+              // preNum
               MyTextView(
-                item.salary ?? "-",
+                item.estAmount?.toString()??"-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: Colors.white,
+                textColor: ColorConstants.textBlue06D9FF,
                 fontSize: 14,
-              ).expanded(),
+              ).marginOnly(right: 20),
             ],
           ).marginOnly(top: 15),
 
+          // publish status
+          Row(
+              mainAxisAlignment: MainAxisAlignment.start,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                MyTextView(
+                  "${"Publish Status".tr}:",
+                  isFontRegular: true,
+                  textColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                ),
+
+                MyTextView(
+                  item.publishStatus==true? "Published".tr:"Unpublished".tr,
+                  marginLeft: 5,
+                  isFontRegular: true,
+                  textColor: Colors.white,
+                  fontSize: 14,
+                ),
+              ]
+          ).marginOnly(top: 15),
+
           // 状态
           Row(
             mainAxisSize: MainAxisSize.max,
@@ -201,29 +353,6 @@ class LabourRequestItem extends StatelessWidget {
             ],
           ).marginOnly(top: 15),
 
-          // 发布状态
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              MyTextView(
-                "Publish Status:".tr,
-                isFontRegular: true,
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-              ),
-
-              //发布状态
-              MyTextView(
-                item.publishStatus ? "Published".tr : "Unpublished".tr,
-                marginLeft: 5,
-                isFontRegular: true,
-                textColor: Colors.white,
-                fontSize: 14,
-              ).expanded(),
-            ],
-          ).marginOnly(top: 15),
-
           // 创建时间
           Row(
             mainAxisSize: MainAxisSize.max,
@@ -256,14 +385,33 @@ class LabourRequestItem extends StatelessWidget {
               crossAxisAlignment: CrossAxisAlignment.center,
               children: [
                 //Copy按钮
+                // Visibility(
+                //   visible: item.actionList?.contains("copy") ?? false,
+                //   child: MyButton(
+                //     onPressed: () {
+                //       FocusScope.of(context).unfocus();
+                //       onCopyAction?.call();
+                //     },
+                //     text: "Copy".tr,
+                //     textColor: ColorConstants.white,
+                //     backgroundColor: hexToColor(
+                //       "#C009FC",
+                //     ),
+                //     radius: 17.25,
+                //     minWidth: 60,
+                //     minHeight: 35,
+                //   ).marginOnly(left: 12),
+                // ),
+
+                // repeat 快速复制
                 Visibility(
-                  visible: item.actionList?.contains("detail") ?? false,
+                  visible: item.actionList?.contains("copy") ?? false,
                   child: MyButton(
                     onPressed: () {
                       FocusScope.of(context).unfocus();
-                      onCopyAction?.call();
+                      onQuickCopyAction?.call();
                     },
-                    text: "Copy".tr,
+                    text: "Quick Copy".tr,
                     textColor: ColorConstants.white,
                     backgroundColor: hexToColor(
                       "#C009FC",

+ 89 - 11
packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_controller.dart

@@ -1,7 +1,11 @@
+import 'package:cpt_uk/modules/job/labour_request_list/widget/quick_copy_dialog_widget.dart';
+import 'package:cpt_uk/modules/job/labour_request_list/widget/quick_copy_dialog_widget_controller.dart';
 import 'package:cpt_uk/modules/job/labour_request_workflow/labour_request_workflow_page.dart';
 import 'package:domain/entity/response/labour_request_index_entity.dart';
-import 'package:domain/entity/response/labour_request_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_table_entity.dart';
 import 'package:domain/repository/labour_repository.dart';
+import 'package:domain/repository/uk_labour_repository.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
 import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
@@ -11,16 +15,20 @@ import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:plugin_platform/http/http_result.dart';
 import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/util.dart';
 import 'package:widgets/dialog/app_default_dialog.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
+import 'package:widgets/dialog/app_custom_dialog.dart';
 
 import '../labour_request_add/labour_request_add_page.dart';
+import '../labour_request_preselected_list/labour_request_preselected_list_page.dart';
 import 'labour_request_filter.dart';
 import 'labour_request_list_state.dart';
 
 class LabourRequestListController extends GetxController with DioCancelableMixin {
+  final UkLabourRepository _UKlabourRepository = Get.find();
   final LabourRepository _labourRepository = Get.find();
   final LabourRequestListState state = LabourRequestListState();
 
@@ -70,7 +78,7 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
 
     // 并发执行两个请求
     var futures = [
-      _labourRepository.fetchLabourRequestList(
+      _UKlabourRepository.fetchLabourRequestList(
         state.keyword,
         DateTimeUtils.formatDate(state.selectedStartDate, format: "yyyy-MM-dd"),
         DateTimeUtils.formatDate(state.selectedEndDate, format: "yyyy-MM-dd"),
@@ -88,7 +96,7 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
 
     //拿到结果
     var results = await Future.wait(futures);
-    var listResult = results[0] as HttpResult<LabourRequestListEntity>;
+    var listResult = results[0] as HttpResult<UkLabourRequestTableEntity>;
     var optionResult = results[1] as HttpResult<LabourRequestIndexEntity>;
 
     //选项数据
@@ -109,7 +117,7 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
   }
 
   // 处理数据与展示的逻辑
-  void handleList(List<LabourRequestListRows>? list) {
+  void handleList(List<UkLabourRequestTableRows>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_curPage == 1) {
@@ -122,6 +130,7 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
         changeLoadingState(LoadState.State_Success);
       } else {
         //加载更多
+
         state.datas.addAll(list);
         refreshController.finishLoad();
         update();
@@ -204,7 +213,7 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
 
   /// 根据ID获取Item对象,用于刷新
   void fetchItemByIdAndRefreshItem(String requestId) async {
-    var result = await _labourRepository.fetchItemByRequestId(
+    var result = await _UKlabourRepository.fetchItemByRequestId(
       requestId,
       cancelToken: cancelToken,
     );
@@ -214,7 +223,6 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
       var data = result.data;
       if (data != null && data.rows != null && data.rows!.isNotEmpty) {
         final requestItem = data.rows![0];
-
         //找到当前数据中的此 requestId,并替换对象,再刷新
         var index = state.datas.indexWhere((element) => element.requestId == requestItem.requestId);
         if (index >= 0) {
@@ -266,26 +274,96 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
   }
 
   //去详情页面
-  void gotoDetailPage(LabourRequestListRows data) {
+  void gotoDetailPage(UkLabourRequestTableRows data) {
     UKLabourRequestAddPage.startInstance(2, data.requestId.toString());
   }
 
   //去编辑页面
-  void gotoEditPage(LabourRequestListRows data) {
+  void gotoEditPage(UkLabourRequestTableRows data) {
     UKLabourRequestAddPage.startInstance(1, data.requestId.toString());
   }
 
+  // 快速复制
+  void quickCopy(UkLabourRequestTableRows data, BuildContext context) {
+    final String dialogTime = 'Repeat ${data.jobTitle} ${data.jobDate} ${data.jobTime}';
+    DialogEngine.show(
+      tag: 'QuickCopyDialog',
+      widget: AppCustomDialog(
+        title: dialogTime,
+        titleSize: 15,
+        dialogWidth: 300,
+        message: "",
+        messageBuilder: (context){
+          return QuickCopyDialogWidget(
+            confirmAction: (startDate, endDate, copyDate){},
+            cancelAction: (startDate, endDate, copyDate){},
+          );
+        },
+        confirmAutoDismiss: false,
+        confirmAction: () {
+          final QuickCopyDialogWidgetController quickCopyDialogWidgetController = Get.find();
+          // 快速复制
+          String job_date = quickCopyDialogWidgetController.state.selectedDate == null ? "" : DateTimeUtils.formatDate(quickCopyDialogWidgetController.state.selectedDate, format: 'yyyy-MM-dd');
+          String start_time = quickCopyDialogWidgetController.state.selectedStartTime == null ? "" : DateTimeUtils.formatDate(quickCopyDialogWidgetController.state.selectedStartTime, format: 'HH:mm');
+          String end_time = quickCopyDialogWidgetController.state.selectedEndTime == null ? "" : DateTimeUtils.formatDate(quickCopyDialogWidgetController.state.selectedEndTime, format: 'HH:mm');
+          if(Utils.isEmpty(job_date)){
+            ToastEngine.show("Job Date Is Empty");
+            return;
+          }
+          if(Utils.isEmpty(start_time)){
+            ToastEngine.show("Start Time Is Empty");
+            return;
+          }
+          if(Utils.isEmpty(end_time)){
+            ToastEngine.show("End Time Is Empty");
+            return;
+          }
+          doQuickCopy(data.requestId.toString(), job_date, start_time, end_time,(){
+            // 刷新列表
+            refreshController.callRefresh();
+            SmartDialog.dismiss(tag: "QuickCopyDialog");
+          });
+        },
+      ));
+  }
+
+  void doQuickCopy(String requestId, String job_date, String start_time, String end_time, Function sCallbak) async {
+    Log.d("快速拷贝的 requestId, job_date, start_time, end_time---- ${requestId}, ${job_date}, ${start_time}, ${end_time}");
+    var result = await _UKlabourRepository.quickCopyLabourRequestSubmit(
+      requestId,
+      job_date,
+      start_time,
+      end_time,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+      sCallbak?.call();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  // 去预选人列表页面
+  void gotoPreSelectedPage(UkLabourRequestTableRows data, BuildContext? context, bool publishStatus){
+    Log.d("当前得id是---- ${data.requestId}");
+    UKLabourRequestPreselectedListPage.startInstance(data.requestId.toString(), publishStatus);
+  }
+
   //去新增页面Copy
-  void gotoCopyPage(LabourRequestListRows data) {
+  void gotoCopyPage(UkLabourRequestTableRows data) {
     UKLabourRequestAddPage.startInstance(0, data.requestId.toString());
   }
 
   //去状态工作流的页面
-  void gotoWorkflowPage(LabourRequestListRows data) {
+  void gotoWorkflowPage(UkLabourRequestTableRows data) {
     UKLabourRequestWorkflowPage.startInstance(data.requestId.toString());
   }
 
-  void doRecall(LabourRequestListRows data) {
+
+  void doRecall(UkLabourRequestTableRows data) {
     DialogEngine.show(
         widget: AppDefaultDialog(
       title: "Message".tr,

+ 6 - 0
packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_page.dart

@@ -153,6 +153,12 @@ class _LabourRequestListState extends BaseState<UKLabourRequestListPage, LabourR
                           onCopyAction: (){
                             controller.gotoCopyPage(state.datas[index]);
                           },
+                          onQuickCopyAction: (){
+                            controller.quickCopy(state.datas[index], context);
+                          },
+                          onPreSelectedClickAction:(){
+                            controller.gotoPreSelectedPage(state.datas[index], context,  state.datas[index].publishStatus!);
+                          }
                         );
                       },
                       childCount: state.datas.length,

+ 2 - 2
packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_state.dart

@@ -1,5 +1,5 @@
 import 'package:domain/entity/response/labour_request_index_entity.dart';
-import 'package:domain/entity/response/labour_request_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_table_entity.dart';
 import 'package:flutter/material.dart';
 
 class LabourRequestListState {
@@ -12,6 +12,6 @@ class LabourRequestListState {
   String? selectedDepartmentId;
 
   //页面的列表数据
-  List<LabourRequestListRows> datas = [];
+  List<UkLabourRequestTableRows> datas = [];
   LabourRequestIndexEntity? indexOptions;
 }

+ 227 - 0
packages/cpt_uk/lib/modules/job/labour_request_list/widget/quick_copy_dialog_widget.dart

@@ -0,0 +1,227 @@
+import 'dart:ui';
+
+import 'package:cpt_uk/modules/job/labour_request_list/widget/quick_copy_dialog_widget_controller.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_applied_staff_search_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/search_app_bar.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/widget_export.dart';
+
+
+/*
+ *  快速复制 labourequest 弹窗
+ */
+class QuickCopyDialogWidget extends StatefulWidget {
+  void Function(DateTime? pickedDate)? pickDateAction;
+  void Function(DateTime? pickedStartTime)? pickStartTimeAction;
+  void Function(DateTime? pickedEndTime)? pickEndTimeAction;
+  void Function(DateTime? pickedDate, DateTime? pickedStartTime, DateTime? pickedEndTime) confirmAction;
+  void Function(DateTime? pickedDate, DateTime? pickedStartTime, DateTime? pickedEndTime) cancelAction;
+
+
+  QuickCopyDialogWidget({
+      super.key,
+      this.pickDateAction,
+       this.pickStartTimeAction,
+       this.pickEndTimeAction,
+       required this.confirmAction,
+        required this.cancelAction,
+  });
+
+  @override
+  State<QuickCopyDialogWidget> createState() => _QuickCopyDialogWidget();
+}
+
+class _QuickCopyDialogWidget extends State<QuickCopyDialogWidget> {
+  @override
+  void initState() {
+    super.initState();
+    Get.put(QuickCopyDialogWidgetController());
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    Get.delete<QuickCopyDialogWidgetController>();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return GetBuilder<QuickCopyDialogWidgetController>(
+      assignId: true,
+      builder: (controller) {
+        return Padding(
+          padding: const EdgeInsets.only(left: 20, right: 20),
+          child: Column(
+            children: [
+              //开始时间
+              Row(
+                children: [
+                  Expanded(
+                    child: FormRequireText(
+                      text: "Job Date".tr,
+                        textColor: Colors.black,
+                    ),
+                  ),
+                ],
+              ),
+
+              //选择时间
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: BoxDecoration(
+                  color: const Color(0xFF4DCFF6).withOpacity(0.2),
+                  borderRadius: const BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    Expanded(
+                      child: MyTextView(
+                        controller.state.selectedDate == null ? "" : DateTimeUtils.formatDate(controller.state.selectedDate, format: 'yyyy-MM-dd'),
+                        fontSize: 14,
+                        hint: "Job Date".tr,
+                        textHintColor: ColorConstants.textGrayAECAE5,
+                        isFontMedium: true,
+                        textColor: ColorConstants.black33,
+                      ),
+                    ),
+                    //下拉选图标
+                    const Visibility(
+                      visible: true,
+                      child: MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                    ),
+                  ],
+                ),
+              ).onTap(() {
+                FocusScope.of(context).unfocus();
+                controller.pickJobDate();
+              }),
+
+              const SizedBox(height: 10),
+
+              Row(
+                children: [
+                  Expanded(
+                    child: FormRequireText(
+                      text: "Job Time".tr,
+                      textColor: Colors.black,
+                    ),
+                  ),
+                ],
+              ),
+
+              Row(
+                children: [
+                  Expanded(
+                    child: Container(
+                      padding: const EdgeInsets.only(left: 16, right: 10),
+                      margin: const EdgeInsets.only(top: 10),
+                      height: 45,
+                      decoration: BoxDecoration(
+                        color: const Color(0xFF4DCFF6).withOpacity(0.2),
+                        borderRadius: const BorderRadius.all(Radius.circular(5)),
+                      ),
+                      child: Row(
+                        mainAxisSize: MainAxisSize.max,
+                        crossAxisAlignment: CrossAxisAlignment.center,
+                        mainAxisAlignment: MainAxisAlignment.start,
+                        children: [
+                          Expanded(
+                            child: MyTextView(
+                              controller.state.selectedStartTime == null ? "" : DateTimeUtils.formatDate(controller.state.selectedStartTime, format: 'HH:mm'),
+                              fontSize: 14,
+                              hint: "Start Time".tr,
+                              textHintColor: ColorConstants.textGrayAECAE5,
+                              isFontMedium: true,
+                              textColor: ColorConstants.black33,
+                            ),
+                          ),
+                          //下拉选图标
+                          const Visibility(
+                            visible: true,
+                            child: MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                          ),
+                        ],
+                      ),
+                    ).onTap(() {
+                      FocusScope.of(context).unfocus();
+                      controller.pickStartTime();
+                    }),
+                  ),
+
+                  //分割线
+                  MyTextView(
+                    "-",
+                    textColor: Colors.white,
+                    marginLeft: 10,
+                    marginRight: 10,
+                    fontSize: 14,
+                    isFontRegular: true,
+                  ),
+
+                  //结束时间
+                  Expanded(
+                    child: Container(
+                      padding: const EdgeInsets.only(left: 16, right: 10),
+                      margin: const EdgeInsets.only(top: 10),
+                      height: 45,
+                      decoration: BoxDecoration(
+                        color: const Color(0xFF4DCFF6).withOpacity(0.2),
+                        borderRadius: const BorderRadius.all(Radius.circular(5)),
+                      ),
+                      child: Row(
+                        mainAxisSize: MainAxisSize.max,
+                        crossAxisAlignment: CrossAxisAlignment.center,
+                        mainAxisAlignment: MainAxisAlignment.start,
+                        children: [
+                          MyTextView(
+                            controller.state.selectedEndTime == null ? "" : DateTimeUtils.formatDate(controller.state.selectedEndTime, format: 'HH:mm'),
+                            fontSize: 14,
+                            hint: "End Time".tr,
+                            textHintColor: ColorConstants.textGrayAECAE5,
+                            isFontMedium: true,
+                            textColor: ColorConstants.black33,
+                          ).expanded(),
+                          //下拉选图标
+                          const Visibility(
+                            visible: true,
+                            child: MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                          ),
+                        ],
+                      ),
+                    ).onTap(() {
+                      FocusScope.of(context).unfocus();
+                      controller.pickEndTime();
+                    }),
+                  ),
+                ],
+              ),
+              //选择时间
+            ],
+          ),
+        );
+      },
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+}

+ 128 - 0
packages/cpt_uk/lib/modules/job/labour_request_list/widget/quick_copy_dialog_widget_controller.dart

@@ -0,0 +1,128 @@
+import 'package:cpt_uk/modules/job/labour_request_list/widget/quick_copy_dialog_widget_state.dart';
+import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'package:domain/repository/labour_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+
+import '../../../../widget/date_range_picker_dialog.dart';
+
+class QuickCopyDialogWidgetController extends GetxController {
+  final LabourRepository _labourRepository = Get.find();
+  final UKJobRepository _ukJobRepository = Get.find();
+  final QuickCopyDialogWidgetState state = QuickCopyDialogWidgetState();
+
+
+  @override
+  void onReady() {
+    super.onReady();
+    // fetchRequestDetail();
+  }
+
+  /// 提交
+  void doSubmit() async {
+
+
+   if (state.selectedStartTime == null) {
+      ToastEngine.show("Choose Start Date".tr);
+      return;
+    } else if (state.selectedEndTime == null) {
+      ToastEngine.show("Choose End Date".tr);
+      return;
+    }
+
+    Future<HttpResult> taskFuture;
+    // if (state.pageType != 0 && Utils.isNotEmpty(state.appliedId) && state.appliedId != "0") {
+    //   taskFuture = _labourRepository.editLabourRequestSubmit(
+    //     state.appliedId,
+    //     state.selectedTemplateId,
+    //     "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm')}:00",
+    //     "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm')}:00",
+    //     state.selectedDepartmentId,
+    //     needNum,
+    //     'hour',
+    //     state.labReqOption?.serviceType == 1 ? amount : null,
+    //   );
+    // } else {
+    //   taskFuture = _ukJobRepository.addLabourRequestSubmit(
+    //     templateId: state.selectedTemplateId,
+    //     jobDate: DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd'),
+    //     startTime: DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm'),
+    //     endTime: DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm'),
+    //     departmentId: state.selectedDepartmentId,
+    //     needNum: needNum,
+    //     salaryBy: 'hour',
+    //     repeatDate: state.repeatDateStr,
+    //     amount: state.labReqOption?.serviceType == 1 ? amount : null,
+    //   );
+    // }
+
+    // var result = await taskFuture;
+
+  }
+
+  //选择日期
+  void pickJobDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.selectedDate,
+      mode: CupertinoDatePickerMode.date,
+      onDateTimeChanged: (date) {
+        state.selectedDate = date;
+        update();
+      },
+      title: "Job Date".tr,
+    );
+  }
+
+  //选择开始时间
+  void pickStartTime() {
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.selectedStartTime,
+      mode: CupertinoDatePickerMode.time,
+      onDateTimeChanged: (date) {
+        state.selectedStartTime = date;
+        update();
+      },
+      title: "Start Time".tr,
+    );
+  }
+
+  // 选择结束时间
+  void pickEndTime() {
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.selectedEndTime ?? state.selectedStartTime,
+      mode: CupertinoDatePickerMode.time,
+      onDateTimeChanged: (date) {
+        state.selectedEndTime = date;
+        update();
+      },
+      title: "End Time".tr,
+    );
+  }
+
+  //选择时间段
+  void pickDateRange() {
+    DialogEngine.show(
+        widget: DateRangePickerDialog(
+          dateRange: state.repeatDateStr,
+          confirmAction: (dateStr) {
+            Log.d("选择的时间段:$dateStr");
+            state.repeatDateStr = dateStr;
+            update();
+          },
+        ));
+  }
+}

+ 14 - 0
packages/cpt_uk/lib/modules/job/labour_request_list/widget/quick_copy_dialog_widget_state.dart

@@ -0,0 +1,14 @@
+
+import 'package:domain/entity/response/uk_labour_request_table_entity.dart';
+
+
+class QuickCopyDialogWidgetState {
+  late final UkLabourRequestTableRows itemObj;
+
+  //页面对应的选择的条件
+  DateTime? selectedDate;
+  DateTime? selectedStartTime;
+  DateTime? selectedEndTime;
+  String? repeatDateStr;  //2025-06-28,2025-06-29,2025-06-30
+
+}

+ 243 - 0
packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request-preselected_item.dart

@@ -0,0 +1,243 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/uk_labour_request_preselected_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_table_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:plugin_basic/basic_export.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';
+
+/*
+ * preselected 主页面列表Item
+ */
+class LabourRequestPreselectedItem extends StatelessWidget {
+  final int index;
+  final UkLabourRequestPreselectedListRows item;
+  bool publishStatus = true;  // true 不显示 delete 按钮
+  final VoidCallback? onDeleteAction;
+
+  LabourRequestPreselectedItem({
+    required this.index,
+    required this.item,
+    this.publishStatus = true,
+    this.onDeleteAction,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.symmetric(vertical: 23, horizontal: 21),
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
+      decoration: BoxDecoration(
+        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(5), // 设置圆角
+      ),
+      child: Column(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          //工作标题
+          MyTextView(
+            item.name ?? "-",
+            isFontMedium: true,
+            textColor: ColorConstants.textYellowFFBB1B,
+            fontSize: 14,
+            // textDecoration: TextDecoration.underline,
+            // decorationColor: ColorConstants.textYellowFFBB1B,
+            // // 可选,设置下划线的颜色
+            // decorationThickness: 2.0,
+            // // 可选,设置下划线的粗细
+            // decorationStyle: TextDecorationStyle.solid, // 可选,设置下划线的样式
+          ),
+
+          // Name
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Name:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.name ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // gender 、  idcard
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              Expanded(
+                  flex: 1,
+                  child:
+                  Row(
+                    children: [
+                      MyTextView(
+                        "Gender:".tr,
+                        isFontRegular: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 14,
+                      ),
+                      //人数
+                      MyTextView(
+                        item.sex?? "-",
+                        marginLeft: 5,
+                        isFontRegular: true,
+                        textColor: Colors.white,
+                        fontSize: 14,
+                      ),
+                    ],
+                  )
+              ),
+
+              // id card
+              Expanded(
+                child: Row(
+                    mainAxisAlignment: MainAxisAlignment.start,
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      MyTextView(
+                        "ID Card No.:".tr,
+                        isFontRegular: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 14,
+                      ),
+
+                      //薪水
+                      MyTextView(
+                        item.nric?? "-",
+                        marginLeft: 5,
+                        isFontRegular: true,
+                        textColor: Colors.white,
+                        fontSize: 14,
+                      ),
+                    ]
+                ),
+              )
+            ],
+          ).marginOnly(top: 15),
+
+          // avatar Status
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+
+              Expanded(
+                  flex: 1,
+                  child: (
+                      Row(
+                        children: [
+                          MyTextView(
+                            "Avatar:".tr,
+                            isFontRegular: true,
+                            textColor: ColorConstants.textGrayAECAE5,
+                            fontSize: 14,
+                          ),
+                          // 头像
+                          MyLoadImage(
+                            item.avatar??'-',
+                            width: 40,
+                            height: 40,
+                          ),
+                        ],
+                      )
+                  )
+              ),
+
+              // Status
+              Expanded(
+                flex: 1,
+                child: Row(
+                    mainAxisAlignment: MainAxisAlignment.start,
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      MyTextView(
+                        "Status:".tr,
+                        isFontRegular: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 14,
+                      ),
+
+                      MyTextView(
+                        item.statusShow ?? "-",
+                        marginLeft: 5,
+                        isFontRegular: true,
+                        textColor: "Approved" == item.statusShow
+                            ? ColorConstants.textGreen05DC82
+                            : "Rejected" == item.statusShow
+                            ? ColorConstants.textRedFF6262
+                            : "Recall" == item.statusShow
+                            ? ColorConstants.textYellowFFBB1B
+                            : ColorConstants.textBlue06D9FF,
+                        fontSize: 14,
+                      ),
+                    ]
+                ),
+              )
+            ],
+          ).marginOnly(top: 15),
+
+          // message
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Message:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.message ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          //按钮
+          Visibility(
+            visible: !publishStatus,
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                //删除按钮
+                MyButton(
+                  onPressed: () {
+                    onDeleteAction?.call();
+                  },
+                  text: "Delete".tr,
+                  textColor: ColorConstants.white,
+                  backgroundColor: Colors.redAccent,
+                  radius: 17.25,
+                  minWidth: 60,
+                  minHeight: 35,
+                ).marginOnly(left: 12),
+              ],
+            ).marginOnly(top: 18, bottom: 2),
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 264 - 0
packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request_preselected_list_controller.dart

@@ -0,0 +1,264 @@
+import 'package:cpt_uk/modules/job/labour_request_list/widget/quick_copy_dialog_widget.dart';
+import 'package:cpt_uk/modules/job/labour_request_list/widget/quick_copy_dialog_widget_controller.dart';
+import 'package:cpt_uk/modules/job/labour_request_preselected_list/widget/preselected_add_staff.dart';
+import 'package:cpt_uk/modules/job/labour_request_workflow/labour_request_workflow_page.dart';
+import 'package:domain/entity/response/labour_request_index_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_preselected_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_table_entity.dart';
+import 'package:domain/repository/uk_labour_repository.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/dialog/app_default_dialog.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:widgets/dialog/app_custom_dialog.dart';
+
+import '../labour_request_add/labour_request_add_page.dart';
+import 'labour_request_preselected_list_state.dart';
+
+
+class UKLabourRequestPreselectedListController extends GetxController with DioCancelableMixin {
+  final UkLabourRepository _ukLabourRepository = Get.find();
+  final LabourRequestPreselectedListState state = LabourRequestPreselectedListState();
+
+  var _curPage = 1;
+  var _needShowPlaceholder = true;
+
+  //页面PlaceHolder的展示
+  LoadState loadingState = LoadState.State_Success;
+  String? errorMessage;
+
+  //刷新页面状态
+  void changeLoadingState(LoadState state) {
+    loadingState = state;
+    update();
+  }
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,
+    controlFinishLoad: true,
+  );
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchLabourRequestList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchLabourRequestList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchLabourRequestList();
+  }
+
+  /// 获取列表数据
+  Future fetchLabourRequestList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    // 并发执行两个请求
+    var futures = [
+      _ukLabourRepository.fetchLabourRequestPreselectedList(
+        state.labourRequestId,
+        curPage: _curPage,
+        cancelToken: cancelToken,
+      ),
+    ];
+
+    //拿到结果
+    var results = await Future.wait(futures);
+    var listResult = results[0] as HttpResult<UkLabourRequestPreselectedListEntity>;
+
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<UkLabourRequestPreselectedListRows>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      if (_curPage == 1) {
+        //刷新的方式
+        state.datas.clear();
+        state.datas.addAll(list);
+        refreshController.finishRefresh();
+
+        //更新展示的状态
+        changeLoadingState(LoadState.State_Success);
+      } else {
+        //加载更多
+        state.datas.addAll(list);
+        refreshController.finishLoad();
+        update();
+      }
+    } else {
+      if (_curPage == 1) {
+        //展示无数据的布局
+        state.datas.clear();
+        changeLoadingState(LoadState.State_Empty);
+        refreshController.finishRefresh();
+      } else {
+        //展示加载完成,没有更多数据了
+        refreshController.finishLoad(IndicatorResult.noMore);
+      }
+    }
+  }
+
+  // 执行搜索
+  void doSearch(String keyword) {
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  // 清空搜索条件
+  void resetFiltering() {
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  //展示筛选的弹窗
+  void showFilterDialog() {
+
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchLabourRequestList();
+
+    registerEventBus();
+  }
+
+  @override
+  void onClose() {
+    unregisterEventBus();
+    state.datas.clear();
+    super.onClose();
+  }
+
+  // EventBus 的事件接收
+  Subscription? subscribe;
+
+  void registerEventBus() {
+    // subscribe = bus.on(AppConstant.eventLabourRequestRefresh, (arg) {
+    //   var requestId = arg as String;
+    //   if (Utils.isNotEmpty(requestId)) {
+    //
+    //   } else {
+    //     refreshController.callRefresh();
+    //   }
+    // });
+  }
+
+  void unregisterEventBus() {
+    // bus.off(AppConstant.eventLabourRequestRefresh, subscribe);
+  }
+
+  // 添加员工
+  showAddStaffDialog(){
+    DialogEngine.show(
+      widget: PreselectedAddStaff(
+        jobId: state.labourRequestId!,
+        confirmAction: (selectedIds, [selectedList]) {
+          //调用接口添加员工
+          _doPreselectedAddStaffSubmit(selectedIds);
+        },
+      ),
+    );
+  }
+
+  //调用接口添加员工
+  void _doPreselectedAddStaffSubmit(String selectedIds) async {
+    var result = await _ukLabourRepository.labourRequestPreselectedAddStaffSubmit(
+        state.labourRequestId,
+        selectedIds,
+        cancelToken: cancelToken
+    );
+
+    if (result.isSuccess) {
+      var addStaffEntity = result.data;
+      List<String> filteredMessages = [];
+      if (addStaffEntity != null && addStaffEntity.resultList?.isNotEmpty == true) {
+        filteredMessages = addStaffEntity.resultList!
+            .where((resultList) => resultList.result == false && Utils.isNotEmpty(resultList.msg))
+            .map((resultList) => '${resultList.name} : ${resultList.msg!}')
+            .toList();
+      }
+
+      if (filteredMessages.isNotEmpty) {
+        //有错误信息
+        NotifyEngine.showFailure(filteredMessages.join(" , "));
+      } else {
+        //无错误信息
+        NotifyEngine.showSuccess("Successful".tr);
+        //添加成功之后刷新页面
+        refreshController.callRefresh();
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  void deletePreselectedStaff(UkLabourRequestPreselectedListRows data, BuildContext? context) {
+    DialogEngine.show(
+      widget: AppDefaultDialog(
+        title: "Message".tr,
+        message: "Are you sure you want to delete this staff?".tr,
+        confirmAction: () {
+          doDeleteStaff(data, context);
+        },
+      ));
+  }
+
+  void doDeleteStaff(UkLabourRequestPreselectedListRows data, BuildContext? context) async {
+      final result = await _ukLabourRepository.labourRequestPreselectedDelete(
+        data.id.toString(),
+        cancelToken: cancelToken,
+      );
+
+      if (result.isSuccess) {
+        NotifyEngine.showSuccess("Successful".tr);
+
+        if (state.datas.length <= 1) {
+          refreshController.callRefresh();
+        } else {
+          // 找到对应id 删除
+          state.datas.removeWhere((item)=> item.id == data.id);
+          update();
+        }
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      }
+
+  }
+
+}

+ 139 - 0
packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request_preselected_list_page.dart

@@ -0,0 +1,139 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/base/base_state.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:plugin_basic/utils/ext_get_nav.dart';
+import 'package:router/path/router_path.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/screen_util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'labour_request-preselected_item.dart';
+import 'labour_request_preselected_list_controller.dart';
+import 'labour_request_preselected_list_state.dart';
+
+
+/*
+ * preselected 的主页列表
+ */
+class UKLabourRequestPreselectedListPage extends BaseStatefulPage<UKLabourRequestPreselectedListController> {
+  UKLabourRequestPreselectedListPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? labourRequestId, bool publishStatus) {
+    return Get.start(RouterPath.UKLabourPreselectedList,  arguments: {'labourRequestId': labourRequestId,'publishStatus':publishStatus});
+  }
+
+  @override
+  UKLabourRequestPreselectedListController createRawController() {
+    return UKLabourRequestPreselectedListController();
+  }
+
+  @override
+  State<UKLabourRequestPreselectedListPage> createState() => _LabourRequestPreselectedListState();
+}
+
+class _LabourRequestPreselectedListState extends BaseState<UKLabourRequestPreselectedListPage, UKLabourRequestPreselectedListController> {
+  late LabourRequestPreselectedListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.labourRequestId = Get.arguments['labourRequestId'];
+    state.publishStatus = Get.arguments['publishStatus'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    Log.d("00989    ${state.publishStatus}     ");
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: MediaQuery.of(context).padding.bottom > 38,
+        top: false,
+        child: Container(
+          width: double.infinity,
+          height: double.infinity,
+          padding: EdgeInsets.only(top: ScreenUtil.getStatusBarH(context)),
+          decoration: const BoxDecoration(
+            gradient: LinearGradient(
+              colors: [
+                Color(0xFF091D44),
+                Color(0xFF245A8A),
+                Color(0xFF7F7CEC),
+              ],
+              begin: Alignment.topCenter,
+              end: Alignment.bottomCenter,
+            ),
+          ),
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            children: [
+              MyAppBar.titleBar(
+                context,
+                'Pre Selected'.tr,
+                actions: [],
+              ),
+              // 添加按钮
+              Visibility(
+                visible: !state.publishStatus,
+                child: MyButton(
+                  type: ClickType.throttle,
+                  milliseconds: 500,
+                  onPressed: () {
+                    FocusScope.of(context).unfocus();
+                    controller.showAddStaffDialog();
+                  },
+                  text: "Add Staff".tr,
+                  textColor: ColorConstants.white,
+                  fontSize: 16,
+                  radius: 20,
+                  backgroundColor: hexToColor("#FFBB1B"),
+                  fontWeight: FontWeight.w500,
+                ).marginSymmetric(horizontal: 15, vertical: 15),
+              ),
+
+              //底部的列表
+              Expanded(
+                child: EasyRefresh(
+                  controller: controller.refreshController,
+                  onRefresh: controller.onRefresh,
+                  onLoad: controller.loadMore,
+                  child: LoadStateLayout(
+                    state: controller.loadingState,
+                    errorMessage: controller.errorMessage,
+                    errorRetry: () {
+                      controller.retryRequest();
+                    },
+                    successSliverWidget: [
+                      SliverList(
+                          delegate: SliverChildBuilderDelegate(
+                                (context, index) {
+                              return LabourRequestPreselectedItem(
+                                  index: index,
+                                  item: state.datas[index],
+                                  publishStatus: state.publishStatus,
+                                  onDeleteAction:(){
+                                    controller.deletePreselectedStaff(state.datas[index], context);
+                                  }
+                              );
+                            },
+                            childCount: state.datas.length,
+                          ))
+                    ],
+                  ),
+                ).expanded(),
+              ),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}

+ 10 - 0
packages/cpt_uk/lib/modules/job/labour_request_preselected_list/labour_request_preselected_list_state.dart

@@ -0,0 +1,10 @@
+
+import 'package:domain/entity/response/uk_labour_request_preselected_list_entity.dart';
+
+class  LabourRequestPreselectedListState {
+  String labourRequestId = "";
+  bool publishStatus = false;
+
+  //页面的列表数据
+  List<UkLabourRequestPreselectedListRows> datas = [];
+}

+ 349 - 0
packages/cpt_uk/lib/modules/job/labour_request_preselected_list/widget/preselected_add_staff.dart

@@ -0,0 +1,349 @@
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_applied_staff_search_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_preselect_addstatff_list_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/search_app_bar.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'preselected_add_staff_controller.dart';
+
+/*
+ * 添加员工的弹窗
+ */
+class PreselectedAddStaff extends StatefulWidget {
+  String jobId;
+  String? selectedStaffIds;
+  void Function(String selectIds, [List<UkLabourRequestPreselectAddstatffListRows>?])? confirmAction;
+
+  PreselectedAddStaff({required this.jobId, this.selectedStaffIds, this.confirmAction});
+
+  @override
+  State<PreselectedAddStaff> createState() => _PreselectedAddStaffState();
+}
+
+class _PreselectedAddStaffState extends State<PreselectedAddStaff> {
+  @override
+  void initState() {
+    super.initState();
+    Get.put(PreselectedAddStaffController());
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    Get.delete<PreselectedAddStaffController>();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return GetBuilder<PreselectedAddStaffController>(
+      assignId: true,
+      builder: (controller) {
+        return Container(
+          width: 300,
+          height: 555,
+          decoration: const BoxDecoration(
+            color: Color(0XFFF7F7F7),
+            borderRadius: BorderRadius.all(Radius.circular(15)),
+          ),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Center(
+                child: MyTextView(
+                  "Choose Staff".tr,
+                  fontSize: 19,
+                  isFontMedium: true,
+                  textColor: ColorConstants.black,
+                  marginTop: 22,
+                  marginBottom: 15,
+                  marginLeft: 22,
+                  marginRight: 22,
+                ),
+              ),
+
+              SearchAppBar(
+                value: controller.keyword,
+                searchBarHeight: 38,
+                searchBarBgColor: Colors.white,
+                searchBarBorderRadius: 15,
+                searchBarBorder: Border.all(
+                  color: Color(0XFFC3C3C3), // 设置边框颜色为灰色
+                  width: 0.5, // 设置边框宽度
+                ),
+                textHintColor: Color(0XFFAFB3B7),
+                textColor: ColorConstants.black33,
+                onSearch: (keyword) {
+                  controller.doSearch(keyword);
+                },
+                hintText: "Staff Name/ID/Phone".tr,
+                controller: controller.searchController,
+              ).marginOnly(left: 16.5, right: 1.5, bottom: 15.5),
+
+              Container(
+                color: Colors.white,
+                child: EasyRefresh(
+                  header: ClassicHeader(
+                    dragText: 'Pull to refresh'.tr,
+                    armedText: 'Release ready'.tr,
+                    readyText: 'Refreshing...'.tr,
+                    processingText: 'Refreshing...'.tr,
+                    processedText: 'Succeeded'.tr,
+                    noMoreText: 'No more'.tr,
+                    failedText: 'Failed'.tr,
+                    messageText: 'Last updated at %T'.tr,
+                    textStyle: const TextStyle(color: ColorConstants.black66, fontSize: 14),
+                    messageStyle: const TextStyle(color: ColorConstants.black66, fontSize: 12),
+                    iconTheme: const IconThemeData(color: ColorConstants.black66),
+                    backgroundColor: Colors.transparent,
+                  ),
+                  footer: ClassicFooter(
+                    dragText: 'Pull to load'.tr,
+                    armedText: 'Release ready'.tr,
+                    readyText: 'Loading...'.tr,
+                    processingText: 'Loading...'.tr,
+                    processedText: 'Succeeded'.tr,
+                    noMoreText: 'No more'.tr,
+                    failedText: 'Failed'.tr,
+                    showMessage: false,
+                    triggerOffset: 50,
+                    iconDimension: 22,
+                    textStyle: const TextStyle(color: ColorConstants.black66, fontSize: 14),
+                    messageStyle: const TextStyle(color: ColorConstants.black66, fontSize: 12),
+                    iconTheme: const IconThemeData(color: ColorConstants.black66),
+                    backgroundColor: Colors.transparent,
+                  ),
+                  controller: controller.refreshController,
+                  onRefresh: controller.onRefresh,
+                  onLoad: controller.loadMore,
+                  child: LoadStateLayout(
+                    themeColor: ColorConstants.black66,
+                    state: controller.loadingState,
+                    errorMessage: controller.errorMessage,
+                    errorRetry: () {
+                      controller.retryRequest();
+                    },
+                    successSliverWidget: [
+                      SliverList(
+                          delegate: SliverChildBuilderDelegate(
+                                (context, index) {
+                              return _buildStaffItem(controller.datas[index], () {
+                                /// Item选中与未选中设置
+                                controller.datas[index].isSelected = !controller.datas[index].isSelected;
+                                controller.update();
+                              });
+                            },
+                            childCount: controller.datas.length,
+                          ))
+                    ],
+                  ),
+                ),
+              ).expanded(),
+
+              //按钮组
+              Row(
+                children: [
+                  //取消按钮
+                  Expanded(
+                      flex: 1,
+                      child: InkWell(
+                        onTap: () {
+                          onCancel();
+                        },
+                        child: MyTextView(
+                          "Cancel".tr,
+                          fontSize: 17.5,
+                          isFontMedium: true,
+                          textAlign: TextAlign.center,
+                          textColor: Color(0XFF0085C4),
+                          cornerRadius: 3,
+                          borderWidth: 1,
+                        ),
+                      )),
+
+                  //垂直分割线
+                  Container(
+                    color: Color(0xff09141F).withOpacity(0.13),
+                    width: 0.5,
+                  ),
+
+                  //同意按钮
+                  Expanded(
+                      flex: 1,
+                      child: InkWell(
+                        onTap: () {
+                          doCallbackAction(controller);
+                        },
+                        child: MyTextView(
+                          "Submit".tr,
+                          marginLeft: 10,
+                          fontSize: 17.5,
+                          isFontMedium: true,
+                          textAlign: TextAlign.center,
+                          textColor: Color(0XFF0085C4),
+                          cornerRadius: 3,
+                        ),
+                      )),
+                ],
+              ).constrained(height: 46),
+            ],
+          ),
+        );
+      },
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  //执行回调
+  void doCallbackAction(PreselectedAddStaffController controller) {
+    onCancel();
+
+    //找到当前选中的
+    var selectedList = controller.datas.where((element) => element.isSelected).toList(growable: false);
+    if (selectedList.isNotEmpty) {
+      var ids = selectedList.map((e) => e.id.toString()).toList(growable: false);
+      String separatedIds = ids.join(',');
+
+      widget.confirmAction?.call(separatedIds, selectedList);
+    }
+
+  }
+
+  Widget _buildStaffItem(UkLabourRequestPreselectAddstatffListRows item, VoidCallback callback) {
+    return Stack(
+      children: [
+        Column(
+          children: [
+            //姓名
+            Row(
+              children: [
+                MyTextView(
+                  "Name:".tr,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  marginRight: 3,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.name ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ),
+
+            //头像
+            Row(
+              children: [
+                MyTextView(
+                  "Avatar:".tr,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  marginRight: 3,
+                  isFontRegular: true,
+                ),
+                MyLoadImage(
+                  item.profilePicture ?? "",
+                  width: 25,
+                  height: 25,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            //性别
+            Row(
+              children: [
+                MyTextView(
+                  "Gender:".tr,
+                  marginRight: 3,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.gender ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            //身份证
+            Row(
+              children: [
+                MyTextView(
+                  "ID Card No.:".tr,
+                  marginRight: 3,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.nric ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            //status
+            Row(
+                mainAxisAlignment: MainAxisAlignment.start,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  MyTextView(
+                    "Status:".tr,
+                    isFontRegular: true,
+                    textColor: ColorConstants.textGrayAECAE5,
+                    fontSize: 14,
+                  ),
+
+                  MyTextView(
+                    item.status == null? "-" : item.status.toString(),
+                    marginLeft: 5,
+                    isFontRegular: true,
+                    textColor: Colors.red,
+                    fontSize: 14,
+                  ),
+                ]
+            ),
+
+            Container(
+              margin: EdgeInsets.only(top: 19),
+              width: double.infinity,
+              height: 1,
+              color: Color(0XFFF7F7F7),
+            )
+          ],
+        ).paddingOnly(left: 19, right: 20, top: 17),
+
+        //是否勾选
+        MyAssetImage(
+          item.isSelected ? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedGrayIcon,
+          width: 20.5,
+          height: 20.5,
+        ).alignRight().marginOnly(right: 20, top: 17.5),
+      ],
+    ).onTap((){
+      callback?.call();
+    });
+  }
+}

+ 136 - 0
packages/cpt_uk/lib/modules/job/labour_request_preselected_list/widget/preselected_add_staff_controller.dart

@@ -0,0 +1,136 @@
+import 'package:domain/entity/response/job_list_applied_staff_search_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_preselect_addstatff_list_entity.dart';
+import 'package:domain/repository/job_repository.dart';
+import 'package:domain/repository/uk_labour_repository.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 添加员工的弹窗的控制器
+ */
+class PreselectedAddStaffController extends GetxController with DioCancelableMixin {
+  final UkLabourRepository _labourRepository = Get.find();
+
+  TextEditingController searchController = TextEditingController();
+
+  var _curPage = 1;
+  var _needShowPlaceholder = true;
+
+  //页面PlaceHolder的展示
+  LoadState loadingState = LoadState.State_Success;
+  String? errorMessage;
+
+  String keyword = "";
+  String? jobId = null;
+  List<UkLabourRequestPreselectAddstatffListRows> datas = [];
+
+  //刷新页面状态
+  void changeLoadingState(LoadState state) {
+    loadingState = state;
+    update();
+  }
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,
+    controlFinishLoad: true,
+  );
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchAllStaffList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchAllStaffList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchAllStaffList();
+  }
+
+  /// 获取列表数据
+  Future fetchAllStaffList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    // 获取 Staff 列表
+    var listResult = await _labourRepository.fetchtPreselectedAddStaffList(
+      keyword,
+      jobId,
+      curPage: _curPage,
+      cancelToken: cancelToken,
+    );
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<UkLabourRequestPreselectAddstatffListRows>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      if (_curPage == 1) {
+        //刷新的方式
+        datas.clear();
+        datas.addAll(list);
+        refreshController.finishRefresh();
+
+        //更新展示的状态
+        changeLoadingState(LoadState.State_Success);
+      } else {
+        //加载更多
+        datas.addAll(list);
+        refreshController.finishLoad();
+        update();
+      }
+    } else {
+      if (_curPage == 1) {
+        //展示无数据的布局
+        datas.clear();
+        changeLoadingState(LoadState.State_Empty);
+        refreshController.finishRefresh();
+      } else {
+        //展示加载完成,没有更多数据了
+        refreshController.finishLoad(IndicatorResult.noMore);
+      }
+    }
+  }
+
+  //搜索
+  void doSearch(String keyword) {
+    this.keyword = keyword;
+    refreshController.callRefresh();
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchAllStaffList();
+  }
+
+  @override
+  void onClose() {
+    datas.clear();
+    super.onClose();
+  }
+}

+ 108 - 0
packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_controller.dart

@@ -0,0 +1,108 @@
+import 'package:domain/entity/response/add_edit_revise_view_s_g_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_revise_edit_detail_entity.dart';
+import 'package:domain/repository/job_sg_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:shared/utils/util.dart';
+
+import 'revise_add_edit_state.dart';
+
+class ReviseAddEditController extends GetxController with DioCancelableMixin {
+  final JobSGRepository _jobRepository = Get.find();
+  final UKJobRepository _ukJobRepository = Get.find();
+  final ReviseAddEditState state = ReviseAddEditState();
+
+  /// 获取首页的数据
+  void fetchRequestDetail() async {
+    //获取到数据
+    Future<HttpResult> taskFuture;
+    if (state.pageType != 0 && Utils.isNotEmpty(state.id) && state.id != "0") {
+      // 编辑/详情
+      taskFuture = _ukJobRepository.fetchEditReviseDetailInfo(reviseId: state.id, cancelToken: cancelToken);
+    } else {
+      // 新增
+      taskFuture = _ukJobRepository.fetchAddReviseDetailInfo(appliedId: state.id, cancelToken: cancelToken);
+    }
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      state.addEditEntity = result.data;
+
+      TextEditingController reviseHourController = state.formData['revise_hour']!['controller'];
+      TextEditingController reasonController = state.formData['reason']!['controller'];
+
+      reviseHourController.text = state.addEditEntity?.revise?.reviseHours ?? "";
+      reasonController.text = state.addEditEntity?.revise?.rejectRemark ?? "";
+
+      update();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchRequestDetail();
+  }
+
+  /// 提交
+  void doSubmit() async {
+    TextEditingController reviseHourController = state.formData['revise_hour']!['controller'];
+    TextEditingController reasonController = state.formData['reason']!['controller'];
+    String reviseHour = reviseHourController.text.toString();
+    String reason = reasonController.text.toString();
+
+    if (Utils.isEmpty(reviseHour)) {
+      ToastEngine.show("Enter Revise Hour".tr);
+      return;
+    } else if (Utils.isEmpty(reason)) {
+      ToastEngine.show("Enter Reason".tr);
+      return;
+    }
+
+    Future<HttpResult> taskFuture;
+    if (state.pageType != 0 && Utils.isNotEmpty(state.id) && state.id != "0") {
+      taskFuture = _ukJobRepository.reviseEditSubmit(
+        reviseId: state.id,
+        reviseHours: reviseHour,
+        reason: reason,
+        cancelToken: cancelToken,
+      );
+    } else {
+      taskFuture = _ukJobRepository.reviseAddSubmit(
+        appliedId: state.id,
+        reviseHours: reviseHour,
+        reason: reason,
+        cancelToken: cancelToken,
+      );
+    }
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //根据类型刷新
+      if (state.pageType != 0 && Utils.isNotEmpty(state.id) && state.id != "0") {
+        //编辑就发送指定的 reviseId 刷新
+        state.cb?.call(state.id ?? "");
+      } else {
+        //新增的就发送空
+        state.cb?.call("");
+      }
+
+      Get.back();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+}

+ 70 - 0
packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_item.dart

@@ -0,0 +1,70 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_applied_list_s_g_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:plugin_basic/basic_export.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';
+import 'package:widgets/shatter/border_select_widget.dart';
+
+/**
+ * 每一个选项
+ */
+class ReviseAddEditItem extends StatelessWidget {
+  final String title;
+  final String content;
+
+  ReviseAddEditItem({
+    required this.title,
+    required this.content,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+
+        //工作标题,选择模板
+        MyTextView(
+          title,
+          textColor:ColorConstants.white,
+          isFontRegular: true,
+          marginTop: 14,
+          fontSize: 15,
+        ),
+
+        //工作标题
+        Container(
+          padding: EdgeInsets.only(left: 16, right: 10),
+          margin: EdgeInsets.only(top: 10),
+          height: 45,
+          decoration: BoxDecoration(
+            color: Color(0xFF4DCFF6).withOpacity(0.5),
+            borderRadius: const BorderRadius.all(Radius.circular(5)),
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              MyTextView(
+                content,
+                fontSize: 15,
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+              ).expanded(),
+
+            ],
+          ),
+        ),
+
+      ],
+    );
+  }
+}

+ 220 - 0
packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_page.dart

@@ -0,0 +1,220 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/base/base_state.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:plugin_basic/utils/ext_get_nav.dart';
+import 'package:router/path/router_path.dart';
+import 'package:shared/utils/screen_util.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+
+import 'package:widgets/no_shadow_scroll_behavior.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/round_my_text_field.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'revise_add_edit_controller.dart';
+import 'revise_add_edit_item.dart';
+import 'revise_add_edit_state.dart';
+
+/**
+ * Revise数据的添加,编辑,详情的页面
+ */
+class UKReviseAddEditPage extends BaseStatefulPage<ReviseAddEditController> {
+  UKReviseAddEditPage({Key? key}) : super(key: key);
+
+  //启动当前页面,pageType 0 是新增  1是编辑  2是详情
+  static void startInstance(int pageType, String? id, void Function(dynamic value)? cb) {
+    return Get.start(RouterPath.UKJobAppliedReviseAddEdit, arguments: {'pageType': pageType, 'id': id,'cb': cb});
+  }
+
+  @override
+  ReviseAddEditController createRawController() {
+    return ReviseAddEditController();
+  }
+
+  @override
+  State<UKReviseAddEditPage> createState() => _LabourRequestAddState();
+}
+
+class _LabourRequestAddState extends BaseState<UKReviseAddEditPage, ReviseAddEditController> {
+  late ReviseAddEditState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.pageType = Get.arguments['pageType'];
+    state.id = Get.arguments['id'];
+    state.cb = Get.arguments['cb'] as void Function(dynamic)?;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return Scaffold(
+        extendBodyBehindAppBar: true,
+        appBar: MyAppBar.appBar(
+            context,
+            state.pageType == 0
+                ? "Add Revise".tr
+                : state.pageType == 1
+                    ? "Edit Revise".tr
+                    : "Detail".tr),
+        body: SafeArea(
+        bottom: MediaQuery.of(context).padding.bottom > 38,
+          top: false,
+          child: Container(
+            width: double.infinity,
+            height: double.infinity,
+            padding: EdgeInsets.only(top: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1),
+            decoration: const BoxDecoration(
+              gradient: LinearGradient(
+                colors: [
+                  Color(0xFF091D44),
+                  Color(0xFF245A8A),
+                  Color(0xFF7F7CEC),
+                ],
+                begin: Alignment.topCenter,
+                end: Alignment.bottomCenter,
+              ),
+            ),
+            child: Scrollbar(
+              child: ScrollConfiguration(
+                behavior: NoShadowScrollBehavior(),
+                child: SingleChildScrollView(
+                  scrollDirection: Axis.vertical,
+                  physics: const BouncingScrollPhysics(),
+                  child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      ReviseAddEditItem(title: "Staff Name".tr, content: state.addEditEntity?.applied?.memberName ?? ""),
+
+                      ReviseAddEditItem(title: "Job Start Time".tr, content: state.addEditEntity?.startTime ?? ""),
+
+                      ReviseAddEditItem(title: "Job End Time".tr, content: state.addEditEntity?.endTime ?? ""),
+
+                      ReviseAddEditItem(title: "Security Clock In".tr, content: state.addEditEntity?.securityIn ?? ""),
+
+                      ReviseAddEditItem(title: "Security Clock Out".tr, content: state.addEditEntity?.securityOut ?? ""),
+
+                      ReviseAddEditItem(title: "Work Clock In".tr, content: state.addEditEntity?.workIn ?? ""),
+
+                      ReviseAddEditItem(title: "Work Clock Out".tr, content: state.addEditEntity?.workOut ?? ""),
+
+                      ReviseAddEditItem(title: "+/- Hours".tr, content: state.addEditEntity?.adjustHours.toString() ?? ""),
+
+
+                      //修改的小时
+                      FormRequireText(
+                        fontSize: 15,
+                        text: "Revise Hours".tr,
+                      ).marginOnly(top: 15),
+
+                      //输入框
+                      CustomTextField(
+                        formKey: "revise_hour",
+                        marginLeft: 0,
+                        marginRight: 0,
+                        paddingTop: 0,
+                        paddingBottom: 0,
+                        height: 45,
+                        fillBackgroundColor: Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+                        enabled: state.pageType != 2,
+                        textInputType: TextInputType.number,
+                        formData: state.formData,
+                        textInputAction: TextInputAction.next,
+                        onSubmit: (key, value) {
+                          state.formData[key]!['focusNode'].unfocus();
+                          FocusScope.of(context).requestFocus(state.formData['reason']!['focusNode']);
+                        },
+                        marginTop: 10,
+                      ),
+
+                      //修改的原因
+                      FormRequireText(
+                        fontSize: 15,
+                        text: "Reason".tr,
+                      ).marginOnly(top: 15),
+
+                      //输入框
+                      IgnoreKeyboardDismiss(
+                        child: Container(
+                          height: 160,
+                          padding: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
+                          decoration: BoxDecoration(
+                            color: Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
+                            borderRadius: const BorderRadius.all(Radius.circular(5)),
+                          ),
+                          child: TextField(
+                            enabled: state.pageType != 2,
+                            cursorColor: ColorConstants.white,
+                            cursorWidth: 1.5,
+                            autofocus: false,
+                            controller: state.formData["reason"]!['controller'],
+                            focusNode: state.formData["reason"]!['focusNode'],
+                            obscureText: state.formData["reason"]!['obsecure'],
+                            // 装饰
+                            decoration: InputDecoration(
+                              isDense: true,
+                              isCollapsed: true,
+                              border: InputBorder.none,
+                              hintText: state.formData["reason"]!['hintText'],
+                              hintStyle: TextStyle(
+                                color: ColorConstants.textGrayAECAE5,
+                                fontSize: 15.0,
+                                fontWeight: FontWeight.w400,
+                              ),
+                            ),
+                            style: TextStyle(
+                              color: ColorConstants.white,
+                              fontSize: 15.0,
+                              fontWeight: FontWeight.w400,
+                            ),
+                            // 键盘动作右下角图标
+                            textInputAction: TextInputAction.done,
+                            onSubmitted: (value) {
+                              FocusScope.of(context).unfocus();
+                              controller.doSubmit();
+                            },
+                          ),
+                        ),
+                      ).marginOnly(top: 10),
+
+                      //提交按钮
+                      Visibility(
+                        visible: state.pageType != 2,
+                        child: MyButton(
+                          type: ClickType.throttle,
+                          milliseconds: 500,
+                          onPressed: () {
+                            FocusScope.of(context).unfocus();
+                            controller.doSubmit();
+                          },
+                          text: "Submit".tr,
+                          textColor: ColorConstants.white,
+                          fontSize: 16,
+                          radius: 22.5,
+                          backgroundColor: hexToColor("#FFBB1B"),
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 20),
+                      ),
+
+                      SizedBox(height: 20),
+                    ],
+                  ).paddingOnly(left: 15, right: 15),
+                ),
+              ),
+            ),
+          ),
+        ),
+      );
+    });
+  }
+}

+ 40 - 0
packages/cpt_uk/lib/modules/job/revise_add_edit/revise_add_edit_state.dart

@@ -0,0 +1,40 @@
+import 'package:domain/entity/response/add_edit_revise_view_s_g_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_revise_add_detail_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_revise_edit_detail_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class ReviseAddEditState {
+
+  int pageType = 0;  //页面的状态 0 是新增  1是编辑  2是详情
+
+  get isAdd => pageType == 0;
+  get isEdit => pageType == 1;
+  get isDetail => pageType == 2;
+
+  String? id;  //编辑和详情需要用到ID,新增是 appliedId  编辑和详情是 reviseId
+  void Function(dynamic value)? cb;
+
+  //页面对应的详情数据
+  UkJobAppliedReviseEditDetailEntity? addEditEntity;
+
+
+  //表单的校验与数据
+  Map<String, Map<String, dynamic>> formData = {
+    'revise_hour': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'reason': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+  };
+
+}

+ 101 - 0
packages/cpt_uk/lib/modules/job/revise_log/revise_log_controller.dart

@@ -0,0 +1,101 @@
+import 'package:domain/entity/response/revise_log_s_g_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_revise_log_entity.dart';
+import 'package:domain/repository/job_sg_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'revise_log_state.dart';
+
+/**
+ * 修改的记录
+ */
+class  ReviseLogController extends GetxController with DioCancelableMixin{
+  final JobSGRepository _jobRepository = Get.find();
+  final UKJobRepository _ukJobRepository = Get.find();
+  final ReviseLogState state = ReviseLogState();
+
+  var _needShowPlaceholder = true;
+
+  //页面PlaceHolder的展示
+  LoadState loadingState = LoadState.State_Success;
+  String? errorMessage;
+
+  //刷新页面状态
+  void changeLoadingState(LoadState state) {
+    loadingState = state;
+    update();
+  }
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,
+    controlFinishLoad: false,
+  );
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    fetchWorkFlowList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _needShowPlaceholder = true;
+    fetchWorkFlowList();
+  }
+
+  /// 获取服务器数据,成员考勤列表
+  Future fetchWorkFlowList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    //获取到数据
+    var result = await _ukJobRepository.featchReviseLogs(
+      reviseId: state.reviseId,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      handleList(result.data?.records);
+      refreshController.finishRefresh(IndicatorResult.success);
+    } else {
+      errorMessage = result.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+      refreshController.finishRefresh(IndicatorResult.fail);
+    }
+
+    //最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<UkJobAppliedReviseLogRecords>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      state.datas.clear();
+      state.datas.addAll(list);
+      //更新状态
+      changeLoadingState(LoadState.State_Success);
+    } else {
+      //展示无数据的布局
+      state.datas.clear();
+      changeLoadingState(LoadState.State_Empty);
+    }
+  }
+
+  @override
+  void onReady() async {
+    super.onReady();
+    fetchWorkFlowList();
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+    state.datas.clear();
+  }
+}

+ 156 - 0
packages/cpt_uk/lib/modules/job/revise_log/revise_log_item.dart

@@ -0,0 +1,156 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/revise_log_s_g_entity.dart';
+import 'package:domain/entity/response/uk_job_applied_revise_log_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+
+/**
+ * 修改记录Item
+ */
+class ReviseLogItem extends StatelessWidget {
+  final int index;
+  final UkJobAppliedReviseLogRecords item;
+
+  ReviseLogItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: EdgeInsets.symmetric(vertical: 23, horizontal: 21),
+      margin: EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
+      decoration: BoxDecoration(
+        color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(5), // 设置圆角
+      ),
+      child: Column(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          //时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Date Time".tr + ":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.createdAt ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ),
+
+          // 操作者
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Operator:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.operationName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 操作类型
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Action".tr + ":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //状态
+              MyTextView(
+                item.actText ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.actText == "Audit" ? ColorConstants.textYellowF8AE00 : ColorConstants.textGreen0AC074,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 操作内容
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              MyTextView(
+                "Content".tr + ":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                _obtainContent(),
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+        ],
+      ),
+    );
+  }
+
+  String _obtainContent() {
+    String displayText = "";
+
+    // 检查 reviseHours
+    if (item.content?.reviseHours != null) {
+      displayText += "Revise Hours => ${item.content!.reviseHours!.value!}\n";
+    }
+
+    // 检查 reviseMsg
+    if (item.content?.reason != null) {
+      displayText += "Reason => ${item.content!.reason!.value!}\n";
+    }
+
+    // 检查 status
+    if (item.content?.status != null) {
+      displayText += "Status => ${item.content!.status!.value!}\n";
+    }
+
+    // 如果没有任何信息,则显示 "-"
+    if (displayText.isEmpty) {
+      displayText = "-";
+    } else {
+      // 去掉末尾的换行符
+      displayText = displayText.trim();
+    }
+
+    return displayText;
+  }
+}

+ 102 - 0
packages/cpt_uk/lib/modules/job/revise_log/revise_log_page.dart

@@ -0,0 +1,102 @@
+
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/base/base_state.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:plugin_basic/utils/ext_get_nav.dart';
+import 'package:router/path/router_path.dart';
+import 'package:shared/utils/screen_util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'revise_log_controller.dart';
+import 'revise_log_state.dart';
+import 'revise_log_item.dart';
+
+/**
+ * 修改的记录
+ */
+class UKReviseLogPage extends BaseStatefulPage<ReviseLogController> {
+  UKReviseLogPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? reviseId) {
+    return Get.start(RouterPath.UKJobAppliedReviseLog,arguments: {'reviseId': reviseId});
+  }
+
+  @override
+  ReviseLogController createRawController() {
+    return ReviseLogController();
+  }
+
+  @override
+  State<UKReviseLogPage> createState() => _AppliedWorkflowState();
+
+}
+
+class _AppliedWorkflowState extends BaseState<UKReviseLogPage, ReviseLogController> {
+
+  late ReviseLogState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.reviseId = Get.arguments['reviseId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return  SafeArea(
+        bottom: MediaQuery.of(context).padding.bottom > 38,
+          top: false,
+          child: Container(
+            width: double.infinity,
+            height: double.infinity,
+            padding: EdgeInsets.only(top:ScreenUtil.getStatusBarH(context)),
+            decoration: const BoxDecoration(
+              gradient: LinearGradient(
+                colors: [
+                  Color(0xFF091D44),
+                  Color(0xFF245A8A),
+                  Color(0xFF7F7CEC),
+                ],
+                begin: Alignment.topCenter,
+                end: Alignment.bottomCenter,
+              ),
+            ),
+            child: Column(
+              children: [
+                MyAppBar.titleBar(context, "Logs".tr),
+
+                EasyRefresh(
+                  controller: controller.refreshController,
+                  onRefresh: controller.onRefresh,
+                  child: LoadStateLayout(
+                    state: controller.loadingState,
+                    errorMessage: controller.errorMessage,
+                    errorRetry: () {
+                      controller.retryRequest();
+                    },
+                    successSliverWidget: [
+                      SliverList(
+                          delegate: SliverChildBuilderDelegate((context, index) {
+                              return ReviseLogItem(index: index,item: state.datas[index]);
+                            },
+                            childCount: state.datas.length,
+                          ))
+                    ],
+                  ),
+                ).marginOnly(top: 5,bottom: 5).expanded(),
+              ],
+            ).marginOnly(top: 10),
+          ),
+        );
+    });
+  }
+}
+
+

+ 11 - 0
packages/cpt_uk/lib/modules/job/revise_log/revise_log_state.dart

@@ -0,0 +1,11 @@
+
+import 'package:domain/entity/response/uk_job_applied_revise_log_entity.dart';
+
+class ReviseLogState {
+
+  String? reviseId;
+
+  //页面的列表数据
+  List<UkJobAppliedReviseLogRecords> datas = [];
+
+}

+ 302 - 19
packages/cpt_uk/lib/modules/job/template_add/template_add_controller.dart

@@ -1,12 +1,17 @@
-import 'package:domain/entity/response/u_k_template_detail_entity.dart';
+import 'package:domain/entity/response/uk_job_template_detail_by_select_title_entity.dart';
+import 'package:domain/entity/response/uk_template_detail_entity.dart';
+import 'package:domain/entity/response/uk_template_detail_index_entity.dart';
+import 'package:domain/entity/response/uk_template_title_option_entity.dart';
 import 'package:domain/repository/uk_job_repository.dart';
 import 'package:get/get.dart';
+import 'package:plugin_platform/engine/loading/loading_engine.dart';
 import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:plugin_platform/http/http_result.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
 
 import 'template_add_state.dart';
 
@@ -14,20 +19,124 @@ class TemplateAddController extends GetxController with DioCancelableMixin {
   final UKJobRepository _labourRepository = Get.find();
   final LabourTemplateAddState state = LabourTemplateAddState();
 
+  @override
+  void onReady() {
+    super.onReady();
+    _fetchAddEditIndexDetail();
+  }
+
   // 获取添加或者编辑的详情
   void _fetchAddEditIndexDetail() async {
+    bool isEdit = state.pageType == 1;
+    bool isNeedFetchDetail = isEdit || Utils.isNotEmpty(state.selectedJobTitleStr);
+    String? templateId;
+    if (isEdit) {
+      templateId = state.templateId;
+    }else {
+      templateId = state.selectedTemplateId?.toString();
+    }
     //获取到数据
-    Future<HttpResult<UKTemplateDetailEntity>> taskFuture;
-    if (Utils.isNotEmpty(state.templateId) && state.templateId != "0") {
+    HttpResult<UkTemplateDetailEntity> taskDetailResult;
+    HttpResult<UkTemplateDetailIndexEntity> taskDetailOptionsResult;
+
+    if(state.indexOptionEntity == null){
+      // 获取选项
+      taskDetailOptionsResult = await _labourRepository.fetchJobTemplateIndex(cancelToken: cancelToken);
+      handlerAddDetailOptionsData(taskDetailOptionsResult);
+    }
+
+    if (isNeedFetchDetail) {
       //编辑
-      taskFuture = _labourRepository.fetchJobTemplateDetail(templateId: state.templateId, cancelToken: cancelToken);
+      taskDetailResult = await _labourRepository.fetchJobTemplateDetail(templateId: templateId, cancelToken: cancelToken);
+      // 处理数据
+      handlerEditDetailData(taskDetailResult);
+    }
+  }
+
+  // 新增时 选择了 jobtitle 后 获取该title对应的模板详情
+  void _fetchSelectJobTitleGetTemplateDetail() async {
+    String? templateId = state.selectedTemplateId?.toString();
+    //获取到数据
+    HttpResult<UkJobTemplateDetailBySelectTitleEntity> taskDetailResult;
+
+    taskDetailResult = await _labourRepository.fetchSelectJobTitleGetTemplateDetail(templateId: templateId, cancelToken: cancelToken);
+      // 处理数据
+    handlerBySelectJobTitleDetailData(taskDetailResult);
+  }
+
+  // 处理 选择 jobtitle 后 该 jobtitle 对应的模板数据的回显
+  void handlerBySelectJobTitleDetailData(HttpResult<UkJobTemplateDetailBySelectTitleEntity> result) async {
+    //处理数据
+    if (result.isSuccess) {
+      UkJobTemplateDetailBySelectTitleEntity? resultData = result.data;
+      // var templateNameController = state.formData['template_name']!['controller'];
+      var descController = state.formData['desc']!['controller'];
+      var noteController = state.formData['note']!['controller'];
+      var contactNameController = state.formData['contact_name']!['controller'];
+      var contactNoController = state.formData['contact_no']!['controller'];
+
+
+      descController.text = resultData?.requirements ?? "";
+      noteController.text = resultData?.note ?? "";
+      contactNameController.text = resultData?.contact ?? "";
+      contactNoController.text = resultData?.contactNo ?? "";
+
+
+      // 证书回显
+      List<int> jobCertificateList = (resultData?.jobCertificate ?? '')
+          .split(',')
+          .where((s) => s.isNotEmpty)
+          .map((s) => int.tryParse(s) ?? 0)
+          .toList();
+
+
+      if (jobCertificateList.isNotEmpty) {
+        state.indexOptionEntity?.certificateList?.forEach((cerItem) {
+          if (jobCertificateList.contains(cerItem.value)) {
+            cerItem.checked = "checked";
+          }
+        });
+      }
+
+      // 交通工具回显
+      List<int> jobVechicleList = (resultData?.jobVehicle ?? '')
+          .split(',')
+          .where((s) => s.isNotEmpty)
+          .map((s) => int.tryParse(s) ?? 0)
+          .toList();
+      if (jobVechicleList.isNotEmpty) {
+        state.indexOptionEntity?.vehicleList?.forEach((vechicleItem) {
+          if (jobVechicleList.contains(vechicleItem.value)) {
+            vechicleItem.checked = "checked";
+          }
+        });
+      }
+
+
+      //默认CheckBox
+      state.selectedCertificateList = state.indexOptionEntity?.certificateList
+          ?.where((e) => e.checked == "checked")
+          .map((e) => e.value!.toString())
+          .toList() ?? [];
+      Log.d("当前选中的证书:${state.selectedCertificateList}");
+
+
+      state.selectedVehicleList = state.indexOptionEntity?.vehicleList
+          ?.where((e) => e.checked == "checked")
+          .map((e) => e.value!.toString())
+          .toList() ?? [];
+      Log.d("当前选中的交通工具:${state.selectedVehicleList}");
+
+      //刷新
+      update();
     } else {
-      //新增
-      taskFuture = _labourRepository.fetchJobTemplateIndex(cancelToken: cancelToken);
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
     }
+  }
 
-    var result = await taskFuture;
 
+  // 处理编辑的详情数据
+  void handlerEditDetailData(HttpResult<UkTemplateDetailEntity> result) async {
     //处理数据
     if (result.isSuccess) {
       state.indexEntity = result.data;
@@ -35,14 +144,43 @@ class TemplateAddController extends GetxController with DioCancelableMixin {
       var templateNameController = state.formData['template_name']!['controller'];
       var descController = state.formData['desc']!['controller'];
       var noteController = state.formData['note']!['controller'];
+      var contactNameController = state.formData['contact_name']!['controller'];
+      var contactNoController = state.formData['contact_no']!['controller'];
       templateNameController.text = state.indexEntity?.row?.jobTitle ?? "";
       descController.text = state.indexEntity?.row?.description ?? "";
       noteController.text = state.indexEntity?.row?.note ?? "";
+      contactNameController.text = state.indexEntity?.row?.contactName ?? "";
+      contactNoController.text = state.indexEntity?.row?.contactNo ?? "";
+
+
+      // 将 state.indexEntity?.certificateList  与 state.indexOptionEntity 进行对比 将 checked 复制给
+      state.indexEntity?.certificateList?.forEach((e) {
+        var option = state.indexOptionEntity?.certificateList?.firstWhere((option) => option.value == e.value, orElse: () => UkTemplateDetailIndexCertificateList());
+        if (option != null) {
+          option.checked = e.checked;
+        }
+      });
+
+      // 将 state.indexEntity?.vehicleList  与 state.indexOptionEntity 进行对比 将 checked 复制给
+      state.indexEntity?.vehicleList?.forEach((e) {
+        var option = state.indexOptionEntity?.vehicleList?.firstWhere((option) => option.value == e.value, orElse: () => UkTemplateDetailIndexVehicleList());
+        if (option != null) {
+          option.checked = e.checked;
+        }
+      });
 
       //默认CheckBox
-      state.selectedCertificateList = state.indexEntity?.certificateList?.where((e) => e.checked == "checked").map((e) => e.value!).toList() ?? [];
+      state.selectedCertificateList = state.indexEntity?.certificateList
+          ?.where((e) => e.checked == "checked")
+          .map((e) => e.value!.toString())
+          .toList() ?? [];
       Log.d("当前选中的证书:${state.selectedCertificateList}");
-      state.selectedVehicleList = state.indexEntity?.vehicleList?.where((e) => e.checked == "checked").map((e) => e.value!).toList() ?? [];
+
+
+      state.selectedVehicleList = state.indexEntity?.vehicleList
+          ?.where((e) => e.checked == "checked")
+          .map((e) => e.value!.toString())
+          .toList() ?? [];
       Log.d("当前选中的交通工具:${state.selectedVehicleList}");
 
       //刷新
@@ -52,24 +190,168 @@ class TemplateAddController extends GetxController with DioCancelableMixin {
     }
   }
 
+
+  // 处理新增时详情页的选项数据
+  void handlerAddDetailOptionsData(HttpResult<UkTemplateDetailIndexEntity> result) async {
+    //处理数据
+    if (result.isSuccess) {
+      state.indexOptionEntity = result.data;
+
+      var templateNameController = state.formData['template_name']!['controller'];
+      var descController = state.formData['desc']!['controller'];
+      var noteController = state.formData['note']!['controller'];
+      var contactNameController = state.formData['contact_name']!['controller'];
+      var contactNoController = state.formData['contact_no']!['controller'];
+      templateNameController.text = "";
+      descController.text =  "";
+      noteController.text =  "";
+      contactNameController.text =  "";
+      contactNoController.text =  "";
+
+
+
+      //默认CheckBox
+      state.selectedCertificateList = state.indexOptionEntity?.certificateList
+          ?.where((e) => e.checked == "checked")
+          .map((e) => e.value!.toString())
+          .toList() ?? [];
+      Log.d("当前的证书: ${state.indexOptionEntity?.certificateList}");
+      Log.d("当前选中的证书:${state.selectedCertificateList}");
+
+
+      state.selectedVehicleList = state.indexOptionEntity?.vehicleList
+          ?.where((e) => e.checked == "checked")
+          .map((e) => e.value!.toString())
+          .toList() ?? [];
+      Log.d("当前的交通工具: ${state.indexOptionEntity?.vehicleList}");
+      Log.d("当前选中的交通工具:${state.selectedVehicleList}");
+
+      //刷新
+      update();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+
+  // 新增时 选择 template
+  void showChooseTemplatePicker(){
+    int selectedTemplateIndex;
+    if (state.selectedJobTemplateStr == null) {
+      selectedTemplateIndex = 0;
+    } else {
+      selectedTemplateIndex = state.indexOptionEntity?.templateList?.indexWhere((template) => template.toString() == state.selectedJobTemplateStr)?? 0;
+    }
+
+    if (selectedTemplateIndex < 0) {
+      selectedTemplateIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.indexOptionEntity?.templateList?.map((e) => e!).toList(growable: false)?? [],
+      initialSelectIndex: selectedTemplateIndex,
+      onPickerChanged: (_, index) {
+        String lastSelectedTemplateStr = state.selectedJobTemplateStr?? "";
+        String curSelectedTemplateStr = state.indexOptionEntity?.templateList?[index] ?? "";
+        if(lastSelectedTemplateStr != curSelectedTemplateStr){
+          state.selectedJobTemplateStr = curSelectedTemplateStr;
+          state.selectedJobTitleStr = "";
+          update();
+          // 需要调接口来获取工作标题的数据源
+          _fetchJobTitleOptionsList();
+        }
+      },
+    );
+  }
+
+  // 获取 工作标题的数据源
+  void _fetchJobTitleOptionsList() async {
+    LoadingEngine.show();
+    try {
+      // 获取到数据
+      HttpResult<UkTemplateTitleOptionEntity> taskResult;
+
+      taskResult = await _labourRepository.fetchJobTitleOptiosByTemplate(
+        state.selectedJobTemplateStr!,
+        cancelToken: cancelToken,
+      );
+
+      if (taskResult.isSuccess) {
+        state.jobTitleOptionEntityList = taskResult.list;
+      } else {
+        ToastEngine.show(taskResult.errorMsg ?? "Network Load Error".tr);
+      }
+    } catch (e) {
+      // Log.e(e);
+    } finally {
+      LoadingEngine.dismiss();
+    }
+  }
+
+
+  // 显示工作标题picker
+  void showChooseJobTitlePicker(){
+    int selectedjobTitleIndex;
+    if (state.selectedJobTitleStr == null) {
+      selectedjobTitleIndex = 0;
+    } else {
+      selectedjobTitleIndex = state.jobTitleOptionEntityList?.indexWhere((title) => title.jobTitle.toString() == state.selectedJobTitleStr)?? 0;
+    }
+
+    if (selectedjobTitleIndex < 0) {
+      selectedjobTitleIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.jobTitleOptionEntityList?.map((e) => e.jobTitle.toString()!).toList(growable: false)?? [],
+      initialSelectIndex: selectedjobTitleIndex,
+      onPickerChanged: (_, index) {
+        state.selectedJobTitleStr = state.jobTitleOptionEntityList?[index]?.jobTitle?.toString()?? "";
+        update();
+        // 选择了 工作标题后 需要重新调用 详情接口
+        _fetchSelectJobTitleGetTemplateDetail();
+      },
+    );
+  }
+
   /// 提交
   void doSubmit() async {
+
     var templateNameController = state.formData['template_name']!['controller'];
     var descController = state.formData['desc']!['controller'];
     var noteController = state.formData['note']!['controller'];
+    var contactNameController = state.formData['contact_name']!['controller'];
+    var contactNoController = state.formData['contact_no']!['controller'];
 
     String templateTitle = templateNameController.text.toString();
     String desc = descController.text.toString();
     String note = noteController.text.toString();
+    String contactName = contactNameController.text.toString();
+    String contactNo = contactNoController.text.toString();
 
-    //只校验模版的名称
-    if (Utils.isEmpty(templateTitle)) {
-      ToastEngine.show("Enter Job Template Title".tr);
-      return;
+    if(state.pageType == 0){
+      // 新增 时 需要校验 工作模板 和 工作标题
+      if (Utils.isEmpty(state.selectedJobTemplateStr)) {
+        ToastEngine.show("Enter Job Template".tr);
+        return;
+      }
+      if (Utils.isEmpty(state.selectedJobTitleStr)) {
+        ToastEngine.show("Enter Job Title".tr);
+        return;
+      }
+    }else if(state.pageType == 1){
+      // 编辑 时 需要校验 工作标题
+      //检验工作标题
+      if (Utils.isEmpty(templateTitle)) {
+        ToastEngine.show("Enter Job Template Title".tr);
+        return;
+      }
     }
 
+
     Future<HttpResult> taskFuture;
     if (Utils.isNotEmpty(state.templateId) && state.templateId != "0") {
+      // 编辑
       taskFuture = _labourRepository.editJobTemplateSubmit(
         templateId: state.templateId,
         jobTitle: templateTitle,
@@ -77,15 +359,21 @@ class TemplateAddController extends GetxController with DioCancelableMixin {
         vehicle: state.selectedVehicleList,
         desc: desc,
         note: note,
+        contactName: contactName,
+        contactNo: contactNo,
         cancelToken: cancelToken,
       );
     } else {
+      // 新增
       taskFuture = _labourRepository.addJobTemplateSubmit(
-        jobTitle: templateTitle,
+        jobTemplateId: state.selectedTemplateId?.toString()??'',
+        jobTitle: state.selectedJobTitleStr?? '',
         certificate: state.selectedCertificateList,
         vehicle: state.selectedVehicleList,
         desc: desc,
         note: note,
+        contactName: contactName,
+        contactNo: contactNo,
         cancelToken: cancelToken,
       );
     }
@@ -105,9 +393,4 @@ class TemplateAddController extends GetxController with DioCancelableMixin {
     }
   }
 
-  @override
-  void onReady() {
-    super.onReady();
-    _fetchAddEditIndexDetail();
-  }
 }

+ 157 - 25
packages/cpt_uk/lib/modules/job/template_add/template_add_page.dart

@@ -1,13 +1,16 @@
 import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:plugin_basic/base/base_state.dart';
 import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/screen_util.dart';
 import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 import 'package:widgets/no_shadow_scroll_behavior.dart';
 import 'package:widgets/shatter/custom_check_box.dart';
@@ -53,19 +56,22 @@ class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddCo
     super.initState();
     state = controller.state;
     state.templateId = Get.arguments['templateId'];
+    state.pageType = Utils.isEmpty(state.templateId)? 0:1;
     state.cb = Get.arguments['cb'] as void Function(dynamic)?;
   }
 
   @override
   Widget build(BuildContext context) {
+    bool isEdit = Utils.isNotEmpty(state.templateId);
+    bool isAdd = Utils.isEmpty(state.templateId);
     return autoCtlGetBuilder(
         id: "all",
         builder: (controller) {
           return Scaffold(
             extendBodyBehindAppBar: true,
-            appBar: MyAppBar.appBar(context, Utils.isEmpty(state.templateId) ? "Create Template".tr : "Edit Template".tr),
+            appBar: MyAppBar.appBar(context, isAdd ? "Create Template".tr : "Edit Template".tr),
             body: SafeArea(
-        bottom: MediaQuery.of(context).padding.bottom > 38,
+              bottom: MediaQuery.of(context).padding.bottom > 38,
               top: false,
               child: Container(
                 width: double.infinity,
@@ -91,24 +97,34 @@ class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddCo
                       child: Column(
                         crossAxisAlignment: CrossAxisAlignment.start,
                         children: [
-                          //模板名称
-                          FormRequireText(text: "Template Title".tr).marginOnly(left: 15, top: 19),
 
-                          CustomTextField(
-                            formKey: "template_name",
-                            formData: state.formData,
-                            height: 46,
-                            fontSize: 14,
-                            onSubmit: (key, value) {
-                              state.formData[key]!['focusNode'].unfocus();
-                              FocusScope.of(context).requestFocus(state.formData['desc']!['focusNode']);
-                            },
-                            marginTop: 10,
-                          ),
+                          if(isEdit)
+                            //模板名称
+                            ...[
+                              FormRequireText(text: "Template Title".tr).marginOnly(left: 15, top: 19),
+                              CustomTextField(
+                                formKey: "template_name",
+                                formData: state.formData,
+                                height: 46,
+                                fontSize: 14,
+                                enabled: isAdd ? true:false,
+                                onSubmit: (key, value) {
+                                  state.formData[key]!['focusNode'].unfocus();
+                                  FocusScope.of(context).requestFocus(state.formData['desc']!['focusNode']);
+                                },
+                                marginTop: 10,
+                              )
+                            ],
+                          if(isAdd)
+                            ...[
+                              _buildTemplateSelectWidget(),
+                              _buildTemplateJobTitleWidget(),
+                            ],
+
 
                           //证书
                           Visibility(
-                            visible: state.indexEntity?.certificateList?.isNotEmpty == true,
+                            visible: state.indexOptionEntity?.certificateList?.isNotEmpty == true,
                             child: MyTextView(
                               "Certificate".tr,
                               textColor: Colors.white,
@@ -121,19 +137,19 @@ class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddCo
 
                           // 证书的多选
                           Visibility(
-                            visible: state.indexEntity?.certificateList?.isNotEmpty == true,
+                            visible: state.indexOptionEntity?.certificateList?.isNotEmpty == true,
                             child: CustomCheckBox(
-                              options: state.indexEntity?.certificateList?.map((e) => e.txt!).toList() ?? [],
+                              options: state.indexOptionEntity?.certificateList?.map((e) => e.txt!).toList() ?? [],
                               onOptionsSelected: (selected) {
                                 // 转换选中的索引为对应的 value
                                 state.selectedCertificateList = selected
                                     .map((index) {
-                                      return state.indexEntity?.certificateList?[index].value; // 获取对应的 value
+                                      return state.indexOptionEntity?.certificateList?[index].value; // 获取对应的 value
                                     })
                                     .whereType<String>()
                                     .toList();
                               },
-                              selectedOptions: state.indexEntity?.certificateList?.where((e) => e.checked == "checked").map((e) => e.txt!).toList() ?? [],
+                              selectedOptions: state.indexOptionEntity?.certificateList?.where((e) => e.checked == "checked").map((e) => e.txt!).toList() ?? [],
                             ).marginOnly(left: 15, right: 15, top: 10),
                           ),
 
@@ -149,19 +165,19 @@ class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddCo
 
                           //交通工具的多选
                           Visibility(
-                            visible: state.indexEntity?.vehicleList?.isNotEmpty == true,
+                            visible: state.indexOptionEntity?.vehicleList?.isNotEmpty == true,
                             child: CustomCheckBox(
-                              options: state.indexEntity?.vehicleList?.map((e) => e.txt!).toList() ?? [],
+                              options: state.indexOptionEntity?.vehicleList?.map((e) => e.txt!).toList() ?? [],
                               onOptionsSelected: (selected) {
                                 // 转换选中的索引为对应的 value
                                 state.selectedVehicleList = selected
                                     .map((index) {
-                                  return state.indexEntity?.vehicleList?[index].value; // 获取对应的 value
+                                  return state.indexOptionEntity?.vehicleList?[index].value; // 获取对应的 value
                                 })
                                     .whereType<String>()
                                     .toList();
                               },
-                              selectedOptions: state.indexEntity?.vehicleList?.where((e) => e.checked == "checked").map((e) => e.txt!).toList() ?? [],
+                              selectedOptions: state.indexOptionEntity?.vehicleList?.where((e) => e.checked == "checked").map((e) => e.txt!).toList() ?? [],
                             ).marginOnly(left: 15, right: 15, top: 10),
                           ),
 
@@ -183,9 +199,39 @@ class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddCo
                           //     );
                           //   },
                           //   id: "language",
+                          //   id: "language",
                           //   init: controller,
                           // ).marginOnly(left: 15, right: 15, top: 10),
 
+                          // 联系人 Contact Name
+                          FormRequireText(text: "Contact Name".tr, isRequired: false).marginOnly(left: 15, top: 19),
+                          CustomTextField(
+                            formKey: "contact_name",
+                            formData: state.formData,
+                            height: 46,
+                            fontSize: 14,
+                            onSubmit: (key, value) {
+                              state.formData[key]!['focusNode'].unfocus();
+                              FocusScope.of(context).requestFocus(state.formData['contact_no']!['focusNode']);
+                            },
+                            marginTop: 10,
+                          ),
+
+
+                          // 联系人电话 Contact No
+                          FormRequireText(text: "Contact No".tr, isRequired: false,).marginOnly(left: 15, top: 19),
+                          CustomTextField(
+                            formKey: "contact_no",
+                            formData: state.formData,
+                            height: 46,
+                            fontSize: 14,
+                            onSubmit: (key, value) {
+                              state.formData[key]!['focusNode'].unfocus();
+                              FocusScope.of(context).requestFocus(state.formData['note']!['focusNode']);
+                            },
+                            marginTop: 10,
+                          ),
+
                           //备注
                           MyTextView(
                             "Note".tr,
@@ -238,7 +284,7 @@ class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddCo
                             ),
                           ),
 
-                          //模板详情
+                          // 描述详情
                           MyTextView(
                             "Description".tr,
                             textColor: Colors.white,
@@ -316,4 +362,90 @@ class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddCo
           );
         });
   }
+
+
+  Widget _buildTemplateSelectWidget() {
+    return Container(
+      margin: const EdgeInsets.only(left: 15, right: 15,),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          // template 模板
+          FormRequireText(text: "Template".tr).marginOnly(top: 15),
+          //选择template
+          Container(
+            padding: const EdgeInsets.only(left: 16, right: 10),
+            margin: const EdgeInsets.only(top: 10),
+            height: 45,
+            decoration: BoxDecoration(
+              color:  const Color(0xFF4DCFF6).withOpacity(0.2),
+              borderRadius: BorderRadius.all(Radius.circular(5)),
+            ),
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              mainAxisAlignment: MainAxisAlignment.start,
+              children: [
+                MyTextView(
+                  state.selectedJobTemplateStr ==null || Utils.isEmpty(state.selectedJobTemplateStr)? '': state.selectedJobTemplateStr! ,
+                  hint: "Choose Template".tr,
+                  textHintColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                  isFontMedium: true,
+                  textColor: ColorConstants.white,
+                ).expanded(),
+                const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ],
+            ),
+          ).onTap(() {
+            controller.showChooseTemplatePicker();
+          })
+        ],
+      ),
+    );
+  }
+
+
+  Widget _buildTemplateJobTitleWidget() {
+    return Container(
+      margin: const EdgeInsets.only(left: 15, right: 15,),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          // 工作标题
+          FormRequireText(text: "Job Title".tr).marginOnly(top: 15),
+          //选择template
+          Container(
+            padding: const EdgeInsets.only(left: 16, right: 10),
+            margin: const EdgeInsets.only(top: 10),
+            height: 45,
+            decoration: BoxDecoration(
+              color:  const Color(0xFF4DCFF6).withOpacity(0.2),
+              borderRadius: BorderRadius.all(Radius.circular(5)),
+            ),
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              mainAxisAlignment: MainAxisAlignment.start,
+              children: [
+                MyTextView(
+                  state.selectedJobTitleStr ==null || Utils.isEmpty(state.selectedJobTitleStr)? '': state.selectedJobTitleStr! ,
+                  hint: "Choose Job Title".tr,
+                  textHintColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                  isFontMedium: true,
+                  textColor: ColorConstants.white,
+                ).expanded(),
+                const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+              ],
+            ),
+          ).onTap(() {
+            controller.showChooseJobTitlePicker();
+          })
+        ],
+      ),
+    );
+  }
 }

+ 32 - 3
packages/cpt_uk/lib/modules/job/template_add/template_add_state.dart

@@ -1,5 +1,7 @@
-import 'package:domain/entity/response/job_template_edit_index_entity.dart';
-import 'package:domain/entity/response/u_k_template_detail_entity.dart';
+
+import 'package:domain/entity/response/uk_template_detail_entity.dart';
+import 'package:domain/entity/response/uk_template_detail_index_entity.dart';
+import 'package:domain/entity/response/uk_template_title_option_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_basic/basic_export.dart';
 
@@ -13,6 +15,20 @@ class LabourTemplateAddState {
       'hintText': 'Enter...'.tr,
       'obsecure': false,
     },
+    'contact_name': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'contact_no': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
     'desc': {
       'value': '',
       'controller': TextEditingController(),
@@ -33,9 +49,22 @@ class LabourTemplateAddState {
   final foodHygieneCertOption = ["Yes".tr, "No".tr];
 
   String templateId = "";
+  int pageType = 0; // 0:新增 1:编辑
   void Function(dynamic value)? cb;
 
-  UKTemplateDetailEntity? indexEntity;  //新增或者编辑的详情
+  String? selectedJobTemplateStr;  // 新增时选择的模版
+
+  int? get selectedTemplateId {
+    // 遍历 jobTitleOptionEntityList 中获取 对应的 selectedJobTitleStr 的 id
+    return jobTitleOptionEntityList?.where((e) => e.jobTitle == selectedJobTitleStr)?.first?.id?? null;
+  }
+
+  List<UkTemplateTitleOptionEntity>? jobTitleOptionEntityList; // 新增时工作标题的数据源
+  String? selectedJobTitleStr;  // 新增时选择的工作标题
+
+  UkTemplateDetailEntity? indexEntity;  //新增或者编辑的详情
+
+  UkTemplateDetailIndexEntity? indexOptionEntity; // 详情页的 数据源
 
   List<String> selectedCertificateList = [];   //选中的 age 的 id
   List<String> selectedVehicleList = [];   //选中的 language 的 id

+ 46 - 0
packages/cpt_uk/lib/modules/job/template_list/item_template.dart

@@ -104,6 +104,52 @@ class TemplateItem extends StatelessWidget {
             ],
           ).marginOnly(top: 14),
 
+          // 联系人
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Contact Name".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //文本
+              MyTextView(
+                item.contactName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 14),
+
+          // 联系电话
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Contact No".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //文本
+              MyTextView(
+                item.contactNo ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 14),
+
           // 创建者
           Row(
             mainAxisSize: MainAxisSize.max,

+ 37 - 34
packages/cpt_uk/lib/modules/main/main_controller.dart

@@ -4,10 +4,13 @@ import 'package:cpt_uk/modules/attendance/security_registration/security_registr
 import 'package:cpt_uk/modules/job/job_category/job_category_page.dart';
 import 'package:cpt_uk/modules/report/report_list/report_list_page.dart';
 import 'package:domain/entity/home_module.dart';
+import 'package:domain/entity/response/hotel_info_entity.dart';
 import 'package:domain/repository/auth_repository.dart';
 import 'package:get/get.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_basic/service/app_config_service.dart';
 import 'package:plugin_basic/service/user_service.dart';
+import 'package:plugin_platform/engine/sp/sp_util.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
@@ -63,10 +66,10 @@ class MainController extends GetxController {
 
       if (hotelInfo != null) {
         UserService.to.hotelInfo.value = hotelInfo;
-
-        //展示UK全部的模块
-        state.datas.clear();
-        state.datas.addAll(state.modules);
+        _handleList(hotelInfo.menus);
+        // //展示UK全部的模块
+        // state.datas.clear();
+        // state.datas.addAll(state.modules);
         changeLoadingState(LoadState.State_Success);
       } else {
         ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
@@ -82,36 +85,36 @@ class MainController extends GetxController {
   }
 
   // 处理数据与展示的逻辑
-  // void _handleList(List<HotelInfoMenus>? list) {
-  //   if (list != null && list.isNotEmpty) {
-  //     //有数据,判断是刷新还是加载更多的数据
-  //     state.datas.clear();
-  //
-  //     int? isAdmin = SPUtil.getInt(AppConstant.storageIsAdmin);
-  //     if (isAdmin == 1) {
-  //       //如果是管理员登录,根据Key筛选需要展示的模块
-  //       for (var hotelInfo in list) {
-  //         if (hotelInfo.key != null) {
-  //           state.datas.addAll(_filterModulesByKey(hotelInfo.key!));
-  //         }
-  //       }
-  //     } else {
-  //       //如果只是签到签出模式,手动的添加模块
-  //       state.datas.addAll(_filterModulesByKey("sign"));
-  //     }
-  //
-  //     //更新状态
-  //     changeLoadingState(LoadState.State_Success);
-  //   } else {
-  //     //展示无数据的布局
-  //     state.datas.clear();
-  //     changeLoadingState(LoadState.State_Empty);
-  //   }
-  // }
-
-  // List<HomeModule> _filterModulesByKey(String key) {
-  //   return state.modules.where((module) => module.key == key).toList();
-  // }
+  void _handleList(List<HotelInfoMenus>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      state.datas.clear();
+
+      int? isAdmin = SPUtil.getInt(AppConstant.storageIsAdmin);
+      if (isAdmin == 1) {
+        //如果是管理员登录,根据Key筛选需要展示的模块
+        for (var hotelInfo in list) {
+          if (hotelInfo.key != null) {
+            state.datas.addAll(_filterModulesByKey(hotelInfo.key!));
+          }
+        }
+      } else {
+        //如果只是签到签出模式,手动的添加模块
+        state.datas.addAll(_filterModulesByKey("sign"));
+      }
+
+      //更新状态
+      changeLoadingState(LoadState.State_Success);
+    } else {
+      //展示无数据的布局
+      state.datas.clear();
+      changeLoadingState(LoadState.State_Empty);
+    }
+  }
+
+  List<HomeModule> _filterModulesByKey(String key) {
+    return state.modules.where((module) => module.key == key).toList();
+  }
 
   @override
   void onReady() async {

+ 107 - 37
packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_controller.dart

@@ -1,19 +1,40 @@
-import 'package:domain/entity/response/staff_request_report_entity.dart';
-import 'package:domain/repository/other_repository.dart';
+import 'package:domain/entity/response/labour_request_index_entity.dart';
+import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:domain/entity/response/uk_report_casual_entity.dart';
+import 'package:domain/repository/labour_repository.dart';
+import 'package:domain/repository/uk_report_repository.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/loading/loading_engine.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:plugin_platform/http/http_result.dart';
 import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/dialog/app_default_dialog.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/picker/date_picker_util.dart';
-
+import 'package:widgets/widget_export.dart';
 import 'casual_payout_report_state.dart';
 
 class CasualPayoutReportController extends GetxController with DioCancelableMixin {
-  final OtherRepository _otherRepository = Get.find();
+  final UKReportRepository _ukReportRepository = Get.find();
   final CasualPayoutReportState state = CasualPayoutReportState();
 
+  var _curPage = 1;
+  var _needShowPlaceholder = true;
+
+  @override
+  void onInit() {
+    super.onInit();
+    state.startDateTime = DateTimeUtils.getFirstDayOfMonth();
+  }
+
   //页面PlaceHolder的展示
-  LoadState loadingState = LoadState.State_Loading;
+  LoadState loadingState = LoadState.State_Success;
   String? errorMessage;
 
   //刷新页面状态
@@ -22,32 +43,85 @@ class CasualPayoutReportController extends GetxController with DioCancelableMixi
     update();
   }
 
-  //重试
-  void retryRequest() {
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,
+    controlFinishLoad: false, // 禁用 上拉
+  );
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchReportData();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchReportData();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
     fetchReportData();
   }
 
-  // 获取当前列表数据
-  void fetchReportData() async {
-    changeLoadingState(LoadState.State_Loading);
+  /// 获取服务器数据,通知消息列表
+  Future fetchReportData() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
 
-    var result = await _otherRepository.fetchReportLabour(
-      DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM-dd"),
-      DateTimeUtils.formatDate(state.endDateTime, format: "yyyy-MM-dd"),
+    //请求列表数据
+    var listResult = await _ukReportRepository.fetchReportCasualData(
+      month: DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM"),
       cancelToken: cancelToken,
     );
 
-    if (result.isSuccess) {
-      state.entity = result.data;
-      state.datas = result.data?.rows ?? [];
-      if (state.datas.isNotEmpty) {
+    LoadingEngine.dismiss();
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<UkReportCasualRows>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      if (_curPage == 1) {
+        //刷新的方式
+        state.datas.clear();
+        state.datas.addAll(list);
+        refreshController.finishRefresh();
+
+        //更新展示的状态
         changeLoadingState(LoadState.State_Success);
       } else {
-        changeLoadingState(LoadState.State_Empty);
+        //加载更多
+        state.datas.addAll(list);
+        refreshController.finishLoad();
+        update();
       }
     } else {
-      errorMessage = result.errorMsg ?? "Network Load Error".tr;
-      changeLoadingState(LoadState.State_Error);
+      if (_curPage == 1) {
+        //展示无数据的布局
+        state.datas.clear();
+        changeLoadingState(LoadState.State_Empty);
+        refreshController.finishRefresh();
+      } else {
+        //展示加载完成,没有更多数据了
+        refreshController.finishLoad(IndicatorResult.noMore);
+      }
     }
   }
 
@@ -57,29 +131,25 @@ class CasualPayoutReportController extends GetxController with DioCancelableMixi
     fetchReportData();
   }
 
-  /// 筛选开始日期
-  void pickerStartDate() {
-    DatePickerUtil.showCupertinoDatePicker(
-      selectedDateTime: state.startDateTime,
-      onDateTimeChanged: (date) {
-        state.startDateTime = date;
-        update();
-        fetchReportData();
-      },
-      title: "Start Date".tr,
-    );
+  @override
+  void onClose() {
+    state.datas.clear();
+    super.onClose();
   }
 
-  /// 筛选结束日期
-  void pickerEndDate() {
+  //   年月的日期筛选
+  void showDatePicker() {
     DatePickerUtil.showCupertinoDatePicker(
-      selectedDateTime: state.endDateTime ?? state.startDateTime,
+      selectedDateTime: state.startDateTime ?? DateTime.now(),
+      mode: CupertinoDatePickerMode.monthYear,
       onDateTimeChanged: (date) {
-        state.endDateTime = date;
-        update();
+        state.startDateTime = date;
+        LoadingEngine.show();
         fetchReportData();
+        update();
       },
-      title: "End Date".tr,
+      title: "Select Date".tr,
     );
   }
+
 }

+ 107 - 142
packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_item.dart

@@ -1,142 +1,107 @@
-import 'package:cs_resources/constants/color_constants.dart';
-import 'package:domain/entity/response/labour_report_entity.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-import 'package:plugin_basic/basic_export.dart';
-import 'package:widgets/ext/ex_widget.dart';
-
-import 'package:widgets/my_text_view.dart';
-
-class ReportLabourItem extends StatelessWidget {
-  LabourReportEntity? entity; //主体数据
-  int type; //0 Completed  1 Incomplete  2 Completed + Incomplete
-
-  ReportLabourItem({
-    required this.entity,
-    required this.type,
-  });
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      width: double.infinity,
-      padding: const EdgeInsets.only(top: 16, bottom: 20),
-      margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),
-      decoration: BoxDecoration(
-        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
-        borderRadius: BorderRadius.circular(5), // 设置圆角
-      ),
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          MyTextView(
-            type == 0
-                ? "Completed".tr
-                : type == 1
-                    ? "Incomplete".tr
-                    : "Completed + Incomplete".tr,
-            fontSize: 14,
-            isFontBold: true,
-            marginBottom: 15,
-            marginLeft: 20,
-            marginRight: 20,
-            textColor: type == 0
-                ? ColorConstants.textGreen0AC074
-                : type == 1
-                    ? ColorConstants.textBlue06D9FF
-                    : ColorConstants.textRedFF6262,
-          ),
-          const Divider(height: 0.5, color: ColorConstants.dividerBar),
-
-          Row(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: [
-              MyTextView(
-                "Outlet".tr,
-                fontSize: 14,
-                textColor: Colors.white,
-                isFontRegular: true,
-              ).expanded(),
-              Column(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  MyTextView("Hours".tr, textColor: Colors.white, fontSize: 14, isFontRegular: true),
-                  MyTextView(
-                    "(${entity?.total?.hrs})",
-                    textColor: type == 0
-                        ? ColorConstants.textGreen0AC074
-                        : type == 1
-                            ? ColorConstants.textBlue06D9FF
-                            : ColorConstants.textRedFF6262,
-                    fontSize: 14,
-                    isFontRegular: true,
-                  ),
-                ],
-              ).expanded(),
-              Column(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  MyTextView("TotalAmt".tr, textColor: Colors.white, fontSize: 14, isFontRegular: true),
-                  MyTextView(
-                    "(${entity?.total?.agAmt})",
-                    textColor: type == 0
-                        ? ColorConstants.textGreen0AC074
-                        : type == 1
-                            ? ColorConstants.textBlue06D9FF
-                            : ColorConstants.textRedFF6262,
-                    fontSize: 14,
-                    isFontRegular: true,
-                  ),
-                ],
-              ).expanded(),
-            ],
-          ).marginOnly(left: 20, right: 20, top: 18, bottom: 2),
-
-          //底部的实际数据
-          ...(entity?.rows.map((item) {
-                return _childItem(
-                  item.outletName,
-                  type == 0
-                      ? item.hrs
-                      : type == 1
-                          ? item.inHrs
-                          : item.totHrs,
-                  type == 0
-                      ? item.agAmt
-                      : type == 1
-                          ? item.inAgAmt
-                          : item.totAgAmt,
-                );
-              }).toList() ??
-              []),
-        ],
-      ),
-    );
-  }
-
-  Widget _childItem(String? outletName, String? hours, String? agAmt) {
-    return Row(
-      children: [
-        MyTextView(
-          outletName ?? "",
-          fontSize: 14,
-          textColor: Colors.white,
-          isFontRegular: true,
-        ).expanded(),
-        MyTextView(
-          "$hours H",
-          fontSize: 14,
-          textColor: Colors.white,
-          isFontRegular: true,
-        ).expanded(),
-        MyTextView(
-          "\$ $agAmt",
-          fontSize: 14,
-          textColor: Colors.white,
-          isFontRegular: true,
-        ).expanded(),
-      ],
-    ).marginOnly(top: 16, left: 20, right: 20);
-  }
-}
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/uk_report_casual_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+
+/*
+ * 用工的列表
+ */
+class CasualPayoutReportItem extends StatelessWidget {
+  final int index;
+  final UkReportCasualRows item;
+
+  CasualPayoutReportItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.symmetric(vertical: 23, horizontal: 21),
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
+      decoration: BoxDecoration(
+        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(5), // 设置圆角
+      ),
+      child: Column(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          // 部门
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Outlet:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //部门
+              MyTextView(
+                item.outletName??"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ),
+
+          // 小时
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                '${"Hours".tr}:',
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //文本
+              MyTextView(
+                item.totHrs?.toString()??'-',
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 总金额
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                '${"TotalAmt".tr}:',
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //文本
+              MyTextView(
+                item.totAmt?.toString()??"-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+        ],
+      ),
+    );
+  }
+}

+ 102 - 77
packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_page.dart

@@ -1,23 +1,28 @@
 import 'package:cs_resources/constants/color_constants.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:shared/utils/date_time_utils.dart';
-import 'package:shared/utils/screen_util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/load_state_layout.dart';
-import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
 
+import 'casual_payout_report_item.dart';
 import 'casual_payout_report_controller.dart';
 
-import 'package:plugin_basic/base/base_stateless_page.dart';
+import 'package:plugin_basic/base/base_state.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
 import 'package:plugin_basic/utils/ext_get_nav.dart';
 import 'package:router/path/router_path.dart';
-
-import 'casual_payout_report_item.dart';
+import 'package:shared/utils/screen_util.dart';
+import 'package:widgets/my_appbar.dart';
 import 'casual_payout_report_state.dart';
 
-class UKCasualPayoutReportPage extends BaseStatelessPage<CasualPayoutReportController> {
+/*
+ * 最后一个Casual payout 的月度报表
+ */
+class UKCasualPayoutReportPage extends BaseStatefulPage<CasualPayoutReportController> {
   UKCasualPayoutReportPage({Key? key}) : super(key: key);
 
   //启动当前页面
@@ -25,98 +30,118 @@ class UKCasualPayoutReportPage extends BaseStatelessPage<CasualPayoutReportContr
     return Get.start(RouterPath.UKReportCasualPayout);
   }
 
+  @override
+  CasualPayoutReportController createRawController() {
+    return CasualPayoutReportController();
+  }
+
+  @override
+  State<UKCasualPayoutReportPage> createState() => _LabourReviewState();
+}
+
+class _LabourReviewState extends BaseState<UKCasualPayoutReportPage, CasualPayoutReportController> {
   late CasualPayoutReportState state;
 
   @override
   void initState() {
+    super.initState();
     state = controller.state;
   }
 
   @override
-  CasualPayoutReportController createRawController() {
-    return CasualPayoutReportController();
-  }
-
-  @override
-  Widget buildWidget(BuildContext context) {
+  Widget build(BuildContext context) {
     return autoCtlGetBuilder(builder: (controller) {
-      return Scaffold(
-        extendBodyBehindAppBar: true,
-        appBar: MyAppBar.appBar(context, "YY Casual Labour Report".tr),
-        body: SafeArea(
+      return SafeArea(
         bottom: MediaQuery.of(context).padding.bottom > 38,
-          top: false,
-          child: Container(
-            width: double.infinity,
-            height: double.infinity,
-            padding: EdgeInsets.only(top: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1),
-            decoration: const BoxDecoration(
-              gradient: LinearGradient(
-                colors: [
-                  Color(0xFF091D44),
-                  Color(0xFF245A8A),
-                  Color(0xFF7F7CEC),
-                ],
-                begin: Alignment.topCenter,
-                end: Alignment.bottomCenter,
-              ),
+        top: false,
+        child: Container(
+          width: double.infinity,
+          height: double.infinity,
+          padding: EdgeInsets.only(top: ScreenUtil.getStatusBarH(context)),
+          decoration: const BoxDecoration(
+            gradient: LinearGradient(
+              colors: [
+                Color(0xFF091D44),
+                Color(0xFF245A8A),
+                Color(0xFF7F7CEC),
+              ],
+              begin: Alignment.topCenter,
+              end: Alignment.bottomCenter,
             ),
-            child: Column(
-              children: [
-                // 时间筛选
-                Container(
-                    width: double.infinity,
-                    height: 36,
-                    margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
-                    decoration: BoxDecoration(
-                      color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
-                      borderRadius: BorderRadius.circular(20.0), // 设置圆角
-                    ),
-                    child: Row(
-                      children: [
-                        MyTextView(
-                          DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM-dd"),
-                          hint: "Start Date".tr,
-                          textHintColor: ColorConstants.textGrayAECAE5,
-                          fontSize: 15,
-                          textAlign: TextAlign.center,
-                          isFontRegular: true,
-                          onClick: controller.pickerStartDate,
-                          textColor: ColorConstants.textGrayAECAE5,
-                        ).expanded(),
-                        Container(color: ColorConstants.dividerBar, height: 21.5, width: 0.5),
-                        MyTextView(
-                          DateTimeUtils.formatDate(state.endDateTime, format: "yyyy-MM-dd"),
-                          hint: "End Date".tr,
-                          textHintColor: ColorConstants.textGrayAECAE5,
-                          fontSize: 15,
-                          textAlign: TextAlign.center,
-                          isFontRegular: true,
-                          onClick: controller.pickerEndDate,
-                          textColor: ColorConstants.textGrayAECAE5,
-                        ).expanded(),
-                      ],
-                    )),
+          ),
+          child: Column(
+            children: [
+              MyAppBar.titleBar(context, "Casual Payout".tr),
 
-                //动态列表
-                LoadStateLayout(
+              //选择时间
+              Container(
+                  width: double.infinity,
+                  height: 36,
+                  margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
+                  decoration: BoxDecoration(
+                    color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+                    borderRadius: BorderRadius.circular(20.0), // 设置圆角
+                  ),
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      MyTextView(
+                        DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM"),
+                        hint: "Month".tr,
+                        textHintColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 15,
+                        textAlign: TextAlign.center,
+                        isFontRegular: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                      ).expanded(),
+                    ],
+                  ).onTap(()=>{
+                    controller.showDatePicker()
+                  })),
+
+              Padding(
+                padding: const EdgeInsets.only(left: 15,right: 15),
+                child: Row(
+                    mainAxisSize: MainAxisSize.max,
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      MyTextView(
+                        "YY Casual Report By Payout Date (Based the Client Rate)",
+                        isFontMedium: true,
+                        textColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 16,
+                        marginBottom: 10,
+                      ).expanded(),
+                    ]
+                ),
+              ),
+
+              //底部的列表
+              EasyRefresh(
+                controller: controller.refreshController,
+                onRefresh: controller.onRefresh,
+                onLoad: controller.loadMore,
+                child: LoadStateLayout(
                   state: controller.loadingState,
                   errorMessage: controller.errorMessage,
                   errorRetry: () {
                     controller.retryRequest();
                   },
                   successSliverWidget: [
-
-                    SliverList(delegate: SliverChildBuilderDelegate((context, index) {
-                        return ReportLabourItem(entity: state.entity, type: index);
+                    SliverList(
+                        delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                        return CasualPayoutReportItem(
+                          index: index,
+                          item: state.datas[index],
+                        );
                       },
-                      childCount: state.datas.isNotEmpty ? 3 : 0,
+                      childCount: state.datas.length,
                     ))
-
                   ],
-                ).expanded(),
-              ],
-            ),
+                ),
+              ).expanded(),
+            ],
           ),
         ),
       );

+ 3 - 5
packages/cpt_uk/lib/modules/report/casual_payout_report/casual_payout_report_state.dart

@@ -1,10 +1,8 @@
-import 'package:domain/entity/response/labour_report_entity.dart';
+import 'package:domain/entity/response/uk_report_casual_entity.dart';
 
 class CasualPayoutReportState {
-
   DateTime? startDateTime;
-  DateTime? endDateTime;
 
-  LabourReportEntity? entity;   //主体数据
-  List<LabourReportRows> datas = [];  //列表数据
+  //页面的列表数据
+  List<UkReportCasualRows> datas = [];
 }

+ 45 - 88
packages/cpt_uk/lib/modules/report/casual_report/casual_report_controller.dart

@@ -1,6 +1,8 @@
 import 'package:domain/entity/response/labour_request_index_entity.dart';
 import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:domain/entity/response/uk_report_casual_entity.dart';
 import 'package:domain/repository/labour_repository.dart';
+import 'package:domain/repository/uk_report_repository.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
@@ -18,129 +20,84 @@ import 'package:widgets/widget_export.dart';
 import 'casual_report_state.dart';
 
 class CasualReportController extends GetxController with DioCancelableMixin {
-  final LabourRepository _labourRepository = Get.find();
+  final UKReportRepository _ukReportRepository = Get.find();
   final CasualReportState state = CasualReportState();
 
-  var _curPage = 1;
-  var _needShowPlaceholder = true;
-
   //页面PlaceHolder的展示
-  LoadState loadingState = LoadState.State_Success;
+  LoadState loadingState = LoadState.State_Loading;
   String? errorMessage;
 
+  @override
+  void onInit() {
+    super.onInit();
+    state.startDateTime = DateTimeUtils.getFirstDayOfMonth();
+    state.endDateTime = DateTimeUtils.getLastDayOfMonth();
+  }
+
   //刷新页面状态
   void changeLoadingState(LoadState state) {
     loadingState = state;
     update();
   }
 
-  // Refresh 控制器
-  final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,
-    controlFinishLoad: true,
-  );
-
-  // Refresh 刷新事件
-  Future onRefresh() async {
-    _curPage = 1;
-    fetchList();
-  }
-
-  // Refresh 加载事件
-  Future loadMore() async {
-    _curPage++;
-    fetchList();
+  //重试
+  void retryRequest() {
+    fetchReportData();
   }
 
-  // 重试请求
-  Future retryRequest() async {
-    _curPage = 1;
-    _needShowPlaceholder = true;
-    fetchList();
-  }
+  // 获取当前列表数据
+  void fetchReportData() async {
+    changeLoadingState(LoadState.State_Loading);
 
-  /// 获取服务器数据,通知消息列表
-  Future fetchList() async {
-    if (_needShowPlaceholder) {
-      changeLoadingState(LoadState.State_Loading);
-    }
-
-    //请求列表数据
-    var listResult = await _labourRepository.fetchLabourReviewList(
-      "",
-      DateTimeUtils.formatDate(state.selectedDate, format: "yyyy-MM-dd"),
-      DateTimeUtils.formatDate(state.selectedDate, format: "yyyy-MM-dd"),
-      "",
-      curPage: _curPage,
+    var result = await _ukReportRepository.fetchReportCasualPayData(
+      startDate: DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM-dd"),
+      endDate: DateTimeUtils.formatDate(state.endDateTime, format: "yyyy-MM-dd"),
       cancelToken: cancelToken,
     );
-    
-    // 处理数据
-    if (listResult.isSuccess) {
-      handleList(listResult.data?.rows);
-    } else {
-      errorMessage = listResult.errorMsg;
-      changeLoadingState(LoadState.State_Error);
-    }
-
-    // 最后赋值
-    _needShowPlaceholder = false;
-  }
 
-  // 处理数据与展示的逻辑
-  void handleList(List<LabourReviewListRows>? list) {
-    if (list != null && list.isNotEmpty) {
-      //有数据,判断是刷新还是加载更多的数据
-      if (_curPage == 1) {
-        //刷新的方式
-        state.datas.clear();
-        state.datas.addAll(list);
-        refreshController.finishRefresh();
-
-        //更新展示的状态
+    if (result.isSuccess) {
+      state.entity = result.data;
+      state.datas = result.data?.rows ?? [];
+      if (state.datas.isNotEmpty) {
         changeLoadingState(LoadState.State_Success);
       } else {
-        //加载更多
-        state.datas.addAll(list);
-        refreshController.finishLoad();
-        update();
-      }
-    } else {
-      if (_curPage == 1) {
-        //展示无数据的布局
-        state.datas.clear();
         changeLoadingState(LoadState.State_Empty);
-        refreshController.finishRefresh();
-      } else {
-        //展示加载完成,没有更多数据了
-        refreshController.finishLoad(IndicatorResult.noMore);
       }
+    } else {
+      errorMessage = result.errorMsg ?? "Network Load Error".tr;
+      changeLoadingState(LoadState.State_Error);
     }
   }
 
   @override
   void onReady() {
     super.onReady();
-    fetchList();
+    fetchReportData();
   }
 
-  @override
-  void onClose() {
-    state.datas.clear();
-    super.onClose();
+  /// 筛选开始日期
+  void pickerStartDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.startDateTime,
+      onDateTimeChanged: (date) {
+        state.startDateTime = date;
+        update();
+        fetchReportData();
+      },
+      title: "Start Date".tr,
+    );
   }
 
-  /// 年月的日期筛选
-  void showDatePicker() {
-
+  /// 筛选结束日期
+  void pickerEndDate() {
     DatePickerUtil.showCupertinoDatePicker(
-      selectedDateTime: state.selectedDate ?? DateTime.now(),
-      mode: CupertinoDatePickerMode.monthYear,
+      selectedDateTime: state.endDateTime ?? state.startDateTime,
       onDateTimeChanged: (date) {
-        state.selectedDate = date;
+        state.endDateTime = date;
         update();
+        fetchReportData();
       },
-      title: "Select Date".tr,
+      title: "End Date".tr,
     );
   }
 

+ 228 - 108
packages/cpt_uk/lib/modules/report/casual_report/casual_report_item.dart

@@ -1,108 +1,228 @@
-import 'package:cs_resources/constants/color_constants.dart';
-import 'package:cs_resources/generated/assets.dart';
-import 'package:domain/entity/response/labour_review_list_entity.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-import 'package:plugin_basic/basic_export.dart';
-import 'package:widgets/ext/ex_widget.dart';
-import 'package:widgets/my_text_view.dart';
-
-/*
- * 用工的列表
- */
-class CasualReportItem extends StatelessWidget {
-  final int index;
-  final LabourReviewListRows item;
-
-  CasualReportItem({
-    required this.index,
-    required this.item,
-  });
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      padding: const EdgeInsets.symmetric(vertical: 23, horizontal: 21),
-      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
-      decoration: BoxDecoration(
-        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
-        borderRadius: BorderRadius.circular(5), // 设置圆角
-      ),
-      child: Column(
-        mainAxisSize: MainAxisSize.max,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          // 部门
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              MyTextView(
-                "Outlet:".tr,
-                isFontRegular: true,
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-              ),
-
-              //部门
-              MyTextView(
-                item.departmentName ?? "-",
-                marginLeft: 5,
-                isFontRegular: true,
-                textColor: Colors.white,
-                fontSize: 14,
-              ).expanded(),
-            ],
-          ),
-
-          // 小时
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              MyTextView(
-                "Hours(2):",
-                isFontRegular: true,
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-              ),
-
-              //文本
-              MyTextView(
-                "2h",
-                marginLeft: 5,
-                isFontRegular: true,
-                textColor: Colors.white,
-                fontSize: 14,
-              ).expanded(),
-            ],
-          ).marginOnly(top: 15),
-
-          // 总金额
-          Row(
-            mainAxisSize: MainAxisSize.max,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              MyTextView(
-                "TotalAmt(0):",
-                isFontRegular: true,
-                textColor: ColorConstants.textGrayAECAE5,
-                fontSize: 14,
-              ),
-
-              //文本
-              MyTextView(
-                "£ 0",
-                marginLeft: 5,
-                isFontRegular: true,
-                textColor: Colors.white,
-                fontSize: 14,
-              ).expanded(),
-            ],
-          ).marginOnly(top: 15),
-        ],
-      ),
-    );
-  }
-}
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/uk_report_casual_entity.dart';
+import 'package:domain/entity/response/uk_report_casual_pay_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+
+/*
+ * 用工的列表
+ */
+class CasualReportItem extends StatelessWidget {
+  UkReportCasualPayEntity? entity; //主体数据
+  int type; //0 Completed  1 Incomplete  2 Completed + Incomplete
+
+  CasualReportItem({
+    required this.entity,
+    required this.type,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    bool isComplated = type == 0;
+    bool isIncomplete = type == 1;
+    bool isCompletedAndIncomplete = type == 2;
+    return Container(
+      width: double.infinity,
+      padding: const EdgeInsets.only(top: 16, bottom: 20),
+      margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),
+      decoration: BoxDecoration(
+        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(5), // 设置圆角
+      ),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            isComplated
+                ? "Completed".tr
+                : isIncomplete
+                ? "Incomplete".tr
+                : "Completed + Incomplete".tr,
+            fontSize: 14,
+            isFontBold: true,
+            marginBottom: 15,
+            marginLeft: 20,
+            marginRight: 20,
+            textColor: isComplated
+                ? ColorConstants.textGreen0AC074
+                : isIncomplete
+                ? ColorConstants.textBlue06D9FF
+                : ColorConstants.textRedFF6262,
+          ),
+          const Divider(height: 0.5, color: ColorConstants.dividerBar),
+
+          Row(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+
+
+
+              MyTextView(
+                "Outlet".tr,
+                fontSize: 14,
+                textColor: Colors.white,
+                isFontRegular: true,
+              ).expanded(),
+              Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  MyTextView("Hours".tr, textColor: Colors.white, fontSize: 14, isFontRegular: true),
+                  MyTextView(
+                    _getTitleHeaderData(entity!, isComplated, isIncomplete, isCompletedAndIncomplete, 'hours')??'--',
+                    textColor: isComplated
+                        ? ColorConstants.textGreen0AC074
+                        : isIncomplete
+                        ? ColorConstants.textBlue06D9FF
+                        : ColorConstants.textRedFF6262,
+                    fontSize: 14,
+                    isFontRegular: true,
+                  ),
+                ],
+              ).expanded(),
+              Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  MyTextView("Count".tr, textColor: Colors.white, fontSize: 14, isFontRegular: true),
+                  MyTextView(
+                    _getTitleHeaderData(entity!, isComplated, isIncomplete, isCompletedAndIncomplete, 'count')??'--',
+                    textColor: isComplated
+                        ? ColorConstants.textGreen0AC074
+                        : isIncomplete
+                        ? ColorConstants.textBlue06D9FF
+                        : ColorConstants.textRedFF6262,
+                    fontSize: 14,
+                    isFontRegular: true,
+                  ),
+                ],
+              ).expanded(),
+              Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  MyTextView("TotalAmt".tr, textColor: Colors.white, fontSize: 14, isFontRegular: true),
+                  MyTextView(
+                    _getTitleHeaderData(entity!, isComplated, isIncomplete, isCompletedAndIncomplete, 'totalAmount')??'--',
+                    textColor: isComplated
+                        ? ColorConstants.textGreen0AC074
+                        : isIncomplete
+                        ? ColorConstants.textBlue06D9FF
+                        : ColorConstants.textRedFF6262,
+                    fontSize: 14,
+                    isFontRegular: true,
+                  ),
+                ],
+              ).expanded(),
+            ],
+
+          ).marginOnly(left: 20, right: 20, top: 18, bottom: 2),
+
+          //底部的实际数据
+          ...(entity?.rows?.map((item) {
+            return _buildCardContentItemMainContent(
+              item.outletName,
+              _getHours(item, isComplated, isIncomplete, isCompletedAndIncomplete),
+              _getCount(item, isComplated, isIncomplete, isCompletedAndIncomplete),
+              _getAgAmt(item, isComplated, isIncomplete, isCompletedAndIncomplete),
+            );
+          }).toList() ??
+              []),
+        ],
+      ),
+    );
+  }
+
+  String? _getHours(UkReportCasualPayRows item, bool isComplated, bool isIncomplete, bool isCompletedAndIncomplete) {
+    if(isComplated){
+      return item?.hrs?.toString()??'-';
+    }else if(isIncomplete){
+      return item?.inHrs?.toString()??'-';
+    }else {
+      return item?.totHrs?.toString()??'-';
+    }
+
+  }
+
+  String? _getCount(UkReportCasualPayRows item, bool isComplated, bool isIncomplete, bool isCompletedAndIncomplete) {
+    if(isComplated){
+      return item?.num?.toString()??'-';
+    }else if(isIncomplete){
+      return item?.inNum?.toString()??'-';
+    }else {
+      return item?.totNum?.toString()??'-';
+    }
+
+  }
+
+  String? _getAgAmt(UkReportCasualPayRows item, bool isComplated, bool isIncomplete, bool isCompletedAndIncomplete) {
+    if(isComplated){
+      return item?.amt?.toString()??'-';
+    }else if(isIncomplete){
+      return item?.inAmt?.toString()??'-';
+    }else {
+      return item?.totAmt?.toString()??'-';
+    }
+  }
+
+  Widget _buildCardContentItemMainContent(String? outletName, String? hours, String? num,  String? agAmt) {
+    return Row(
+      children: [
+        MyTextView(
+          outletName ?? "",
+          fontSize: 14,
+          textColor: Colors.white,
+          isFontRegular: true,
+        ).expanded(),
+        MyTextView(
+          "$hours H",
+          fontSize: 14,
+          textColor: Colors.white,
+          isFontRegular: true,
+        ).expanded(),
+        MyTextView(
+          "$num",
+          fontSize: 14,
+          textColor: Colors.white,
+          isFontRegular: true,
+        ).expanded(),
+        MyTextView(
+          "\£ $agAmt",
+          fontSize: 14,
+          textColor: Colors.white,
+          isFontRegular: true,
+        ).expanded(),
+      ],
+    ).marginOnly(top: 16, left: 20, right: 20);
+  }
+
+  String? _getTitleHeaderData(UkReportCasualPayEntity entity, bool isComplated, bool isIncomplete, bool isCompletedAndIncomplete, String type) {
+    switch(type){
+      case 'hours':
+        if(isComplated){
+          return entity?.total?.hrs?.toString()??'-';
+        }else if(isIncomplete){
+          return entity?.total?.inHrs?.toString()??'-';
+        }else {
+          return entity?.total?.totHrs?.toString()??'-';
+        }
+      case 'count':
+        if(isComplated){
+          return entity?.total?.num?.toString()??'-';
+        }else if(isIncomplete){
+          return entity?.total?.inNum?.toString()??'-';
+        }else {
+          return entity?.total?.totNum?.toString()??'-';
+        }
+      case 'totalAmount':
+        if(isComplated){
+          return entity?.total?.amt?.toString()??'-';
+        }else if(isIncomplete){
+          return entity?.total?.inAmt?.toString()??'-';
+        }else {
+          return entity?.total?.totAmt?.toString()??'-';
+        }
+    }
+  }
+}

+ 49 - 43
packages/cpt_uk/lib/modules/report/casual_report/casual_report_page.dart

@@ -1,3 +1,4 @@
+import 'package:cs_resources/constants/color_constants.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
@@ -19,7 +20,7 @@ import 'package:widgets/my_appbar.dart';
 import 'casual_report_state.dart';
 
 /*
- * 最后一个Casual的月度报表
+ * Casual 报表
  */
 class UKCasualReportPage extends BaseStatefulPage<CasualReportController> {
   UKCasualReportPage({Key? key}) : super(key: key);
@@ -74,52 +75,57 @@ class _LabourReviewState extends BaseState<UKCasualReportPage, CasualReportContr
 
               //选择时间
               Container(
-                width: double.infinity,
-                height: 42,
-                padding: const EdgeInsets.symmetric(horizontal: 14),
-                margin: const EdgeInsets.only(left: 15, right: 15, top: 10, bottom: 5),
-                decoration: BoxDecoration(
-                  color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
-                  borderRadius: BorderRadius.circular(20), // 设置圆角
-                ),
-                child:Align(
-                  alignment: Alignment.centerLeft, // 左侧对齐
-                  child: MyTextView(
-                    DateTimeUtils.formatDate(state.selectedDate??DateTime.now(),format: "yyyy-MM"),
-                    textColor: Colors.white,
-                    fontSize: 15,
-                    isFontRegular: true,
+                  width: double.infinity,
+                  height: 36,
+                  margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
+                  decoration: BoxDecoration(
+                    color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+                    borderRadius: BorderRadius.circular(20.0), // 设置圆角
                   ),
-                ),
-              ).onTap((){
-                controller.showDatePicker();
-              }),
+                  child: Row(
+                    children: [
+                      MyTextView(
+                        DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM-dd"),
+                        hint: "Start Date".tr,
+                        textHintColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 15,
+                        textAlign: TextAlign.center,
+                        isFontRegular: true,
+                        onClick: controller.pickerStartDate,
+                        textColor: ColorConstants.textGrayAECAE5,
+                      ).expanded(),
+                      Container(color: ColorConstants.dividerBar, height: 21.5, width: 0.5),
+                      MyTextView(
+                        DateTimeUtils.formatDate(state.endDateTime, format: "yyyy-MM-dd"),
+                        hint: "End Date".tr,
+                        textHintColor: ColorConstants.textGrayAECAE5,
+                        fontSize: 15,
+                        textAlign: TextAlign.center,
+                        isFontRegular: true,
+                        onClick: controller.pickerEndDate,
+                        textColor: ColorConstants.textGrayAECAE5,
+                      ).expanded(),
+                    ],
+                  )),
 
-              //底部的列表
-              EasyRefresh(
-                controller: controller.refreshController,
-                onRefresh: controller.onRefresh,
-                onLoad: controller.loadMore,
-                child: LoadStateLayout(
-                  state: controller.loadingState,
-                  errorMessage: controller.errorMessage,
-                  errorRetry: () {
-                    controller.retryRequest();
+              //动态列表
+              LoadStateLayout(
+                state: controller.loadingState,
+                errorMessage: controller.errorMessage,
+                errorRetry: () {
+                  controller.retryRequest();
+                },
+                successSliverWidget: [
+
+                  SliverList(delegate: SliverChildBuilderDelegate((context, index) {
+                    return CasualReportItem(entity: state.entity, type: index);
                   },
-                  successSliverWidget: [
-                    SliverList(
-                        delegate: SliverChildBuilderDelegate(
-                      (context, index) {
-                        return CasualReportItem(
-                          index: index,
-                          item: state.datas[index],
-                        );
-                      },
-                      childCount: state.datas.length,
-                    ))
-                  ],
-                ),
+                    childCount: state.datas.isNotEmpty ? 3 : 0,
+                  ))
+
+                ],
               ).expanded(),
+
             ],
           ),
         ),

+ 6 - 5
packages/cpt_uk/lib/modules/report/casual_report/casual_report_state.dart

@@ -1,9 +1,10 @@
-import 'package:domain/entity/response/labour_request_index_entity.dart';
-import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:domain/entity/response/uk_report_casual_entity.dart';
+import 'package:domain/entity/response/uk_report_casual_pay_entity.dart';
 
 class CasualReportState {
-  DateTime? selectedDate;
+  DateTime? startDateTime;
+  DateTime? endDateTime;
 
-  //页面的列表数据
-  List<LabourReviewListRows> datas = [];
+  UkReportCasualPayEntity? entity;   //主体数据
+  List<UkReportCasualPayRows> datas = [];  //列表数据
 }

+ 23 - 35
packages/cpt_uk/lib/modules/report/outlet_staff_report/outlet_staff_report_controller.dart

@@ -1,5 +1,7 @@
 import 'package:domain/entity/response/staff_request_report_entity.dart';
+import 'package:domain/entity/response/uk_report_outlet_entity.dart';
 import 'package:domain/repository/other_repository.dart';
+import 'package:domain/repository/uk_report_repository.dart';
 import 'package:get/get.dart';
 import 'package:plugin_basic/service/app_config_service.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
@@ -11,9 +13,15 @@ import 'package:widgets/picker/date_picker_util.dart';
 import 'outlet_staff_report_state.dart';
 
 class OutletStaffReportController extends GetxController with DioCancelableMixin {
-  final OtherRepository _otherRepository = Get.find();
+  final UKReportRepository _ukReportRepository = Get.find();
   final OutletStaffReportState state = OutletStaffReportState();
 
+  @override
+  void onInit() {
+    super.onInit();
+    state.formatStartDateTime();
+  }
+
   //页面PlaceHolder的展示
   LoadState loadingState = LoadState.State_Loading;
   String? errorMessage;
@@ -33,41 +41,21 @@ class OutletStaffReportController extends GetxController with DioCancelableMixin
   void fetchReportData() async {
     changeLoadingState(LoadState.State_Loading);
 
-    //根据不同的国家,调用不同的接口
-    if (ConfigService.to.selectCountry.value == 1) {
-      //如果是新加坡版本的
-      var result = await _otherRepository.fetchReportStaffRequest(
-        DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM-dd"),
-        DateTimeUtils.formatDate(state.endDateTime, format: "yyyy-MM-dd"),
-        cancelToken: cancelToken,
-      );
-      if (result.isSuccess) {
-        state.datas = result.list
-                ?.whereType<StaffRequestReportEntity>() // 直接过滤出非 null 的 StaffRequestReportEntity
-                .toList() ??
-            [];
-        changeLoadingState(LoadState.State_Success);
-      } else {
-        errorMessage = result.errorMsg ?? "Network Load Error".tr;
-        changeLoadingState(LoadState.State_Error);
-      }
+    //如果是越南的版本
+    var result = await _ukReportRepository.fetchReportOutletData(
+      startDate: DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM-dd"),
+      endDate: DateTimeUtils.formatDate(state.endDateTime, format: "yyyy-MM-dd"),
+      cancelToken: cancelToken,
+    );
+    if (result.isSuccess) {
+      state.datas = result.data?.requestList
+          ?.whereType<UkReportOutletRequestList>() // 直接过滤出非 null 的 StaffRequestReportEntity
+          .toList() ??
+          [];
+      changeLoadingState(LoadState.State_Success);
     } else {
-      //如果是越南的版本
-      var result = await _otherRepository.fetchStaffReportVN(
-        DateTimeUtils.formatDate(state.startDateTime, format: "yyyy-MM-dd"),
-        DateTimeUtils.formatDate(state.endDateTime, format: "yyyy-MM-dd"),
-        cancelToken: cancelToken,
-      );
-      if (result.isSuccess) {
-        state.datas = result.data?.requestList
-                .whereType<StaffRequestReportEntity>() // 直接过滤出非 null 的 StaffRequestReportEntity
-                .toList() ??
-            [];
-        changeLoadingState(LoadState.State_Success);
-      } else {
-        errorMessage = result.errorMsg ?? "Network Load Error".tr;
-        changeLoadingState(LoadState.State_Error);
-      }
+      errorMessage = result.errorMsg ?? "Network Load Error".tr;
+      changeLoadingState(LoadState.State_Error);
     }
   }
 

+ 2 - 2
packages/cpt_uk/lib/modules/report/outlet_staff_report/outlet_staff_report_item.dart

@@ -1,5 +1,5 @@
 import 'package:cs_resources/constants/color_constants.dart';
-import 'package:domain/entity/response/staff_request_report_entity.dart';
+import 'package:domain/entity/response/uk_report_outlet_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
@@ -10,7 +10,7 @@ import 'package:widgets/my_text_view.dart';
 import 'package:widgets/shatter/custom_progress_bar.dart';
 
 class OutletStaffReportItem extends StatelessWidget {
-  final StaffRequestReportEntity item;
+  final UkReportOutletRequestList item;
 
   OutletStaffReportItem({
     required this.item,

+ 7 - 3
packages/cpt_uk/lib/modules/report/outlet_staff_report/outlet_staff_report_state.dart

@@ -1,9 +1,13 @@
-import 'package:domain/entity/response/staff_request_report_entity.dart';
+import 'package:domain/entity/response/uk_report_outlet_entity.dart';
 
 class OutletStaffReportState {
 
   DateTime? startDateTime;
-  DateTime? endDateTime;
+  // startDateTime 为 当月的 1号
+  formatStartDateTime() {
+    startDateTime = DateTime(endDateTime!.year, endDateTime!.month, 1);
+  }
+  DateTime? endDateTime = DateTime.now().add(Duration(days: 0));
 
-  List<StaffRequestReportEntity> datas = [];  //列表数据
+  List<UkReportOutletRequestList> datas = [];  //列表数据
 }

+ 1 - 0
packages/cpt_uk/lib/modules/report/report_list/report_list_controller.dart

@@ -60,6 +60,7 @@ class ReportListController extends GetxController {
 
   /// 跳转到指定的模块中去
   void gotoReportPage(HomeModule module) {
+    Log.d("点击的 module  ${module.key}");
     switch (module.key) {
       case 'labour':
         UKLabourReportPage.startInstance();

+ 49 - 12
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_controller.dart

@@ -1,21 +1,29 @@
 import 'package:domain/entity/response/attendance_review_entity.dart';
+import 'package:domain/entity/response/uk_attendance_review_entity.dart';
+import 'package:domain/entity/response/uk_attendance_review_remark_entity.dart';
 import 'package:domain/repository/job_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
 import 'package:get/get.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/loading/loading_engine.dart';
 import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:plugin_platform/http/http_result.dart';
 
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/dialog/app_default_dialog.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../../job/job_applied_workflow/applied_workflow_page.dart';
 import 'attendance_review_reject_dialog.dart';
+import 'attendance_review_remark_dialog.dart';
 import 'attendance_review_state.dart';
 
 class AttendanceReviewController extends GetxController with DioCancelableMixin {
   final JobRepository _jobRepository = Get.find();
+  final UKJobRepository _ukJobRepository = Get.find();
   final AttendanceReviewState state = AttendanceReviewState();
 
   var _curPage = 1;
@@ -62,8 +70,7 @@ class AttendanceReviewController extends GetxController with DioCancelableMixin
       changeLoadingState(LoadState.State_Loading);
     }
 
-    // 并发执行两个请求
-    final listResult = await _jobRepository.fetchAttendanceReviewList(
+    final listResult = await _ukJobRepository.fetchAttendanceReviewList(
       state.keyword,
       curPage: _curPage,
       cancelToken: cancelToken,
@@ -82,7 +89,7 @@ class AttendanceReviewController extends GetxController with DioCancelableMixin
   }
 
   // 处理数据与展示的逻辑
-  void handleList(List<AttendanceReviewRows>? list) {
+  void handleList(List<UkAttendanceReviewRows>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_curPage == 1) {
@@ -141,17 +148,19 @@ class AttendanceReviewController extends GetxController with DioCancelableMixin
   }
 
   /// Item选中与未选中设置
-  void doSelectedOrNot(AttendanceReviewRows data) {
+  void doSelectedOrNot(UkAttendanceReviewRows data) {
     data.isSelected = !data.isSelected;
     Log.d("isSelected:${data.isSelected}");
     update();
   }
 
   /// 执行批量同意
-  void _requestBatchApprove(String recordIds) async {
+  void _requestBatchApprove(String recordIds, String? auditMark) async {
     //执行请求
-    var result = await _jobRepository.approveAttendanceReviews(
+    var result = await _ukJobRepository.attendanceReviewsBatchSubmit(
       recordIds,
+      'approve', //审核类型Type【approve|reject】
+      auditMark,
       cancelToken: cancelToken,
     );
 
@@ -167,11 +176,12 @@ class AttendanceReviewController extends GetxController with DioCancelableMixin
   }
 
   /// 执行批量拒绝
-  void _requestBatchReject(String recordIds, String? reason) async {
+  void _requestBatchReject(String recordIds, String? auditMark) async {
     //执行请求
-    var result = await _jobRepository.rejectLabourReviews(
+    var result = await _ukJobRepository.attendanceReviewsBatchSubmit(
       recordIds,
-      reason,
+      'reject', //审核类型Type【approve|reject】
+      auditMark,
       cancelToken: cancelToken,
     );
 
@@ -200,7 +210,7 @@ class AttendanceReviewController extends GetxController with DioCancelableMixin
           title: "Message".tr,
           message: "Are you sure you want to setting approved?".tr,
           confirmAction: () {
-            _requestBatchApprove(recordIds);
+            _requestBatchApprove(recordIds, '');
           },
         ),
       );
@@ -243,7 +253,34 @@ class AttendanceReviewController extends GetxController with DioCancelableMixin
   }
 
   /// 去用工审核流程页面
-  void gotoStatusViewPage(AttendanceReviewRows data) {
-    ToastEngine.show("去工作流页面");
+  void gotoStatusViewPage(UkAttendanceReviewRows data) {
+    UKAppliedWorkflowPage.startInstance(data.appliedId?.toString());
+  }
+
+  /// 获取remark info
+  Future<UkAttendanceReviewRemarkEntity> getRemarkInfo(String appliedId) async {
+    final result = await _ukJobRepository.fetchAttendanceReviewRemarkInfo(appliedId);
+    if(result.isSuccess){
+      return result.data!;
+    }else {
+      return HttpResult(isSuccess: false) as UkAttendanceReviewRemarkEntity;
+    }
+  }
+
+  /// 显示 remarks 弹框
+  void showRemarkDialog(UkAttendanceReviewRows data) async{
+    // 先获取 remark info
+    LoadingEngine.show();
+    final result = await getRemarkInfo(data.appliedId.toString());
+    Log.d("result   ---- ${result}");
+    LoadingEngine.dismiss();
+    DialogEngine.show(
+      widget: AttendaceReviewRemarkDialog(
+        remarkInfo: result,
+        confirmAction: (reason) {
+
+        },
+      ),
+    );
   }
 }

+ 69 - 63
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_item.dart

@@ -1,12 +1,14 @@
 import 'package:cs_resources/constants/color_constants.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/response/attendance_review_entity.dart';
+import 'package:domain/entity/response/uk_attendance_review_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:plugin_basic/basic_export.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';
 
@@ -15,14 +17,18 @@ import 'package:widgets/my_text_view.dart';
  */
 class AttendanceReviewItem extends StatelessWidget {
   final int index;
-  final AttendanceReviewRows item;
+  final UkAttendanceReviewRows item;
+  final VoidCallback? onEditAction;
   final VoidCallback? onStatusAction;
+  final VoidCallback? onRemarkAction;
   final VoidCallback? onItemAction;
 
   AttendanceReviewItem({
     required this.index,
     required this.item,
+    this.onEditAction,
     this.onStatusAction,
+    this.onRemarkAction,
     this.onItemAction,
   });
 
@@ -258,68 +264,68 @@ class AttendanceReviewItem extends StatelessWidget {
           ).marginOnly(top: 12),
 
           // //按钮组
-          // Visibility(
-          //   visible: item.actionList?.isNotEmpty ?? false,
-          //   child: Row(
-          //     mainAxisSize: MainAxisSize.max,
-          //     mainAxisAlignment: MainAxisAlignment.end,
-          //     crossAxisAlignment: CrossAxisAlignment.center,
-          //     children: [
-          //       //编辑按钮
-          //       Visibility(
-          //         visible: item.actionList?.contains("edit") ?? false,
-          //         child: MyButton(
-          //           onPressed: () {
-          //             FocusScope.of(context).unfocus();
-          //             onEditAction?.call();
-          //           },
-          //           text: "Edit".tr,
-          //           textColor: ColorConstants.white,
-          //           backgroundColor: hexToColor(
-          //             "#FFBB1B",
-          //           ),
-          //           radius: 17.25,
-          //           minWidth: 60,
-          //           minHeight: 35,
-          //         ).marginOnly(left: 12),
-          //       ),
-          //
-          //       //状态工作流按钮
-          //       Visibility(
-          //         visible: item.actionList?.contains("status") ?? false,
-          //         child: MyButton(
-          //           onPressed: () {
-          //             FocusScope.of(context).unfocus();
-          //             onStatusAction?.call();
-          //           },
-          //           text: "Status".tr,
-          //           textColor: ColorConstants.white,
-          //           backgroundColor: hexToColor("#0AC074"),
-          //           radius: 17.25,
-          //           minWidth: 60,
-          //           minHeight: 35,
-          //         ).marginOnly(left: 12),
-          //       ),
-          //
-          //       //Remark按钮
-          //       Visibility(
-          //         visible: item.actionList?.contains("remarks") ?? false,
-          //         child: MyButton(
-          //           onPressed: () {
-          //             FocusScope.of(context).unfocus();
-          //             onRemarkAction?.call();
-          //           },
-          //           text: "Remarks".tr,
-          //           textColor: ColorConstants.white,
-          //           backgroundColor: hexToColor("#56AAFF"),
-          //           radius: 17.25,
-          //           minWidth: 60,
-          //           minHeight: 35,
-          //         ).marginOnly(left: 12),
-          //       ),
-          //     ],
-          //   ).marginOnly(top: 15),
-          // ),
+          Visibility(
+            visible: item.actionList?.isNotEmpty ?? false,
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                //编辑按钮
+                // Visibility(
+                //   visible: item.actionList?.contains("edit") ?? false,
+                //   child: MyButton(
+                //     onPressed: () {
+                //       FocusScope.of(context).unfocus();
+                //       onEditAction?.call();
+                //     },
+                //     text: "Edit".tr,
+                //     textColor: ColorConstants.white,
+                //     backgroundColor: hexToColor(
+                //       "#FFBB1B",
+                //     ),
+                //     radius: 17.25,
+                //     minWidth: 60,
+                //     minHeight: 35,
+                //   ).marginOnly(left: 12),
+                // ),
+
+                //状态工作流按钮
+                Visibility(
+                  visible: item.actionList?.contains("status") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onStatusAction?.call();
+                    },
+                    text: "Status".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#0AC074"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+
+                //Remark按钮
+                Visibility(
+                  visible: item.actionList?.contains("remark") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onRemarkAction?.call();
+                    },
+                    text: "Remarks".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#56AAFF"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+              ],
+            ).marginOnly(top: 15),
+          ),
         ],
       ),
     ).onTap(() {

+ 4 - 1
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_page.dart

@@ -117,11 +117,14 @@ class _LabourReviewState extends BaseState<UKAttendanceReviewPage, AttendanceRev
                           index: index,
                           item: state.datas[index],
                           onStatusAction: () {
-
+                            controller.gotoStatusViewPage(state.datas[index]);
                           },
                           onItemAction: () {
                             controller.doSelectedOrNot(state.datas[index]);
                           },
+                          onRemarkAction: () {
+                            controller.showRemarkDialog(state.datas[index]);
+                          },
                         );
                       },
                       childCount: state.datas.length,

+ 219 - 0
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_remark_dialog.dart

@@ -0,0 +1,219 @@
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/uk_attendance_review_entity.dart';
+import 'package:domain/entity/response/uk_attendance_review_remark_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * remark的弹窗
+ */
+class AttendaceReviewRemarkDialog extends StatefulWidget {
+
+  UkAttendanceReviewRemarkEntity? remarkInfo;
+  void Function(String reason)? confirmAction;
+
+  AttendaceReviewRemarkDialog({this.confirmAction, this.remarkInfo});
+
+  @override
+  State<AttendaceReviewRemarkDialog> createState() => _AttendaceReviewRemarkDialogState();
+}
+
+class _AttendaceReviewRemarkDialogState extends State<AttendaceReviewRemarkDialog> {
+
+  late TextEditingController _controller;
+  late FocusNode _focusNode;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = TextEditingController();
+    _focusNode = FocusNode();
+
+    _controller.text = widget.remarkInfo?.remark??'-';
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        //Title (如果使用 Container 为最外层容器则默认为 match_parent 的效果,除非我们限制宽度和最大高度最小高度)
+        Stack(
+          children: [
+            Container(
+              width: double.infinity,
+              decoration: const BoxDecoration(
+                color: Colors.white,
+                borderRadius: BorderRadius.all(Radius.circular(15)),
+              ),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Center(
+                    child: MyTextView(
+                      "Remarks".tr,
+                      fontSize: 19,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black,
+                      marginTop: 23,
+                      marginLeft: 22,
+                      marginRight: 22,
+                    ),
+                  ),
+
+                  MyTextView(
+                    widget.remarkInfo?.memberName ?? "",
+                    fontSize: 16,
+                    textColor: ColorConstants.black,
+                    marginTop: 10,
+                    marginLeft: 22,
+                    marginRight: 22,
+                  ),
+
+                  IgnoreKeyboardDismiss(
+                    child: Container(
+                      height: 130,
+                      margin: const EdgeInsets.symmetric(vertical: 19, horizontal: 22),
+                      padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
+                      decoration: BoxDecoration(
+                        color: const Color(0xFFF0F0F0),
+                        border: Border.all(
+                          color: const Color(0xFFD8D8D8),
+                          width: 0.5,
+                        ),
+                      ),
+                      child: TextField(
+                        cursorColor: ColorConstants.black66,
+                        cursorWidth: 1.5,
+                        autofocus: false,
+                        enabled: false,  // 禁止输入
+                        focusNode: _focusNode,
+                        controller: _controller,
+                        // 装饰
+                        decoration: const InputDecoration(
+                          isDense: true,
+                          isCollapsed: true,
+                          border: InputBorder.none,
+                          // hintText: "Enter...".tr,
+                          hintText: "",
+                          hintStyle: TextStyle(
+                            color: ColorConstants.black66,
+                            fontSize: 15.0,
+                            fontWeight: FontWeight.w400,
+                          ),
+
+                        ),
+                        style: const TextStyle(
+                          color: ColorConstants.black,
+                          fontSize: 15.0,
+                          fontWeight: FontWeight.w400,
+                        ),
+                        // 键盘动作右下角图标
+                        textInputAction: TextInputAction.done,
+                        onSubmitted: (value) {
+                          // doCallbackAction();
+                        },
+                      ),
+                    ),
+                  ),
+
+                  // 分割线
+                  Container(
+                    color: const Color(0XFFCECECE),
+                    height: 0.5,
+                  ),
+
+                  //按钮组
+                  Visibility(
+                    visible: false,
+                    child: Row(
+                      children: [
+                        Expanded(
+                            flex: 1,
+                            child: InkWell(
+                              onTap: () {
+                                onCancel();
+                              },
+                              child: MyTextView(
+                                "Cancel".tr,
+                                fontSize: 17.5,
+                                isFontMedium: true,
+                                textAlign: TextAlign.center,
+                                textColor: const Color(0XFF0085C4),
+                                cornerRadius: 3,
+                                borderWidth: 1,
+                              ),
+                            )),
+                        Container(
+                          color: const Color(0xff09141F).withOpacity(0.13),
+                          width: 0.5,
+                        ),
+                        Expanded(
+                            flex: 1,
+                            child: InkWell(
+                              onTap: () {
+                                doCallbackAction();
+                              },
+                              child: MyTextView(
+                                "Submit".tr,
+                                marginLeft: 10,
+                                fontSize: 17.5,
+                                isFontMedium: true,
+                                textAlign: TextAlign.center,
+                                textColor: const Color(0XFF0085C4),
+                                cornerRadius: 3,
+                              ),
+                            )),
+                      ],
+                    ).constrained(height: 46),
+                  ),
+                ],
+              ),
+            ),
+            Positioned(
+              top: 15,
+              right: 15,
+              child: const MyAssetImage(Assets.baseLibDialogCloseRed, width: 20.5, height: 20.5).onTap((){
+                SmartDialog.dismiss();
+              }),
+            )
+          ]
+        ),
+      ],
+    ).constrained(width: 285);
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  //执行回调
+  void doCallbackAction() {
+    _focusNode.unfocus();
+
+    final content = _controller.text.toString();
+
+    if (Utils.isEmpty(content)) {
+      ToastEngine.show("Please Enter Reason".tr);
+      return;
+    }
+
+    onCancel();
+
+    widget.confirmAction?.call(content);
+  }
+}

+ 2 - 2
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_state.dart

@@ -1,4 +1,4 @@
-import 'package:domain/entity/response/attendance_review_entity.dart';
+import 'package:domain/entity/response/uk_attendance_review_entity.dart';
 import 'package:flutter/material.dart';
 
 class AttendanceReviewState {
@@ -7,6 +7,6 @@ class AttendanceReviewState {
   String keyword = "";
 
   //页面的列表数据
-  List<AttendanceReviewRows> datas = [];
+  List<UkAttendanceReviewRows> datas = [];
 
 }

+ 296 - 67
packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_controller.dart

@@ -1,46 +1,100 @@
+import 'package:cpt_uk/modules/job/labour_request_add/widget/labour_request_interface.dart';
+import 'package:cpt_uk/modules/job/labour_request_preselected_list/widget/preselected_add_staff.dart';
+import 'package:cpt_uk/widget/date_range_picker_dialog.dart';
 import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_detail_entity.dart';
 import 'package:domain/repository/labour_repository.dart';
+import 'package:domain/repository/uk_job_repository.dart';
+import 'package:domain/repository/uk_labour_repository.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
 import 'package:plugin_basic/constants/app_constant.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
 import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:plugin_platform/http/http_result.dart';
 import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/util.dart';
 import 'package:widgets/picker/date_picker_util.dart';
 import 'package:widgets/picker/option_pick_util.dart';
+import 'package:file_picker/file_picker.dart';
 
 import 'labour_review_edit_state.dart';
 
-class LabourReviewEditController extends GetxController with DioCancelableMixin {
+class LabourReviewEditController extends GetxController with DioCancelableMixin implements CommonLabourRequestController {
   final LabourRepository _labourRepository = Get.find();
+  final UKJobRepository _ukJobRepository = Get.find();
+  final UkLabourRepository _ukLabourRepository = Get.find();
+
   final LabourReviewEditState state = LabourReviewEditState();
 
+  @override
+  CommonLabourRequestState get commonState => state;
+
   /// 获取首页的数据
   void fetchRequestDetail() async {
     //获取到数据
-
-    final taskFuture = _labourRepository.fetchLabourReviewDetail(state.requestId, cancelToken: cancelToken);
+    Future<HttpResult<UkLabourRequestDetailEntity>> taskFuture;
+    // Log.d("请求的state.appliedId  ${state.appliedId}");
+    if (Utils.isNotEmpty(state.requestId) && state.requestId != "0") {
+      // Log.d("请求的state.appliedId3333  ${state.appliedId}");
+      taskFuture = _ukLabourRepository.fetchLabourRequestDetail(state.requestId);
+    } else {
+      taskFuture = _ukLabourRepository.fetchLabourRequestAddOption();
+    }
 
     var result = await taskFuture;
 
     //处理数据
     if (result.isSuccess) {
       state.labReqOption = result.data;
+      // state.selectedDate = state.labReqOption?.jobStart == null ? null : DateTimeUtils.getDateTime(state.labReqOption!.jobStart!);
       state.selectedStartTime = state.labReqOption?.jobStart == null ? null : DateTimeUtils.getDateTime(state.labReqOption!.jobStart!);
       state.selectedEndTime = state.labReqOption?.jobEnd == null ? null : DateTimeUtils.getDateTime(state.labReqOption!.jobEnd!);
-      state.noStaff = state.labReqOption?.needNum.toString() == "0" ? "" : state.labReqOption?.needNum.toString();
+      state.selectedTypeId = state.labReqOption?.employmentType.toString() ?? '';
+
+      state.attFilePath = state.labReqOption?.attUrl?? '';
+      state.jobSelectJobStart = state.labReqOption?.jobStart?? '';
+      state.jobSelectJobEnd = state.labReqOption?.jobEnd?? '';
+
+
+      if(state.pageType == 0){
+        // 新增
+        state.noStaff = '';
+        state.amount =  '';
+      }else {
+        state.noStaff = state.labReqOption?.needNum?.toString() == "0" ? "" : state.labReqOption?.needNum.toString();
+        state.amount = state.labReqOption?.amount?.toString() == "0" ? "" : state.labReqOption?.amount.toString();
+      }
+
       var needNumController = state.formData['no_of_staff']!['controller'];
-      needNumController.text = state.noStaff;
+      needNumController.text = state.noStaff??state.noStaff!='null'??"0";
       var amountController = state.formData['amount']!['controller'];
-      amountController.text = state.labReqOption?.amount ?? "";
-      state.selectedTemplateId = state.labReqOption?.templateId;
-      state.selectedDepartmentId = state.labReqOption?.departmentId;
+      amountController.text = state.amount??state.amount!='null'??"0";
+
+      var remarkController = state.formData['remark']!['controller'];
+      var eventController = state.formData['event']!['controller'];
+      var eventTypeController = state.formData['event_type']!['controller'];
+      var eventPaxController = state.formData['event_pax']!['controller'];
+      var revenueController = state.formData['revenue']!['controller'];
+      var positionController = state.formData['position']!['controller'];
+      var totalCostController = state.formData['total_cost']!['controller'];
+      remarkController.text = state.labReqOption?.description ?? '';
+      eventController.text = state.labReqOption?.eventName ?? "";
+      eventTypeController.text = state.labReqOption?.eventType ?? "";
+      eventPaxController.text = state.labReqOption?.passengers.toString() ?? "";
+      revenueController.text = state.labReqOption?.estRevenue ?? "";
+      positionController.text = state.labReqOption?.position ?? "";
+      totalCostController.text = state.labReqOption?.estCost ?? "";
 
-      state.chargeOptionId = state.labReqOption?.chargeList.firstWhere((element) => element.checked == "checked").value;
+
+      state.selectedTemplateId = state.labReqOption?.templateId.toString();
+      state.selectedDepartmentId = state.labReqOption?.departmentId.toString();
+      //时薪还是房间计费
+      state.chargeOptionId = state.labReqOption?.chargeList!.firstWhere((element) => element.checked == "checked").value;
 
       update();
     } else {
@@ -54,59 +108,8 @@ class LabourReviewEditController extends GetxController with DioCancelableMixin
     fetchRequestDetail();
   }
 
-  /// 提交
-  void doSubmit() async {
-    var needNumController = state.formData['no_of_staff']!['controller'];
-    var amountController = state.formData['amount']!['controller'];
-    String needNum = needNumController.text.toString();
-    String amount = amountController.text.toString();
-
-    if (Utils.isEmpty(state.selectedTemplateId)) {
-      ToastEngine.show("Choose Job Title".tr);
-      return;
-    } else if (state.selectedStartTime == null) {
-      ToastEngine.show("Choose Start Date".tr);
-      return;
-    } else if (state.selectedEndTime == null) {
-      ToastEngine.show("Choose End Date".tr);
-      return;
-    } else if (Utils.isEmpty(state.selectedDepartmentId)) {
-      ToastEngine.show("Choose Outlet".tr);
-      return;
-    } else if (Utils.isEmpty(needNum)) {
-      ToastEngine.show("Enter No. of Staff".tr);
-      return;
-    } else if (state.labReqOption?.serviceType == 1 && Utils.isEmpty(amount)) {
-      ToastEngine.show("Enter Amount".tr);
-      return;
-    }
-
-
-    var result = await _labourRepository.editLabourReviewSubmit(
-      state.requestId,
-      state.selectedTemplateId,
-      DateTimeUtils.formatDate(state.selectedStartTime),
-      DateTimeUtils.formatDate(state.selectedEndTime),
-      state.selectedDepartmentId,
-      needNum,
-      state.chargeOptionId,
-      state.labReqOption?.serviceType == 1 ? amount : null,
-    );
-
-    //处理数据
-    if (result.isSuccess) {
-      NotifyEngine.showSuccess("Successful".tr);
-
-      //根据类型刷新
-      state.cb?.call(state.requestId ?? "");
-
-      Get.back();
-    } else {
-      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
-    }
-  }
-
   // 筛选工作模板
+  @override
   void pickJobTitle() {
     if (state.labReqOption == null || state.pageType == 2) {
       return;
@@ -116,7 +119,7 @@ class LabourReviewEditController extends GetxController with DioCancelableMixin
     if (state.selectedTemplateId == null) {
       selectedTemplateIndex = 0;
     } else {
-      selectedTemplateIndex = state.labReqOption!.templateList.indexWhere((department) => department.value.toString() == state.selectedTemplateId);
+      selectedTemplateIndex = state.labReqOption!.templateList!.indexWhere((department) => department.value.toString() == state.selectedTemplateId);
     }
 
     if (selectedTemplateIndex < 0) {
@@ -124,16 +127,17 @@ class LabourReviewEditController extends GetxController with DioCancelableMixin
     }
 
     OptionPickerUtil.showCupertinoOptionPicker(
-      items: state.labReqOption!.templateList.map((e) => e.txt!).toList(growable: false),
+      items: state.labReqOption!.templateList!.map((e) => e.txt!).toList(growable: false),
       initialSelectIndex: selectedTemplateIndex,
       onPickerChanged: (_, index) {
-        state.selectedTemplateId = state.labReqOption!.templateList[index].value!.toString();
+        state.selectedTemplateId = state.labReqOption!.templateList![index].value!.toString();
         update();
       },
     );
   }
 
   //选择开始时间
+  @override
   void pickStartTime() {
     if (state.labReqOption == null || state.pageType == 2) {
       return;
@@ -151,6 +155,7 @@ class LabourReviewEditController extends GetxController with DioCancelableMixin
   }
 
   // 选择结束时间
+  @override
   void pickEndTime() {
     if (state.labReqOption == null || state.pageType == 2) {
       return;
@@ -167,8 +172,46 @@ class LabourReviewEditController extends GetxController with DioCancelableMixin
     );
   }
 
+  // 筛选 employ ment type
+  @override
+  void pickEmploymentType() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    int selectedEmploymentTypeIndex;
+    if (state.selectedTypeId == null) {
+      selectedEmploymentTypeIndex = 0;
+    } else {
+      if (state.labReqOption?.employmentList != null && state.labReqOption!.employmentList!.isNotEmpty) {
+        selectedEmploymentTypeIndex = state.labReqOption!.employmentList!.indexWhere(
+                (employment) => employment.value.toString() == state.selectedTypeId
+        );
+      } else {
+        // 处理 departmentList 为空或 null 的情况
+        selectedEmploymentTypeIndex = 0;
+      }
+    }
+
+    if (selectedEmploymentTypeIndex < 0) {
+      selectedEmploymentTypeIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.labReqOption!.employmentList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedEmploymentTypeIndex,
+      onPickerChanged: (_, index) {
+        state.selectedTypeId = state.labReqOption!.employmentList![index].value!.toString();
+        update();
+      },
+    );
+  }
+
+
   // 筛选部门
+  @override
   void pickDepartment() {
+    Log.d("点击了 筛选部门  ${state.labReqOption}");
     if (state.labReqOption == null || state.pageType == 2) {
       return;
     }
@@ -177,7 +220,7 @@ class LabourReviewEditController extends GetxController with DioCancelableMixin
     if (state.selectedDepartmentId == null) {
       selectedDepartmentIndex = 0;
     } else {
-      selectedDepartmentIndex = state.labReqOption!.departmentList.indexWhere((department) => department.value.toString() == state.selectedDepartmentId);
+      selectedDepartmentIndex = state.labReqOption!.departmentList!.indexWhere((department) => department.value.toString() == state.selectedDepartmentId);
     }
 
     if (selectedDepartmentIndex < 0) {
@@ -185,12 +228,198 @@ class LabourReviewEditController extends GetxController with DioCancelableMixin
     }
 
     OptionPickerUtil.showCupertinoOptionPicker(
-      items: state.labReqOption!.departmentList.map((e) => e.txt!).toList(growable: false),
+      items: state.labReqOption!.departmentList!.map((e) => e.txt!).toList(growable: false),
       initialSelectIndex: selectedDepartmentIndex,
       onPickerChanged: (_, index) {
-        state.selectedDepartmentId = state.labReqOption!.departmentList[index].value!.toString();
+        state.selectedDepartmentId = state.labReqOption!.departmentList![index].value!.toString();
+        update();
+      },
+    );
+  }
+
+  // 选择单个文件
+  @override
+  void pickAttFile() async {
+    FilePickerResult? result = await FilePicker.platform.pickFiles(
+      allowMultiple: false,
+      type: FileType.custom,
+      allowedExtensions: ['jpg', 'png', 'jpeg', 'pdf', 'docx'],
+    );
+
+    if (result != null) {
+      PlatformFile selectedPlatformFile = result.files.first;
+      Log.d("path:${selectedPlatformFile.path} name:${selectedPlatformFile.name}");
+
+      state.attFilePath = selectedPlatformFile.path;
+      update();
+
+      // final fileResult = await _thRepository.uploadFile(selectedPlatformFile.path);
+      // if (fileResult.isSuccess) {
+      //   state.attFilePath = fileResult.data?.path;
+      //   update();
+      // } else {
+      //   ToastEngine.show(fileResult.errorMsg ?? "Network Load Error".tr);
+      // }
+    }
+  }
+
+  @override
+  void handlerSelectPreSelect() {
+    // DialogEngine.show(
+    //   widget: PreselectedAddStaff(
+    //     jobId: '0',
+    //     selectedStaffIds: "",
+    //     confirmAction: (selectedIds, [selectedList]) {
+    //
+    //     },
+    //   ),
+    // );
+  }
+
+
+  //选择时间段
+  @override
+  void pickDateRange() {
+    // DialogEngine.show(
+    //   widget: DateRangePickerDialog(
+    //     dateRange: state.repeatDateStr,
+    //     confirmAction: (dateStr) {
+    //       Log.d("选择的时间段:$dateStr");
+    //       update();
+    //     },
+    //   ));
+  }
+  @override
+  void pickJobDate() {
+    // TODO: implement pickJobDate
+  }
+
+  // 编辑状态时 修改 开始日期时间  YYYY-MM-DD HH:mm
+  @override
+  void pickJobStart() {
+    // TODO: implement pickJobStart
+    DatePickerUtil.showCupertinoDatePicker(
+      title: "Job Start".tr,
+      selectedDateTime: state.jobStart,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        Log.d("选取的开始日期时间:${date.toString()}");
+        Log.d("----------${DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd HH:mm')}");
+        state.jobSelectJobStart = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd HH:mm');
         update();
       },
     );
+
+  }
+
+  // 编辑状态时 修改 结束日期时间  YYYY-MM-DD HH:mm
+  @override
+  void pickJobEnd() {
+    // TODO: implement pickJobEnd
+    DatePickerUtil.showCupertinoDatePicker(
+      title: "Job End".tr,
+      selectedDateTime: state.jobStart,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        Log.d("选取的结束日期时间:${date.toString()}");
+        state.jobSelectJobEnd = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd HH:mm');
+        update();
+      },
+    );
+  }
+
+
+  /// 提交
+  @override
+  void doSubmit() async {
+    Log.d("labour_review_edit controller 提交");
+
+    var needNumController = state.formData['no_of_staff']!['controller'];
+    var amountController = state.formData['amount']!['controller'];
+    String needNum = needNumController.text.toString();
+    String amount = amountController.text.toString();
+    // String? jobApplyPreId = state.preSelectedIds;
+
+    var remarkController = state.formData['remark']!['controller'];
+    var eventController = state.formData['event']!['controller'];
+    var eventTypeController = state.formData['event_type']!['controller'];
+    var eventPaxController = state.formData['event_pax']!['controller'];
+    var revenueController = state.formData['revenue']!['controller'];
+    var positionController = state.formData['position']!['controller'];
+    var totalCostController = state.formData['total_cost']!['controller'];
+
+    String event = eventController.text.toString();
+    String eventType = eventTypeController.text.toString();
+    String eventPax = eventPaxController.text.toString();
+    String revenue = revenueController.text.toString();
+    String position = positionController.text.toString();
+    String totalCost = totalCostController.text.toString();
+    String remark = remarkController.text.toString();
+
+
+    if (Utils.isEmpty(state.selectedTemplateId)) {
+      ToastEngine.show("Choose Job Title".tr);
+      return;
+    } else if (state.selectedStartTime == null) {
+      ToastEngine.show("Choose Start Date".tr);
+      return;
+    } else if (state.selectedEndTime == null) {
+      ToastEngine.show("Choose End Date".tr);
+      return;
+    } else if (Utils.isEmpty(state.selectedDepartmentId)) {
+      ToastEngine.show("Choose Outlet".tr);
+      return;
+    } else if (Utils.isEmpty(needNum)) {
+      ToastEngine.show("Enter No. of Staff".tr);
+      return;
+    } else if (state.labReqOption?.serviceType == 1 && Utils.isEmpty(amount)) {
+      ToastEngine.show("Enter Amount".tr);
+      return;
+    }
+
+    Future<HttpResult> taskFuture;
+    // 编辑
+    taskFuture = _ukLabourRepository.labourRequestReviewEditSubmit(
+        requestId: state.requestId,
+        templateId: state.selectedTemplateId,
+        jobStart: "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedStartTime, format: 'HH:mm')}:00",
+        jobEnd: "${DateTimeUtils.formatDate(state.selectedDate, format: 'yyyy-MM-dd')} ${DateTimeUtils.formatDate(state.selectedEndTime, format: 'HH:mm')}:00",
+        departmentId: state.selectedDepartmentId,
+        needNum: needNum,
+        salaryBy: 'hour',
+        amount: state.labReqOption?.serviceType == 1 ? amount : null,
+        employmentType: state.selectedTypeId,
+        eventName: event,
+        eventType: eventType,
+        passengers: eventPax,
+        estRevenue: revenue,
+        position: position,
+        estCost: totalCost,
+        description: remark,
+        attUrl: state.attFilePath,
+        cancelToken: cancelToken
+    );
+
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //根据类型刷新
+      if (state.pageType != 0 && Utils.isNotEmpty(state.requestId) && state.requestId != "0") {
+        //编辑就发送指定的 requestId
+        bus.emit(AppConstant.eventLabourRequestRefresh, state.requestId);
+      } else {
+        //新增的就发送空
+        bus.emit(AppConstant.eventLabourRequestRefresh, "");
+      }
+
+      Get.back();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
   }
+
 }

+ 4 - 257
packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_page.dart

@@ -1,3 +1,4 @@
+import 'package:cpt_uk/modules/job/labour_request_add/widget/lab_request_and_request_review_form.dart';
 import 'package:cs_resources/constants/color_constants.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
@@ -12,6 +13,7 @@ import 'package:plugin_basic/utils/ext_get_nav.dart';
 import 'package:router/path/router_path.dart';
 import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/screen_util.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -21,6 +23,7 @@ import 'package:widgets/no_shadow_scroll_behavior.dart';
 import 'package:widgets/shatter/custom_radio_check.dart';
 import 'package:widgets/shatter/form_require_text.dart';
 import 'package:widgets/shatter/round_my_text_field.dart';
+import 'package:widgets/widget_export.dart';
 
 import 'labour_review_edit_controller.dart';
 import 'labour_review_edit_state.dart';
@@ -87,263 +90,7 @@ class _LabourReviewEditState extends BaseState<UKLabourReviewEditPage, LabourRev
                   child: Column(
                     crossAxisAlignment: CrossAxisAlignment.start,
                     children: [
-                      //工作标题,选择模板
-                      FormRequireText(
-                        text: "Job Title".tr,
-                      ).marginOnly(top: 15),
-
-                      //工作标题
-                      Container(
-                        padding: const EdgeInsets.only(left: 16, right: 10),
-                        margin: const EdgeInsets.only(top: 10),
-                        height: 45,
-                        decoration: BoxDecoration(
-                          color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
-                          borderRadius: const BorderRadius.all(Radius.circular(5)),
-                        ),
-                        child: Row(
-                          mainAxisSize: MainAxisSize.max,
-                          crossAxisAlignment: CrossAxisAlignment.center,
-                          mainAxisAlignment: MainAxisAlignment.start,
-                          children: [
-                            MyTextView(
-                              state.selectedTemplateId == null || state.selectedTemplateId == "0"
-                                  ? ""
-                                  : state.labReqOption!.templateList
-                                          .firstWhere((element) => element.value.toString() == state.selectedTemplateId,
-                                              orElse: () => LabourRequestEditIndexTemplateList())
-                                          .txt ??
-                                      "",
-                              fontSize: 14,
-                              hint: "Choose Job Title".tr,
-                              textHintColor: ColorConstants.textGrayAECAE5,
-                              isFontMedium: true,
-                              textColor: ColorConstants.white,
-                            ).expanded(),
-
-                            //下拉选图标
-                            Visibility(
-                              visible: state.pageType != 2,
-                              child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
-                            ),
-                          ],
-                        ),
-                      ).onTap(() {
-                        FocusScope.of(context).unfocus();
-                        controller.pickJobTitle();
-                      }),
-
-                      //开始时间
-                      FormRequireText(
-                        text: "Start Time".tr,
-                      ).marginOnly(top: 15),
-
-                      //选择时间
-                      Container(
-                        padding: const EdgeInsets.only(left: 16, right: 10),
-                        margin: const EdgeInsets.only(top: 10),
-                        height: 45,
-                        decoration: BoxDecoration(
-                          color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
-                          borderRadius: const BorderRadius.all(Radius.circular(5)),
-                        ),
-                        child: Row(
-                          mainAxisSize: MainAxisSize.max,
-                          crossAxisAlignment: CrossAxisAlignment.center,
-                          mainAxisAlignment: MainAxisAlignment.start,
-                          children: [
-                            MyTextView(
-                              state.selectedStartTime == null ? "" : DateTimeUtils.formatDate(state.selectedStartTime),
-                              fontSize: 14,
-                              hint: "Job Start Time".tr,
-                              textHintColor: ColorConstants.textGrayAECAE5,
-                              isFontMedium: true,
-                              textColor: ColorConstants.white,
-                            ).expanded(),
-                            //下拉选图标
-                            Visibility(
-                              visible: state.pageType != 2,
-                              child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
-                            ),
-                          ],
-                        ),
-                      ).onTap(() {
-                        FocusScope.of(context).unfocus();
-                        controller.pickStartTime();
-                      }),
-
-                      //结束时间
-                      FormRequireText(
-                        text: "End Time".tr,
-                      ).marginOnly(top: 15),
-
-                      //选择时间
-                      Container(
-                        padding: const EdgeInsets.only(left: 16, right: 10),
-                        margin: const EdgeInsets.only(top: 10),
-                        height: 45,
-                        decoration: BoxDecoration(
-                          color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
-                          borderRadius: const BorderRadius.all(Radius.circular(5)),
-                        ),
-                        child: Row(
-                          mainAxisSize: MainAxisSize.max,
-                          crossAxisAlignment: CrossAxisAlignment.center,
-                          mainAxisAlignment: MainAxisAlignment.start,
-                          children: [
-                            MyTextView(
-                              state.selectedEndTime == null ? "" : DateTimeUtils.formatDate(state.selectedEndTime),
-                              fontSize: 14,
-                              hint: "Job End Time".tr,
-                              textHintColor: ColorConstants.textGrayAECAE5,
-                              isFontMedium: true,
-                              textColor: ColorConstants.white,
-                            ).expanded(),
-                            //下拉选图标
-                            Visibility(
-                              visible: state.pageType != 2,
-                              child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
-                            ),
-                          ],
-                        ),
-                      ).onTap(() {
-                        FocusScope.of(context).unfocus();
-                        controller.pickEndTime();
-                      }),
-
-                      //工作选择部门
-                      FormRequireText(
-                        text: "Outlet".tr,
-                      ).marginOnly(top: 15),
-
-                      //选择部门
-                      Container(
-                        padding: const EdgeInsets.only(left: 16, right: 10),
-                        margin: const EdgeInsets.only(top: 10),
-                        height: 45,
-                        decoration: BoxDecoration(
-                          color: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
-                          borderRadius: const BorderRadius.all(Radius.circular(5)),
-                        ),
-                        child: Row(
-                          mainAxisSize: MainAxisSize.max,
-                          crossAxisAlignment: CrossAxisAlignment.center,
-                          mainAxisAlignment: MainAxisAlignment.start,
-                          children: [
-                            MyTextView(
-                              state.selectedDepartmentId == null || state.selectedDepartmentId == "0"
-                                  ? ""
-                                  : state.labReqOption!.departmentList
-                                          .firstWhere((element) => element.value.toString() == state.selectedDepartmentId,
-                                              orElse: () => LabourRequestEditIndexDepartmentList())
-                                          .txt ??
-                                      "",
-                              fontSize: 14,
-                              hint: "Choose Outlet".tr,
-                              textHintColor: ColorConstants.textGrayAECAE5,
-                              isFontMedium: true,
-                              textColor: ColorConstants.white,
-                            ).expanded(),
-                            //下拉选图标
-                            Visibility(
-                              visible: state.pageType != 2,
-                              child: const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
-                            ),
-                          ],
-                        ),
-                      ).onTap(() {
-                        FocusScope.of(context).unfocus();
-                        controller.pickDepartment();
-                      }),
-
-                      //需要的人数
-                      FormRequireText(
-                        text: "No. of Staff".tr,
-                      ).marginOnly(top: 15),
-
-                      //输入框(只允许输入数字)
-                      CustomTextField(
-                        formKey: "no_of_staff",
-                        marginLeft: 0,
-                        marginRight: 0,
-                        paddingTop: 0,
-                        paddingBottom: 0,
-                        height: 45,
-                        fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
-                        enabled: state.pageType != 2,
-                        inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
-                        textInputType: TextInputType.number,
-                        formData: state.formData,
-                        textInputAction: TextInputAction.done,
-                        onSubmit: (key, value) {
-                          FocusScope.of(context).unfocus();
-                        },
-                        marginTop: 10,
-                      ),
-
-                      FormRequireText(
-                        text: "Salary By".tr,
-                      ).marginOnly(top: 15),
-
-                      //选择计费类型
-                      state.labReqOption != null
-                          ? CustomRadioCheck(
-                              options: state.labReqOption!.chargeList.map((e) => e.txt).whereType<String>().toList(), //后台返回的数据展示,并且根据后台的数据匹配索引
-                              selectedPosition: state.labReqOption!.chargeList.indexWhere((element) => element.checked == "checked"),
-                              onOptionSelected: (index, text) {
-                                //修改内存的值
-                                state.chargeOptionId = state.labReqOption!.chargeList[index].value;
-                              },
-                            ).marginOnly(top: 15)
-                          : const CircularProgressIndicator(),
-
-                      //选择是否需要输入金额
-                      Visibility(
-                        visible: state.labReqOption?.serviceType == 1,
-                        child: FormRequireText(
-                          text: "Amount".tr,
-                        ).marginOnly(top: 15),
-                      ),
-
-                      Visibility(
-                        visible: state.labReqOption?.serviceType == 1,
-                        child: CustomTextField(
-                          formKey: "amount",
-                          marginLeft: 0,
-                          marginRight: 0,
-                          paddingTop: 0,
-                          paddingBottom: 0,
-                          height: 45,
-                          fillBackgroundColor: const Color(0xFF4DCFF6).withOpacity(state.pageType == 2 ? 0.5 : 0.2),
-                          enabled: state.pageType != 2,
-                          textInputType: TextInputType.number,
-                          formData: state.formData,
-                          textInputAction: TextInputAction.done,
-                          onSubmit: (key, value) {
-                            FocusScope.of(context).unfocus();
-                          },
-                          marginTop: 10,
-                        ),
-                      ),
-
-                      //提交按钮
-                      Visibility(
-                        visible: state.pageType != 2,
-                        child: MyButton(
-                          type: ClickType.throttle,
-                          milliseconds: 500,
-                          onPressed: () {
-                            FocusScope.of(context).unfocus();
-                            controller.doSubmit();
-                          },
-                          text: "Submit".tr,
-                          textColor: ColorConstants.white,
-                          fontSize: 16,
-                          radius: 22.5,
-                          backgroundColor: hexToColor("#FFBB1B"),
-                          fontWeight: FontWeight.w500,
-                        ).marginSymmetric(horizontal: 0, vertical: 30),
-                      ),
+                      CommonLabourRequestFormFields(controller: controller)
                     ],
                   ).paddingOnly(left: 15, right: 15),
                 ),

+ 93 - 2
packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_state.dart

@@ -1,15 +1,33 @@
+import 'dart:io';
+
+import 'package:cpt_uk/modules/job/labour_request_add/widget/labour_request_interface.dart';
 import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_detail_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_basic/basic_export.dart';
+import 'package:shared/utils/date_time_utils.dart';
+
+class LabourReviewEditState implements CommonLabourRequestState {
+  @override
+  String useInSence = 'labour_request_review';  // labour_request 、 labour_request_review
+
+  @override
+  DateTime? get jobEnd => labReqOption?.jobEnd != null? DateTimeUtils.getDateTime(labReqOption!.jobEnd!): null;
 
-class LabourReviewEditState {
+  @override
+  DateTime? get jobStart => labReqOption?.jobStart !=null? DateTimeUtils.getDateTime(labReqOption!.jobStart!): null;
+
+  @override
+  String? jobSelectJobStart;
+  @override
+  String? jobSelectJobEnd;
 
   int pageType = 2;  //页面的状态 1是编辑  2是详情
   String? requestId;  //编辑和详情需要用到ID
   void Function(dynamic value)? cb;
 
   //页面对应的详情数据
-  LabourRequestEditIndexEntity? labReqOption;
+  UkLabourRequestDetailEntity? labReqOption;
 
   //页面对应的选择的条件
   DateTime? selectedStartTime;
@@ -17,9 +35,33 @@ class LabourReviewEditState {
   String? selectedTemplateId;
   String? selectedDepartmentId;
   String? noStaff;  //成员数量
+  String? amount;
+
+  String? selectedTypeId;
+  String? selectedType;
+
+  String? event;
+  String? eventType;
+  String? eventPax;
+  String? estimatedRevenue;
+  String? position;
+  String? estimatedTotalCost;
+  String? remark; //备注
+  String? attFilePath; // 附件地址
 
   String? chargeOptionId;
 
+  int get serviceType => labReqOption?.serviceType ?? 0;
+  List<UkLabourRequestDetailLocationList>? get locationList => labReqOption?.locationList;
+  List<UkLabourRequestDetailTemplateList>? get templateList => labReqOption?.templateList;
+  List<UkLabourRequestDetailDepartmentList>? get departmentList => labReqOption?.departmentList;
+  List<UkLabourRequestDetailChargeList>? get chargeList => labReqOption?.chargeList;
+  List<UkLabourRequestDetailEmploymentList>? get employmentList => labReqOption?.employmentList;
+
+  DateTime? get selectedDate => selectedStartTime;
+  String? get repeatDateStr => '';
+  String? get preSelectedNames => '';
+
   //表单的校验与数据
   Map<String, Map<String, dynamic>> formData = {
     'no_of_staff': {
@@ -36,6 +78,55 @@ class LabourReviewEditState {
       'hintText': 'Enter Amount'.tr,
       'obsecure': false,
     },
+    'remark': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event_type': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'event_pax': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'revenue': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'position': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'total_cost': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
   };
 
 }

+ 94 - 62
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_controller.dart

@@ -1,13 +1,17 @@
 import 'package:domain/entity/response/labour_request_index_entity.dart';
 import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_review_list_entity.dart';
 import 'package:domain/repository/labour_repository.dart';
+import 'package:domain/repository/uk_labour_repository.dart';
 import 'package:get/get.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
 import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:plugin_platform/http/http_result.dart';
 import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/event_bus.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:shared/utils/util.dart';
 import 'package:widgets/dialog/app_default_dialog.dart';
@@ -21,6 +25,7 @@ import 'labour_review_state.dart';
 
 class LabourReviewController extends GetxController with DioCancelableMixin {
   final LabourRepository _labourRepository = Get.find();
+  final UkLabourRepository _UkLabourRepository = Get.find();
   final LabourReviewState state = LabourReviewState();
 
   var _curPage = 1;
@@ -45,40 +50,40 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
   // Refresh 刷新事件
   Future onRefresh() async {
     _curPage = 1;
-    fetchAppliedStaffList();
+    fetchLabourRequestReViewList();
   }
 
   // Refresh 加载事件
   Future loadMore() async {
     _curPage++;
-    fetchAppliedStaffList();
+    fetchLabourRequestReViewList();
   }
 
   // 重试请求
   Future retryRequest() async {
     _curPage = 1;
     _needShowPlaceholder = true;
-    fetchAppliedStaffList();
+    fetchLabourRequestReViewList();
   }
 
   /// 获取服务器数据,通知消息列表
-  Future fetchAppliedStaffList() async {
+  Future fetchLabourRequestReViewList() async {
     if (_needShowPlaceholder) {
       changeLoadingState(LoadState.State_Loading);
     }
 
     // 并发执行两个请求
     var futures = [
-      _labourRepository.fetchLabourReviewList(
-        state.keyword,
-        DateTimeUtils.formatDate(state.selectedStartDate, format: "yyyy-MM-dd"),
-        DateTimeUtils.formatDate(state.selectedEndDate, format: "yyyy-MM-dd"),
-        state.selectedDepartmentId,
-        curPage: _curPage,
-        cancelToken: cancelToken,
+      _UkLabourRepository.fetchLabourRequestReViewList(
+          keyword: state.keyword,
+          startDate: DateTimeUtils.formatDate(state.selectedStartDate, format: "yyyy-MM-dd"),
+          endDate:DateTimeUtils.formatDate(state.selectedEndDate, format: "yyyy-MM-dd"),
+          departmentId: state.selectedDepartmentId,
+          curPage: _curPage,
+          cancelToken: cancelToken,
       ),
       state.indexOptions == null
-          ? _labourRepository.fetchLabourReviewIndex(
+          ? _labourRepository.fetchLabourRequestIndex(
               cancelToken: cancelToken,
             )
           : Future(() => HttpResult(isSuccess: true).convert(data: state.indexOptions!)),
@@ -86,8 +91,12 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
 
     //拿到结果
     var results = await Future.wait(futures);
-    var listResult = results[0] as HttpResult<LabourReviewListEntity>;
-    var optionResult = results[1] as HttpResult<LabourRequestIndexEntity>;
+    var listResult = results[0] as HttpResult<UkLabourRequestReviewListEntity?>;
+    var optionResult = results[1] as HttpResult<LabourRequestIndexEntity?>;
+
+    // Log.d("state.indexOptions  ${state.indexOptions}");
+
+    // Log.d("optionResult  ${optionResult}");
 
     //选项数据
     if (state.indexOptions == null && optionResult.isSuccess) {
@@ -96,7 +105,9 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
 
     // 处理数据
     if (listResult.isSuccess) {
-      handleList(listResult.data?.rows);
+      List<UkLabourRequestReviewListRows> validList = listResult.data?.rows?.whereType<UkLabourRequestReviewListRows>().toList()?? [];
+
+      handleList(validList);
     } else {
       errorMessage = listResult.errorMsg;
       changeLoadingState(LoadState.State_Error);
@@ -107,7 +118,7 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
   }
 
   // 处理数据与展示的逻辑
-  void handleList(List<LabourReviewListRows>? list) {
+  void handleList(List<UkLabourRequestReviewListRows>? list) {
     if (list != null && list.isNotEmpty) {
       //有数据,判断是刷新还是加载更多的数据
       if (_curPage == 1) {
@@ -140,7 +151,7 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
   @override
   void onReady() {
     super.onReady();
-    fetchAppliedStaffList();
+    fetchLabourRequestReViewList();
   }
 
   @override
@@ -149,6 +160,25 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
     super.onClose();
   }
 
+  // EventBus 的事件接收
+  Subscription? subscribe;
+
+  void registerEventBus() {
+    subscribe = bus.on(AppConstant.eventLabourRequestRefresh, (arg) {
+      var requestId = arg as String;
+      if (Utils.isNotEmpty(requestId)) {
+        // fetchItemByIdAndRefreshItem(requestId);
+        refreshController.callRefresh();
+      } else {
+        refreshController.callRefresh();
+      }
+    });
+  }
+
+  void unregisterEventBus() {
+    bus.off(AppConstant.eventLabourRequestRefresh, subscribe);
+  }
+
   /// 搜索
   void doSearch(String keyword) {
     state.keyword = keyword;
@@ -168,7 +198,7 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
   }
 
   /// Item选中与未选中设置
-  void doSelectedOrNot(LabourReviewListRows data) {
+  void doSelectedOrNot(UkLabourRequestReviewListRows data) {
     data.isSelected = !data.isSelected;
     Log.d("isSelected:${data.isSelected}");
     update();
@@ -177,8 +207,9 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
   /// 执行批量同意
   void _requestBatchApprove(String recordIds) async {
     //执行请求
-    var result = await _labourRepository.approveLabourReviews(
-      recordIds,
+    var result = await _UkLabourRepository.labourRequestReviewBatchSubmit(
+      recordIds: recordIds,
+      type: 'approve', // 审核类型Type【approve|reject】
       cancelToken: cancelToken,
     );
 
@@ -196,9 +227,9 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
   /// 执行批量拒绝
   void _requestBatchReject(String recordIds, String? reason) async {
     //执行请求
-    var result = await _labourRepository.rejectLabourReviews(
-      recordIds,
-      reason,
+    var result = await _UkLabourRepository.labourRequestReviewBatchSubmit(
+      recordIds: recordIds,
+      type: 'reject', // 审核类型Type【approve|reject】
       cancelToken: cancelToken,
     );
 
@@ -260,12 +291,12 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
 
   /// 删除对应的recordId的Item数据
   void _removeItemsByList(String recordIds) {
+    // Log.d("需要移除的recordIds  ${recordIds}");
     // 将逗号分隔的字符串转换为数组
     List<String> recordIdList = recordIds.split(',');
-
     // 移除列表中符合条件的项
-    state.datas.removeWhere((e) => recordIdList.contains(e.recordId));
-
+    state.datas.removeWhere((e) => recordIdList.contains(e.recordId.toString()));
+    // Log.d("移除后的 state.datas   ${state.datas}");
     update();
   }
 
@@ -294,52 +325,53 @@ class LabourReviewController extends GetxController with DioCancelableMixin {
   }
 
   /// 去详情页面
-  void gotoDetailPage(LabourReviewListRows data) {
-    UKLabourReviewEditPage.startInstance(2, data.requestId, null);
+  void gotoDetailPage(UkLabourRequestReviewListRows data) {
+    UKLabourReviewEditPage.startInstance(2, data.requestId!.toString(), null);
   }
 
   /// 去编辑页面
-  void gotoEditPage(LabourReviewListRows data) {
-    UKLabourReviewEditPage.startInstance(1, data.requestId, (result) {
+  void gotoEditPage(UkLabourRequestReviewListRows data) {
+    UKLabourReviewEditPage.startInstance(1, data.requestId!.toString(), (result) {
       if (Utils.isNotEmpty(result)) {
-        fetchItemByIdAndRefreshItem(data.recordId);
+        // fetchItemByIdAndRefreshItem(data.requestId!.toString());
+        refreshController.callRefresh();
       }
     });
   }
 
   /// 去用工审核流程页面
-  void gotoStatusViewPage(LabourReviewListRows data) {
-    UKLabourReviewWorkflowPage.startInstance(data.requestId);
+  void gotoStatusViewPage(UkLabourRequestReviewListRows data) {
+    UKLabourReviewWorkflowPage.startInstance(data.requestId!.toString());
   }
 
   /// 根据ID获取Item对象,用于刷新
-  void fetchItemByIdAndRefreshItem(String? recordId) async {
-    var result = await _labourRepository.fetchItemByRecordId(
-      recordId,
-      cancelToken: cancelToken,
-    );
-
-    //处理数据
-    if (result.isSuccess) {
-      var data = result.data;
-      if (data != null && data.rows.isNotEmpty) {
-        List<LabourReviewListRows> newItem = data.rows;
-
-        // 创建一个 Map 来加速查找
-        Map<String, LabourReviewListRows> newItemMap = {for (var item in newItem) item.recordId ?? "": item};
-
-        // 遍历 state.datas 进行替换
-        for (int i = 0; i < state.datas.length; i++) {
-          if (newItemMap.containsKey(state.datas[i].recordId)) {
-            state.datas[i] = newItemMap[state.datas[i].recordId]!;
-          }
-        }
-
-        //刷新
-        update();
-      }
-    } else {
-      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
-    }
-  }
+  // void fetchItemByIdAndRefreshItem(String? requestId) async {
+  //   var result = await _labourRepository.fetchItemByRecordId(
+  //     requestId,
+  //     cancelToken: cancelToken,
+  //   );
+  //
+  //   //处理数据
+  //   if (result.isSuccess) {
+  //     var data = result.data;
+  //     if (data != null && data.rows.isNotEmpty) {
+  //       List<LabourReviewListRows> newItem = data.rows;
+  //
+  //       // 创建一个 Map 来加速查找
+  //       Map<String, LabourReviewListRows> newItemMap = {for (var item in newItem) item.recordId ?? "": item};
+  //
+  //       // 遍历 state.datas 进行替换
+  //       for (int i = 0; i < state.datas.length; i++) {
+  //         if (newItemMap.containsKey(state.datas[i].recordId)) {
+  //           state.datas[i] = newItemMap[state.datas[i].recordId]!;
+  //         }
+  //       }
+  //
+  //       //刷新
+  //       update();
+  //     }
+  //   } else {
+  //     ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+  //   }
+  // }
 }

+ 107 - 20
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_item.dart

@@ -3,6 +3,7 @@ import 'package:cs_resources/generated/assets.dart';
 import 'package:domain/entity/response/job_list_applied_info_entity.dart';
 import 'package:domain/entity/response/job_list_applied_staff_list_entity.dart';
 import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_review_list_entity.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
@@ -18,7 +19,7 @@ import 'package:widgets/my_text_view.dart';
  */
 class LabourReviewItem extends StatelessWidget {
   final int index;
-  final LabourReviewListRows item;
+  final UkLabourRequestReviewListRows item;
   final VoidCallback? onStatusAction;
   final VoidCallback? onEditAction;
   final VoidCallback? onDetailAction;
@@ -76,13 +77,13 @@ class LabourReviewItem extends StatelessWidget {
             ],
           ),
 
-          // 部门
+          // Event Name
           Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Outlet:".tr,
+                "${'Event Name'.tr}:",
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
@@ -90,7 +91,7 @@ class LabourReviewItem extends StatelessWidget {
 
               //部门
               MyTextView(
-                item.departmentName ?? "-",
+                item.eventName ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
                 textColor: Colors.white,
@@ -99,21 +100,21 @@ class LabourReviewItem extends StatelessWidget {
             ],
           ).marginOnly(top: 15),
 
-          // 工作日期时间
+          // 部门
           Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Datetime:".tr,
+                "Outlet:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
               ),
 
-              //日期时间
+              //部门
               MyTextView(
-                item.jobTime ?? "-",
+                item.departmentName ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
                 textColor: Colors.white,
@@ -122,21 +123,21 @@ class LabourReviewItem extends StatelessWidget {
             ],
           ).marginOnly(top: 15),
 
-          // 人数
+          // 工作日期时间
           Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "No. of Staff:".tr,
+                "DateTime:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
               ),
 
-              //人数
+              //日期时间
               MyTextView(
-                item.needNum.toString(),
+                "${item.jobDate} ${item.jobTime}"?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
                 textColor: Colors.white,
@@ -145,13 +146,100 @@ class LabourReviewItem extends StatelessWidget {
             ],
           ).marginOnly(top: 15),
 
-          // 薪水
+          // 人数  薪水
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              Expanded(
+                flex: 1,
+                child: Row(
+                  children: [
+                    MyTextView(
+                      "No. of Staff:".tr,
+                      isFontRegular: true,
+                      textColor: ColorConstants.textGrayAECAE5,
+                      fontSize: 14,
+                    ),
+
+                    //人数
+                    MyTextView(
+                      item.needNum.toString(),
+                      marginLeft: 5,
+                      isFontRegular: true,
+                      textColor: Colors.white,
+                      fontSize: 14,
+                    ),
+                  ],
+                ),
+              ),
+              // 薪水
+              Expanded(
+                flex: 1,
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    MyTextView(
+                      "${"Salary".tr}:",
+                      isFontRegular: true,
+                      textColor: ColorConstants.textGrayAECAE5,
+                      fontSize: 14,
+                    ),
+
+                    //发布状态
+                    MyTextView(
+                      item.salary ?? "-",
+                      marginLeft: 5,
+                      isFontRegular: true,
+                      textColor: Colors.redAccent,
+                      fontSize: 14,
+                    ).expanded(),
+                  ],
+                ),
+              ),
+            ],
+          ).marginOnly(top: 15),
+
+
+
+          // Est Amount job Hours
           Row(
             mainAxisSize: MainAxisSize.max,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
+              // Est Amount
+              Expanded(
+                flex: 1,
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    MyTextView(
+                      "${"Est Amount(£)".tr}:",
+                      isFontRegular: true,
+                      textColor: ColorConstants.textGrayAECAE5,
+                      fontSize: 14,
+                    ),
+
+                    MyTextView(
+                      item.estAmount ?? "-",
+                      marginLeft: 5,
+                      isFontRegular: true,
+                      textColor: Colors.teal,
+                      fontSize: 14,
+                    ).expanded(),
+                  ],
+                ),
+              )
+            ],
+          ).marginOnly(top: 15),
+
+          // Job Hours
+          Row(
+            children: [
               MyTextView(
-                "${"Salary".tr}:",
+                "${"Job Hours".tr}:",
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
@@ -159,7 +247,7 @@ class LabourReviewItem extends StatelessWidget {
 
               //发布状态
               MyTextView(
-                item.salaryShow ?? "-",
+                item.jobHours ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
                 textColor: Colors.white,
@@ -209,7 +297,6 @@ class LabourReviewItem extends StatelessWidget {
                 fontSize: 14,
               ),
 
-              //发布状态
               MyTextView(
                 item.createdAt ?? "-",
                 marginLeft: 5,
@@ -222,7 +309,7 @@ class LabourReviewItem extends StatelessWidget {
 
           //按钮组
           Visibility(
-            visible: item.btnList?.isNotEmpty ?? false,
+            visible: true,
             child: Row(
               mainAxisSize: MainAxisSize.max,
               mainAxisAlignment: MainAxisAlignment.end,
@@ -230,7 +317,7 @@ class LabourReviewItem extends StatelessWidget {
               children: [
                 //详情按钮
                 Visibility(
-                  visible: item.btnList?.contains("detail") ?? false,
+                  visible: false,
                   child: MyButton(
                     onPressed: () {
                       FocusScope.of(context).unfocus();
@@ -249,7 +336,7 @@ class LabourReviewItem extends StatelessWidget {
 
                 //Edit按钮
                 Visibility(
-                  visible: item.btnList.contains("edit") ?? false,
+                  visible: true,
                   child: MyButton(
                     onPressed: () {
                       FocusScope.of(context).unfocus();
@@ -266,7 +353,7 @@ class LabourReviewItem extends StatelessWidget {
 
                 //状态工作流按钮
                 Visibility(
-                  visible: item.btnList.contains("status") ?? false,
+                  visible: true,
                   child: MyButton(
                     onPressed: () {
                       FocusScope.of(context).unfocus();

+ 2 - 1
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_state.dart

@@ -1,5 +1,6 @@
 import 'package:domain/entity/response/labour_request_index_entity.dart';
 import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:domain/entity/response/uk_labour_request_review_list_entity.dart';
 import 'package:flutter/material.dart';
 
 class LabourReviewState {
@@ -11,6 +12,6 @@ class LabourReviewState {
   String? selectedDepartmentId;
 
   //页面的列表数据
-  List<LabourReviewListRows> datas = [];
+  List<UkLabourRequestReviewListRows> datas = [];
   LabourRequestIndexEntity? indexOptions;
 }

+ 32 - 4
packages/cpt_uk/lib/router/uk_router.dart

@@ -13,7 +13,6 @@ import 'package:cpt_uk/modules/job/labour_request_workflow/labour_request_workfl
 import 'package:cpt_uk/modules/job/template_add/template_add_page.dart';
 import 'package:cpt_uk/modules/job/template_list/template_list_page.dart';
 import 'package:cpt_uk/modules/main/main_page.dart';
-import 'package:cpt_uk/modules/report/casual_payout_report/casual_payout_report_page.dart';
 import 'package:cpt_uk/modules/report/casual_report/casual_report_page.dart';
 import 'package:cpt_uk/modules/report/finance_report/report_finance_page.dart';
 import 'package:cpt_uk/modules/report/labour_report/labour_report_page.dart';
@@ -25,7 +24,12 @@ import 'package:router/path/router_path.dart';
 
 import '../modules/job/job_applied/job_applied_page.dart';
 import '../modules/job/job_applied_edit/job_applied_edit_page.dart';
+import '../modules/job/job_applied_revise_list/job_applied_revise_list_page.dart';
+import '../modules/job/labour_request_preselected_list/labour_request_preselected_list_page.dart';
+import '../modules/job/revise_add_edit/revise_add_edit_page.dart';
+import '../modules/job/revise_log/revise_log_page.dart';
 import '../modules/report/attendance_report/attendance_report_page.dart';
+import '../modules/report/casual_payout_report/casual_payout_report_page.dart';
 import '../modules/review/attendance_review_list/attendance_review_page.dart';
 import '../modules/review/labour_review_edit/labour_review_edit_page.dart';
 import '../modules/review/labour_review_list/labour_review_page.dart';
@@ -70,6 +74,12 @@ class UKPageRouter {
       page: () => UKLabourRequestAddPage(),
     ),
 
+    //工作用工请求的preselect列表
+    GetPage(
+      name: RouterPath.UKLabourPreselectedList,
+      page: () => UKLabourRequestPreselectedListPage(),
+    ),
+
     //工作用工请求的操作流
     GetPage(
       name: RouterPath.UKLabourWorlkflow,
@@ -118,7 +128,7 @@ class UKPageRouter {
       page: () => UKAppliedWorkflowPage(),
     ),
 
-    //工作列表用工请求审核
+    //工作列表用工请求审核列表
     GetPage(
       name: RouterPath.UKLabourReviewList,
       page: () => UKLabourReviewPage(),
@@ -136,6 +146,24 @@ class UKPageRouter {
       page: () => UKLabourReviewWorkflowPage(),
     ),
 
+    //Revise
+    GetPage(
+      name: RouterPath.UKJobAppliedReviseList,
+      page: () => UKJobAppliedRevisePage(),
+    ),
+
+    //Revise addAndEdit
+    GetPage(
+      name: RouterPath.UKJobAppliedReviseAddEdit,
+      page: () => UKReviseAddEditPage(),
+    ),
+
+    //Revise log 页面
+    GetPage(
+      name: RouterPath.UKJobAppliedReviseLog,
+      page: () => UKReviseLogPage(),
+    ),
+
     //考勤的审核列表
     GetPage(
       name: RouterPath.UKAttendanceReviewList,
@@ -196,13 +224,13 @@ class UKPageRouter {
       page: () => UKAttendanceReportPage(),
     ),
 
-    //报表 - 临时工作付款统计
+    //报表 - 临时工月度报表 payout报表
     GetPage(
       name: RouterPath.UKReportCasualPayout,
       page: () => UKCasualPayoutReportPage(),
     ),
 
-    //报表 - 临时工月度报表
+    //报表 - 临时工作付款统计
     GetPage(
       name: RouterPath.UKReportCasualMonthly,
       page: () => UKCasualReportPage(),

+ 66 - 0
packages/cs_domain/lib/constants/api_constants.dart

@@ -287,6 +287,64 @@ class ApiConstants {
   static const apiReviseLogListSG = "/index.php/api/v1/hotel/revise/logs";
 
   // =========================== 英国特有的一些接口 ↓=========================================
+  // 添加工作模板 获取 工作模板 和 证书列表 和 交通工具 选项
+  static const apiJobTemplateAddIndexUK = "/index.php/api/v1/hotel/temp/add-view";
+  // 获取工作模板详情
+  static const apiJobTemplateDetailUK = "/index.php/api/v1/hotel/temp/edit-view";
+  // 工作详情中 根据所选模板 获取 工作标题
+  static const apiJobTemplateTitleOptionsUK = "/index.php/api/v1/hotel/temp/show-template-title";
+  // 选择工作标题后 获取该标题对应的模板数据
+  static const apiJobTemplateDetailBySelectTitleUK = "/index.php/api/v1/hotel/temp/show-template-record";
+  // labourrequest 快速复制工作
+  static const apiLabourRequestQuickCopyUK = "/index.php/api/v1/hotel/lab-req/quick-copy";
+  // 预选人列表
+  static const apiLabourRequestPreSelectListUK = "/index.php/api/v1/hotel/prestaff/table";
+  // 筛选的条件
+  static const apiLabourRequestPreSelectIndexUK = "/index.php/api/v1/hotel/prestaff/index";
+  // 预选人 -添加员工的列表
+  static const apiLabourRequestPreSelectAddStaffListUK = "/index.php/api/v1/hotel/prestaff/staff-view";
+  // 预选人 - 批量添加员工
+  static const apiLabourRequestPreSelectAddBatchUK = "/index.php/api/v1/hotel/prestaff/staff-submit";
+  // 预选人-删除员工
+  static const apiLabourRequestPreSelectDeleteUK = "/index.php/api/v1/hotel/prestaff/delete";
+
+  // labourequest-review 列表
+  static const apiLabourRequestReViewListUK = "/index.php/api/v1/hotel/lab-req/review";
+  // labourequest-review workflow的审核详情
+  static const apiLabourRequestReViewWorkFlowDetailUK = "/index.php/api/v1/hotel/lab-req/review-workflow";
+  // labourrequest-review 编辑提交
+  static const apiLabourRequestReViewEditUK = "/index.php/api/v1/hotel/lab-req/review-submit";
+  // labourrequest-review 批量审核(确认和拒绝)提交
+  static const apiLabourRequestReViewBatchSubmitUK = "/index.php/api/v1/hotel/lab-req/review-batch";
+  // applied - 设置小费
+  static const apiAppliedStaffBatchSetTipUK = "/index.php/api/v1/hotel/applied/batch-tips";
+  // revise - 列表
+  static const apiAppliedStaffReviseListUK = "/index.php/api/v1/hotel/revise/table";
+  // revise - add 时的 详情页面
+  static const apiAppliedStaffReviseAddUK = "/index.php/api/v1/hotel/revise/add-view";
+  // revise - edit 时的 详情页面
+  static const apiAppliedStaffReviseEditUK = "/index.php/api/v1/hotel/revise/edit-view";
+  // revise 添加 提交
+  static const apiAppliedStaffReviseAddSubmitUK = "/index.php/api/v1/hotel/revise/add-submit";
+  // revise 编辑 提交
+  static const apiAppliedStaffReviseEditSubmitUK = "/index.php/api/v1/hotel/revise/edit-submit";
+  // revise recall
+  static const apiAppliedStaffReviseRecallUK = "/index.php/api/v1/hotel/revise/recall";
+  // revise delete
+  static const apiAppliedStaffReviseDeleteUK = "/index.php/api/v1/hotel/revise/delete";
+  // revise logs
+  static const apiAppliedStaffReviseLogsUK = "/index.php/api/v1/hotel/revise/logs";
+  // staff - detail
+  static const apiStaffDetailUK = "/index.php/api/v1/hotel/member/detail-new";
+  // staff - labour history
+  static const apiStaffLabourHistoryUK = "/index.php/api/v1/hotel/member/history";
+  // attentanceReview 列表
+  static const apiAttendanceReviewTableUK = "/index.php/api/v1/hotel/applied/attn-review";
+  // attentanceReview 批量审核/批量拒绝
+  static const apiAttendanceReviewBatchSubmitUK = "/index.php/api/v1/hotel/applied/attn-batch";
+  // attentanceReview 获取批注
+  static const apiAttendanceReviewRemarksUK = "/index.php/api/v1/hotel/applied/attn-remarks";
+
 
   //门卫的考勤选项
   static const apiSecurityAttendanceOptionUK = "/index.php/api/v1/hotel/security/index";
@@ -309,6 +367,9 @@ class ApiConstants {
   //UK的用工报表
   static const apiReportLabourUK = "/index.php/api/v1/hotel/report/labour-request";
 
+  //UK的outlet报表
+  static const apiReportOutletUK = "/index.php/api/v1/hotel/report/outlet";
+
   //UK的电子考勤报表
   static const apiReportAttendanceUK = "/index.php/api/v1/hotel/report/attendance";
 
@@ -318,6 +379,11 @@ class ApiConstants {
   //UK的工作时长报表
   static const apiReportWorkingHoursUK = "/index.php/api/v1/hotel/report/working-hours";
 
+  // UK casual-report报表
+  static const apiReportCasualUK = "/index.php/api/v1/hotel/report/casual-report";
+  //UK casual-payout 报表
+  static const apiReportCasualPayoutUK = "/index.php/api/v1/hotel/report/casual-payout";
+
   // =========================== 报表与其他 ↓=========================================
 
   // 设备列表

+ 0 - 64
packages/cs_domain/lib/entity/response/u_k_template_detail_entity.dart

@@ -1,64 +0,0 @@
-import 'package:domain/entity/response/index_option_entity.dart';
-import 'package:domain/generated/json/base/json_field.dart';
-import 'package:domain/generated/json/u_k_template_detail_entity.g.dart';
-import 'dart:convert';
-export 'package:domain/generated/json/u_k_template_detail_entity.g.dart';
-
-@JsonSerializable()
-class UKTemplateDetailEntity {
-  UKTemplateDetailRow? row;
-  @JSONField(name: "certificate_list")
-  List<IndexOptionEntity>? certificateList = [];
-  @JSONField(name: "vehicle_list")
-  List<IndexOptionEntity>? vehicleList = [];
-
-  UKTemplateDetailEntity();
-
-  factory UKTemplateDetailEntity.fromJson(Map<String, dynamic> json) => $UKTemplateDetailEntityFromJson(json);
-
-  Map<String, dynamic> toJson() => $UKTemplateDetailEntityToJson(this);
-
-  @override
-  String toString() {
-    return jsonEncode(this);
-  }
-}
-
-@JsonSerializable()
-class UKTemplateDetailRow {
-  String? id;
-  @JSONField(name: "company_id")
-  String? companyId;
-  @JSONField(name: "job_title")
-  String? jobTitle;
-  @JSONField(name: "contact_name")
-  String? contactName;
-  @JSONField(name: "contact_no")
-  String? contactNo;
-  String? vehicle;
-  String? certificate;
-  String? age;
-  String? language;
-  int gender = 0;
-  String? description;
-  String? note;
-  @JSONField(name: "operator_id")
-  String? operatorId;
-  @JSONField(name: "created_at")
-  String? createdAt;
-  @JSONField(name: "updated_at")
-  String? updatedAt;
-  @JSONField(name: "deleted_at")
-  String? deletedAt;
-
-  UKTemplateDetailRow();
-
-  factory UKTemplateDetailRow.fromJson(Map<String, dynamic> json) => $UKTemplateDetailRowFromJson(json);
-
-  Map<String, dynamic> toJson() => $UKTemplateDetailRowToJson(this);
-
-  @override
-  String toString() {
-    return jsonEncode(this);
-  }
-}

+ 4 - 0
packages/cs_domain/lib/entity/response/u_k_template_entity.dart

@@ -27,6 +27,10 @@ class UKTemplateRows {
 	String? jobTitle;
 	String? vehicle;
 	String? certificate;
+	@JSONField(name: "contact_name")
+	String? contactName;
+	@JSONField(name: "contact_no")
+	String? contactNo;
 	@JSONField(name: "created_by")
 	String? createdBy;
 	@JSONField(name: "created_at")

+ 72 - 0
packages/cs_domain/lib/entity/response/uk_attendance_review_entity.dart

@@ -0,0 +1,72 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_attendance_review_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_attendance_review_entity.g.dart';
+
+@JsonSerializable()
+class UkAttendanceReviewEntity {
+	int? total;
+	List<UkAttendanceReviewRows>? rows;
+
+	UkAttendanceReviewEntity();
+
+	factory UkAttendanceReviewEntity.fromJson(Map<String, dynamic> json) => $UkAttendanceReviewEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkAttendanceReviewEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkAttendanceReviewRows {
+	@JSONField(name: "record_id")
+	int? recordId;
+	@JSONField(name: "order_id")
+	int? orderId;
+	@JSONField(name: "applied_id")
+	int? appliedId;
+	@JSONField(name: "staff_name")
+	String? staffName;
+	@JSONField(name: "job_title")
+	String? jobTitle;
+	@JSONField(name: "department_name")
+	String? departmentName;
+	@JSONField(name: "job_time")
+	String? jobTime;
+	@JSONField(name: "status_show")
+	String? statusShow;
+	@JSONField(name: "adjust_show")
+	String? adjustShow;
+	@JSONField(name: "total_show")
+	String? totalShow;
+	@JSONField(name: "clock_in")
+	String? clockIn;
+	@JSONField(name: "in_class")
+	int? inClass;
+	@JSONField(name: "clock_out")
+	String? clockOut;
+	@JSONField(name: "out_class")
+	int? outClass;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "has_reason")
+	int? hasReason;
+	@JSONField(name: "action_list")
+	List<String>? actionList;
+
+	bool isSelected = false;
+
+	UkAttendanceReviewRows();
+
+	factory UkAttendanceReviewRows.fromJson(Map<String, dynamic> json) => $UkAttendanceReviewRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkAttendanceReviewRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 25 - 0
packages/cs_domain/lib/entity/response/uk_attendance_review_remark_entity.dart

@@ -0,0 +1,25 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_attendance_review_remark_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_attendance_review_remark_entity.g.dart';
+
+@JsonSerializable()
+class UkAttendanceReviewRemarkEntity {
+	@JSONField(name: "applied_id")
+	int? appliedId;
+	@JSONField(name: "member_name")
+	String? memberName;
+	String? disabled;
+	String? remark;
+
+	UkAttendanceReviewRemarkEntity();
+
+	factory UkAttendanceReviewRemarkEntity.fromJson(Map<String, dynamic> json) => $UkAttendanceReviewRemarkEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkAttendanceReviewRemarkEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 176 - 0
packages/cs_domain/lib/entity/response/uk_job_applied_revise_add_detail_entity.dart

@@ -0,0 +1,176 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_job_applied_revise_add_detail_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_job_applied_revise_add_detail_entity.g.dart';
+
+@JsonSerializable()
+class UkJobAppliedReviseAddDetailEntity {
+	UkJobAppliedReviseAddDetailApplied? applied;
+	@JSONField(name: "start_time")
+	String? startTime;
+	@JSONField(name: "end_time")
+	String? endTime;
+	@JSONField(name: "security_in")
+	String? securityIn;
+	@JSONField(name: "security_out")
+	String? securityOut;
+	@JSONField(name: "work_in")
+	String? workIn;
+	@JSONField(name: "work_out")
+	String? workOut;
+	@JSONField(name: "adjust_hours")
+	int? adjustHours;
+	String? view;
+
+	UkJobAppliedReviseAddDetailEntity();
+
+	factory UkJobAppliedReviseAddDetailEntity.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseAddDetailEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseAddDetailEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseAddDetailApplied {
+	@JSONField(name: "s_id")
+	int? sId;
+	@JSONField(name: "member_id")
+	int? memberId;
+	@JSONField(name: "member_name")
+	String? memberName;
+	@JSONField(name: "job_id")
+	int? jobId;
+	@JSONField(name: "is_assigned")
+	int? isAssigned;
+	@JSONField(name: "cancel_status")
+	int? cancelStatus;
+	@JSONField(name: "cancel_reason")
+	String? cancelReason;
+	@JSONField(name: "cancel_image")
+	String? cancelImage;
+	@JSONField(name: "cancel_time")
+	int? cancelTime;
+	@JSONField(name: "checkin_time")
+	int? checkinTime;
+	@JSONField(name: "adjusted_checkin_time")
+	int? adjustedCheckinTime;
+	@JSONField(name: "checkin_signature")
+	String? checkinSignature;
+	@JSONField(name: "checkin_address")
+	String? checkinAddress;
+	@JSONField(name: "checkout_time")
+	int? checkoutTime;
+	@JSONField(name: "adjusted_checkout_time")
+	int? adjustedCheckoutTime;
+	@JSONField(name: "checkout_signature")
+	String? checkoutSignature;
+	@JSONField(name: "checkout_address")
+	String? checkoutAddress;
+	@JSONField(name: "work_hours")
+	int? workHours;
+	@JSONField(name: "adjusted_work_minutes")
+	String? adjustedWorkMinutes;
+	@JSONField(name: "extra_work_minutes")
+	String? extraWorkMinutes;
+	@JSONField(name: "adjusted_hourly_rate")
+	int? adjustedHourlyRate;
+	@JSONField(name: "employer_rate")
+	int? employerRate;
+	@JSONField(name: "job_salary")
+	int? jobSalary;
+	@JSONField(name: "job_rating")
+	int? jobRating;
+	String? reviews;
+	@JSONField(name: "process_date")
+	int? processDate;
+	@JSONField(name: "payment_methods")
+	String? paymentMethods;
+	@JSONField(name: "add_time")
+	int? addTime;
+	@JSONField(name: "update_time")
+	int? updateTime;
+	@JSONField(name: "member_current_lat")
+	String? memberCurrentLat;
+	@JSONField(name: "member_current_long")
+	String? memberCurrentLong;
+	int? deduction;
+	String? cpf;
+	@JSONField(name: "cpf_deduction")
+	int? cpfDeduction;
+	String? remark;
+	@JSONField(name: "employer_remark")
+	String? employerRemark;
+	String? processor;
+	@JSONField(name: "work_status")
+	int? workStatus;
+	@JSONField(name: "work_status_source")
+	int? workStatusSource;
+	@JSONField(name: "check_status")
+	int? checkStatus;
+	@JSONField(name: "is_send")
+	int? isSend;
+	@JSONField(name: "is_late")
+	int? isLate;
+	@JSONField(name: "parent_id")
+	int? parentId;
+	@JSONField(name: "revise_version")
+	int? reviseVersion;
+	int? source;
+	@JSONField(name: "no_show_remark")
+	dynamic noShowRemark;
+	@JSONField(name: "is_prompt")
+	int? isPrompt;
+	@JSONField(name: "reject_time")
+	int? rejectTime;
+	@JSONField(name: "reject_remark")
+	String? rejectRemark;
+	int? urgent;
+	@JSONField(name: "checkin_temperature")
+	int? checkinTemperature;
+	@JSONField(name: "checkout_temperature")
+	int? checkoutTemperature;
+	@JSONField(name: "security_clock_in")
+	int? securityClockIn;
+	@JSONField(name: "security_clock_out")
+	int? securityClockOut;
+	@JSONField(name: "work_clock_in")
+	int? workClockIn;
+	@JSONField(name: "work_clock_out")
+	int? workClockOut;
+	@JSONField(name: "hotel_applied_id")
+	int? hotelAppliedId;
+	@JSONField(name: "break_hours")
+	int? breakHours;
+	@JSONField(name: "is_cash_pay")
+	int? isCashPay;
+	@JSONField(name: "applied_id")
+	int? appliedId;
+	@JSONField(name: "security_in_time")
+	int? securityInTime;
+	@JSONField(name: "security_out_time")
+	int? securityOutTime;
+	@JSONField(name: "co_confirmed")
+	int? coConfirmed;
+	@JSONField(name: "co_reason")
+	String? coReason;
+	@JSONField(name: "co_reason_type")
+	int? coReasonType;
+	@JSONField(name: "agency_rate")
+	String? agencyRate;
+	String? gratuity;
+
+	UkJobAppliedReviseAddDetailApplied();
+
+	factory UkJobAppliedReviseAddDetailApplied.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseAddDetailAppliedFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseAddDetailAppliedToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 362 - 0
packages/cs_domain/lib/entity/response/uk_job_applied_revise_edit_detail_entity.dart

@@ -0,0 +1,362 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_job_applied_revise_edit_detail_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_job_applied_revise_edit_detail_entity.g.dart';
+
+@JsonSerializable()
+class UkJobAppliedReviseEditDetailEntity {
+	UkJobAppliedReviseEditDetailApplied? applied;
+	@JSONField(name: "start_time")
+	String? startTime;
+	@JSONField(name: "end_time")
+	String? endTime;
+	@JSONField(name: "security_in")
+	String? securityIn;
+	@JSONField(name: "security_out")
+	String? securityOut;
+	@JSONField(name: "work_in")
+	String? workIn;
+	@JSONField(name: "work_out")
+	String? workOut;
+	@JSONField(name: "adjust_hours")
+	int? adjustHours;
+	UkJobAppliedReviseEditDetailRevise? revise;
+	String? view;
+
+	UkJobAppliedReviseEditDetailEntity();
+
+	factory UkJobAppliedReviseEditDetailEntity.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseEditDetailEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseEditDetailEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseEditDetailApplied {
+	@JSONField(name: "s_id")
+	int? sId;
+	@JSONField(name: "member_id")
+	int? memberId;
+	@JSONField(name: "member_name")
+	String? memberName;
+	@JSONField(name: "job_id")
+	int? jobId;
+	@JSONField(name: "is_assigned")
+	int? isAssigned;
+	@JSONField(name: "cancel_status")
+	int? cancelStatus;
+	@JSONField(name: "cancel_reason")
+	String? cancelReason;
+	@JSONField(name: "cancel_image")
+	String? cancelImage;
+	@JSONField(name: "cancel_time")
+	int? cancelTime;
+	@JSONField(name: "checkin_time")
+	int? checkinTime;
+	@JSONField(name: "adjusted_checkin_time")
+	int? adjustedCheckinTime;
+	@JSONField(name: "checkin_signature")
+	String? checkinSignature;
+	@JSONField(name: "checkin_address")
+	String? checkinAddress;
+	@JSONField(name: "checkout_time")
+	int? checkoutTime;
+	@JSONField(name: "adjusted_checkout_time")
+	int? adjustedCheckoutTime;
+	@JSONField(name: "checkout_signature")
+	String? checkoutSignature;
+	@JSONField(name: "checkout_address")
+	String? checkoutAddress;
+	@JSONField(name: "work_hours")
+	int? workHours;
+	@JSONField(name: "adjusted_work_minutes")
+	String? adjustedWorkMinutes;
+	@JSONField(name: "extra_work_minutes")
+	String? extraWorkMinutes;
+	@JSONField(name: "adjusted_hourly_rate")
+	int? adjustedHourlyRate;
+	@JSONField(name: "employer_rate")
+	int? employerRate;
+	@JSONField(name: "job_salary")
+	int? jobSalary;
+	@JSONField(name: "job_rating")
+	int? jobRating;
+	String? reviews;
+	@JSONField(name: "process_date")
+	int? processDate;
+	@JSONField(name: "payment_methods")
+	String? paymentMethods;
+	@JSONField(name: "add_time")
+	int? addTime;
+	@JSONField(name: "update_time")
+	int? updateTime;
+	@JSONField(name: "member_current_lat")
+	String? memberCurrentLat;
+	@JSONField(name: "member_current_long")
+	String? memberCurrentLong;
+	int? deduction;
+	String? cpf;
+	@JSONField(name: "cpf_deduction")
+	int? cpfDeduction;
+	String? remark;
+	@JSONField(name: "employer_remark")
+	String? employerRemark;
+	String? processor;
+	@JSONField(name: "work_status")
+	int? workStatus;
+	@JSONField(name: "work_status_source")
+	int? workStatusSource;
+	@JSONField(name: "check_status")
+	int? checkStatus;
+	@JSONField(name: "is_send")
+	int? isSend;
+	@JSONField(name: "is_late")
+	int? isLate;
+	@JSONField(name: "parent_id")
+	int? parentId;
+	@JSONField(name: "revise_version")
+	int? reviseVersion;
+	int? source;
+	@JSONField(name: "no_show_remark")
+	dynamic noShowRemark;
+	@JSONField(name: "is_prompt")
+	int? isPrompt;
+	@JSONField(name: "reject_time")
+	int? rejectTime;
+	@JSONField(name: "reject_remark")
+	String? rejectRemark;
+	int? urgent;
+	@JSONField(name: "checkin_temperature")
+	int? checkinTemperature;
+	@JSONField(name: "checkout_temperature")
+	int? checkoutTemperature;
+	@JSONField(name: "security_clock_in")
+	int? securityClockIn;
+	@JSONField(name: "security_clock_out")
+	int? securityClockOut;
+	@JSONField(name: "work_clock_in")
+	int? workClockIn;
+	@JSONField(name: "work_clock_out")
+	int? workClockOut;
+	@JSONField(name: "hotel_applied_id")
+	int? hotelAppliedId;
+	@JSONField(name: "break_hours")
+	int? breakHours;
+	@JSONField(name: "is_cash_pay")
+	int? isCashPay;
+	@JSONField(name: "applied_id")
+	int? appliedId;
+	@JSONField(name: "security_in_time")
+	int? securityInTime;
+	@JSONField(name: "security_out_time")
+	int? securityOutTime;
+	@JSONField(name: "co_confirmed")
+	int? coConfirmed;
+	@JSONField(name: "co_reason")
+	String? coReason;
+	@JSONField(name: "co_reason_type")
+	int? coReasonType;
+	@JSONField(name: "agency_rate")
+	String? agencyRate;
+	String? gratuity;
+
+	UkJobAppliedReviseEditDetailApplied();
+
+	factory UkJobAppliedReviseEditDetailApplied.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseEditDetailAppliedFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseEditDetailAppliedToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseEditDetailRevise {
+	int? id;
+	@JSONField(name: "company_id")
+	int? companyId;
+	@JSONField(name: "s_id")
+	int? sId;
+	@JSONField(name: "member_id")
+	int? memberId;
+	@JSONField(name: "job_id")
+	int? jobId;
+	@JSONField(name: "employer_admin_id")
+	int? employerAdminId;
+	@JSONField(name: "revise_hours")
+	String? reviseHours;
+	@JSONField(name: "revise_minute")
+	String? reviseMinute;
+	String? salary;
+	@JSONField(name: "tax_deduction")
+	String? taxDeduction;
+	String? reason;
+	int? status;
+	@JSONField(name: "reject_remark")
+	String? rejectRemark;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "updated_at")
+	String? updatedAt;
+	@JSONField(name: "deleted_at")
+	dynamic deletedAt;
+	UkJobAppliedReviseEditDetailReviseApplied? applied;
+
+	UkJobAppliedReviseEditDetailRevise();
+
+	factory UkJobAppliedReviseEditDetailRevise.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseEditDetailReviseFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseEditDetailReviseToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseEditDetailReviseApplied {
+	@JSONField(name: "s_id")
+	int? sId;
+	@JSONField(name: "member_id")
+	int? memberId;
+	@JSONField(name: "member_name")
+	String? memberName;
+	@JSONField(name: "job_id")
+	int? jobId;
+	@JSONField(name: "is_assigned")
+	int? isAssigned;
+	@JSONField(name: "cancel_status")
+	int? cancelStatus;
+	@JSONField(name: "cancel_reason")
+	String? cancelReason;
+	@JSONField(name: "cancel_image")
+	String? cancelImage;
+	@JSONField(name: "cancel_time")
+	int? cancelTime;
+	@JSONField(name: "checkin_time")
+	int? checkinTime;
+	@JSONField(name: "adjusted_checkin_time")
+	int? adjustedCheckinTime;
+	@JSONField(name: "checkin_signature")
+	String? checkinSignature;
+	@JSONField(name: "checkin_address")
+	String? checkinAddress;
+	@JSONField(name: "checkout_time")
+	int? checkoutTime;
+	@JSONField(name: "adjusted_checkout_time")
+	int? adjustedCheckoutTime;
+	@JSONField(name: "checkout_signature")
+	String? checkoutSignature;
+	@JSONField(name: "checkout_address")
+	String? checkoutAddress;
+	@JSONField(name: "work_hours")
+	int? workHours;
+	@JSONField(name: "adjusted_work_minutes")
+	String? adjustedWorkMinutes;
+	@JSONField(name: "extra_work_minutes")
+	String? extraWorkMinutes;
+	@JSONField(name: "adjusted_hourly_rate")
+	int? adjustedHourlyRate;
+	@JSONField(name: "employer_rate")
+	int? employerRate;
+	@JSONField(name: "job_salary")
+	int? jobSalary;
+	@JSONField(name: "job_rating")
+	int? jobRating;
+	String? reviews;
+	@JSONField(name: "process_date")
+	int? processDate;
+	@JSONField(name: "payment_methods")
+	String? paymentMethods;
+	@JSONField(name: "add_time")
+	int? addTime;
+	@JSONField(name: "update_time")
+	int? updateTime;
+	@JSONField(name: "member_current_lat")
+	String? memberCurrentLat;
+	@JSONField(name: "member_current_long")
+	String? memberCurrentLong;
+	int? deduction;
+	String? cpf;
+	@JSONField(name: "cpf_deduction")
+	int? cpfDeduction;
+	String? remark;
+	@JSONField(name: "employer_remark")
+	String? employerRemark;
+	String? processor;
+	@JSONField(name: "work_status")
+	int? workStatus;
+	@JSONField(name: "work_status_source")
+	int? workStatusSource;
+	@JSONField(name: "check_status")
+	int? checkStatus;
+	@JSONField(name: "is_send")
+	int? isSend;
+	@JSONField(name: "is_late")
+	int? isLate;
+	@JSONField(name: "parent_id")
+	int? parentId;
+	@JSONField(name: "revise_version")
+	int? reviseVersion;
+	int? source;
+	@JSONField(name: "no_show_remark")
+	dynamic noShowRemark;
+	@JSONField(name: "is_prompt")
+	int? isPrompt;
+	@JSONField(name: "reject_time")
+	int? rejectTime;
+	@JSONField(name: "reject_remark")
+	String? rejectRemark;
+	int? urgent;
+	@JSONField(name: "checkin_temperature")
+	int? checkinTemperature;
+	@JSONField(name: "checkout_temperature")
+	int? checkoutTemperature;
+	@JSONField(name: "security_clock_in")
+	int? securityClockIn;
+	@JSONField(name: "security_clock_out")
+	int? securityClockOut;
+	@JSONField(name: "work_clock_in")
+	int? workClockIn;
+	@JSONField(name: "work_clock_out")
+	int? workClockOut;
+	@JSONField(name: "hotel_applied_id")
+	int? hotelAppliedId;
+	@JSONField(name: "break_hours")
+	int? breakHours;
+	@JSONField(name: "is_cash_pay")
+	int? isCashPay;
+	@JSONField(name: "applied_id")
+	int? appliedId;
+	@JSONField(name: "security_in_time")
+	int? securityInTime;
+	@JSONField(name: "security_out_time")
+	int? securityOutTime;
+	@JSONField(name: "co_confirmed")
+	int? coConfirmed;
+	@JSONField(name: "co_reason")
+	String? coReason;
+	@JSONField(name: "co_reason_type")
+	int? coReasonType;
+	@JSONField(name: "agency_rate")
+	String? agencyRate;
+	String? gratuity;
+
+	UkJobAppliedReviseEditDetailReviseApplied();
+
+	factory UkJobAppliedReviseEditDetailReviseApplied.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseEditDetailReviseAppliedFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseEditDetailReviseAppliedToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 54 - 0
packages/cs_domain/lib/entity/response/uk_job_applied_revise_info_entity.dart

@@ -0,0 +1,54 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_job_applied_revise_info_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_job_applied_revise_info_entity.g.dart';
+
+@JsonSerializable()
+class UkJobAppliedReviseInfoEntity {
+	int? total;
+	List<UkJobAppliedReviseInfoRows>? rows;
+
+	UkJobAppliedReviseInfoEntity();
+
+	factory UkJobAppliedReviseInfoEntity.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseInfoEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseInfoEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseInfoRows {
+	int? id;
+	@JSONField(name: "revise_hours")
+	String? reviseHours;
+	@JSONField(name: "staff_name")
+	String? staffName;
+	@JSONField(name: "staff_nric")
+	String? staffNric;
+	@JSONField(name: "job_time")
+	String? jobTime;
+	@JSONField(name: "total_hours")
+	int? totalHours;
+	int? status;
+	@JSONField(name: "status_show")
+	String? statusShow;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "action_list")
+	List<String>? actionList;
+
+	UkJobAppliedReviseInfoRows();
+
+	factory UkJobAppliedReviseInfoRows.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseInfoRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseInfoRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 119 - 0
packages/cs_domain/lib/entity/response/uk_job_applied_revise_log_entity.dart

@@ -0,0 +1,119 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_job_applied_revise_log_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_job_applied_revise_log_entity.g.dart';
+
+@JsonSerializable()
+class UkJobAppliedReviseLogEntity {
+	List<UkJobAppliedReviseLogRecords>? records;
+	String? view;
+
+	UkJobAppliedReviseLogEntity();
+
+	factory UkJobAppliedReviseLogEntity.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseLogEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseLogEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseLogRecords {
+	int? id;
+	@JSONField(name: "operation_name")
+	String? operationName;
+	@JSONField(name: "data_type")
+	int? dataType;
+	String? desc;
+	UkJobAppliedReviseLogRecordsContent? content;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "act_class")
+	String? actClass;
+	@JSONField(name: "act_text")
+	String? actText;
+
+	UkJobAppliedReviseLogRecords();
+
+	factory UkJobAppliedReviseLogRecords.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseLogRecordsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseLogRecordsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseLogRecordsContent {
+	@JSONField(name: "revise_hours")
+	UkJobAppliedReviseLogRecordsContentReviseHours? reviseHours;
+	UkJobAppliedReviseLogRecordsContentStatus? status;
+	UkJobAppliedReviseLogRecordsContentReason? reason;
+
+	UkJobAppliedReviseLogRecordsContent();
+
+	factory UkJobAppliedReviseLogRecordsContent.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseLogRecordsContentFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseLogRecordsContentToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseLogRecordsContentReviseHours {
+	String? field;
+	int? value;
+
+	UkJobAppliedReviseLogRecordsContentReviseHours();
+
+	factory UkJobAppliedReviseLogRecordsContentReviseHours.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseLogRecordsContentReviseHoursFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseLogRecordsContentReviseHoursToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseLogRecordsContentStatus {
+	String? field;
+	String? value;
+
+	UkJobAppliedReviseLogRecordsContentStatus();
+
+	factory UkJobAppliedReviseLogRecordsContentStatus.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseLogRecordsContentStatusFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseLogRecordsContentStatusToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedReviseLogRecordsContentReason {
+	String? field;
+	String? value;
+
+	UkJobAppliedReviseLogRecordsContentReason();
+
+	factory UkJobAppliedReviseLogRecordsContentReason.fromJson(Map<String, dynamic> json) => $UkJobAppliedReviseLogRecordsContentReasonFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedReviseLogRecordsContentReasonToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 165 - 0
packages/cs_domain/lib/entity/response/uk_job_applied_staff_list_entity.dart

@@ -0,0 +1,165 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_job_applied_staff_list_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_job_applied_staff_list_entity.g.dart';
+
+@JsonSerializable()
+class UkJobAppliedStaffListEntity {
+	int? total;
+	List<UkJobAppliedStaffListRows>? rows;
+
+	UkJobAppliedStaffListEntity();
+
+	factory UkJobAppliedStaffListEntity.fromJson(Map<String, dynamic> json) => $UkJobAppliedStaffListEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedStaffListEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedStaffListRows {
+	@JSONField(name: "applied_id")
+	int? appliedId;
+	@JSONField(name: "member_id")
+	int? memberId;
+	@JSONField(name: "is_delete")
+	int? isDelete;
+	@JSONField(name: "staff_name")
+	String? staffName;
+	@JSONField(name: "job_title")
+	String? jobTitle;
+	@JSONField(name: "outlet_name")
+	dynamic outletName;
+	@JSONField(name: "job_date")
+	String? jobDate;
+	@JSONField(name: "start_time")
+	String? startTime;
+	@JSONField(name: "end_time")
+	String? endTime;
+	@JSONField(name: "adjust_show")
+	String? adjustShow;
+	@JSONField(name: "total_show")
+	int? totalShow;
+	@JSONField(name: "total_rooms")
+	int? totalRooms;
+	@JSONField(name: "work_status")
+	int? workStatus;
+	@JSONField(name: "reject_remark")
+	String? rejectRemark;
+	@JSONField(name: "reject_remark_short")
+	String? rejectRemarkShort;
+	int? status;
+	@JSONField(name: "status_show")
+	String? statusShow;
+	@JSONField(name: "applied_at")
+	String? appliedAt;
+	@JSONField(name: "security_in")
+	UkJobAppliedStaffListRowsSecurityIn? securityIn;
+	@JSONField(name: "security_out")
+	UkJobAppliedStaffListRowsSecurityOut? securityOut;
+	@JSONField(name: "work_in")
+	UkJobAppliedStaffListRowsWorkIn? workIn;
+	@JSONField(name: "work_out")
+	UkJobAppliedStaffListRowsWorkOut? workOut;
+	@JSONField(name: "revise_hours")
+	int? reviseHours;
+	String? gratuity;
+	@JSONField(name: "s_in")
+	int? sIn;
+	@JSONField(name: "s_out")
+	int? sOut;
+	@JSONField(name: "w_in")
+	int? wIn;
+	@JSONField(name: "w_out")
+	int? wOut;
+	@JSONField(name: "action_list")
+	List<String>? actionList;
+	bool isSelected = false;
+
+	UkJobAppliedStaffListRows();
+
+	factory UkJobAppliedStaffListRows.fromJson(Map<String, dynamic> json) => $UkJobAppliedStaffListRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedStaffListRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedStaffListRowsSecurityIn {
+	String? time;
+	dynamic image;
+	int? changed;
+
+	UkJobAppliedStaffListRowsSecurityIn();
+
+	factory UkJobAppliedStaffListRowsSecurityIn.fromJson(Map<String, dynamic> json) => $UkJobAppliedStaffListRowsSecurityInFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedStaffListRowsSecurityInToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedStaffListRowsSecurityOut {
+	String? time;
+	dynamic image;
+	int? changed;
+
+	UkJobAppliedStaffListRowsSecurityOut();
+
+	factory UkJobAppliedStaffListRowsSecurityOut.fromJson(Map<String, dynamic> json) => $UkJobAppliedStaffListRowsSecurityOutFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedStaffListRowsSecurityOutToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedStaffListRowsWorkIn {
+	String? time;
+	dynamic image;
+	int? changed;
+
+	UkJobAppliedStaffListRowsWorkIn();
+
+	factory UkJobAppliedStaffListRowsWorkIn.fromJson(Map<String, dynamic> json) => $UkJobAppliedStaffListRowsWorkInFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedStaffListRowsWorkInToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkJobAppliedStaffListRowsWorkOut {
+	String? time;
+	dynamic image;
+	int? changed;
+
+	UkJobAppliedStaffListRowsWorkOut();
+
+	factory UkJobAppliedStaffListRowsWorkOut.fromJson(Map<String, dynamic> json) => $UkJobAppliedStaffListRowsWorkOutFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobAppliedStaffListRowsWorkOutToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 44 - 0
packages/cs_domain/lib/entity/response/uk_job_template_detail_by_select_title_entity.dart

@@ -0,0 +1,44 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_job_template_detail_by_select_title_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_job_template_detail_by_select_title_entity.g.dart';
+
+@JsonSerializable()
+class UkJobTemplateDetailBySelectTitleEntity {
+	int? id;
+	@JSONField(name: "title_id")
+	int? titleId;
+	String? title;
+	String? contact;
+	@JSONField(name: "contact_no")
+	String? contactNo;
+	String? requirements;
+	String? note;
+	@JSONField(name: "job_title_id")
+	int? jobTitleId;
+	@JSONField(name: "job_title")
+	String? jobTitle;
+	@JSONField(name: "job_certificate")
+	String? jobCertificate;
+	@JSONField(name: "job_vehicle")
+	String? jobVehicle;
+	@JSONField(name: "challenge_25")
+	int? challenge25;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "updated_at")
+	String? updatedAt;
+	@JSONField(name: "deleted_at")
+	dynamic deletedAt;
+
+	UkJobTemplateDetailBySelectTitleEntity();
+
+	factory UkJobTemplateDetailBySelectTitleEntity.fromJson(Map<String, dynamic> json) => $UkJobTemplateDetailBySelectTitleEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkJobTemplateDetailBySelectTitleEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 158 - 0
packages/cs_domain/lib/entity/response/uk_labour_request_detail_entity.dart

@@ -0,0 +1,158 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_labour_request_detail_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_labour_request_detail_entity.g.dart';
+
+@JsonSerializable()
+class UkLabourRequestDetailEntity {
+	@JSONField(name: "request_id")
+	int? requestId;
+	@JSONField(name: "job_title")
+	String? jobTitle;
+	@JSONField(name: "job_start")
+	String? jobStart;
+	@JSONField(name: "job_end")
+	String? jobEnd;
+	@JSONField(name: "need_num")
+	int? needNum;
+	@JSONField(name: "department_id")
+	int? departmentId;
+	@JSONField(name: "template_id")
+	int? templateId;
+	String? location;
+	@JSONField(name: "job_location_other")
+	String? jobLocationOther;
+	@JSONField(name: "service_type")
+	int? serviceType;
+	@JSONField(name: "salary_by")
+	String? salaryBy;
+	int? amount;
+	@JSONField(name: "employment_type")
+	int? employmentType;
+	@JSONField(name: "event_name")
+	String? eventName;
+	@JSONField(name: "event_type")
+	String? eventType;
+	int? passengers;
+	@JSONField(name: "est_revenue")
+	String? estRevenue;
+	String? position;
+	String? description;
+	@JSONField(name: "att_url")
+	String? attUrl;
+	@JSONField(name: "est_cost")
+	String? estCost;
+	@JSONField(name: "est_ratio")
+	int? estRatio;
+	@JSONField(name: "location_list")
+	List<UkLabourRequestDetailLocationList>? locationList;
+	@JSONField(name: "template_list")
+	List<UkLabourRequestDetailTemplateList>? templateList;
+	@JSONField(name: "department_list")
+	List<UkLabourRequestDetailDepartmentList>? departmentList;
+	@JSONField(name: "charge_list")
+	List<UkLabourRequestDetailChargeList>? chargeList;
+	@JSONField(name: "employment_list")
+	List<UkLabourRequestDetailEmploymentList>? employmentList;
+
+	UkLabourRequestDetailEntity();
+
+	factory UkLabourRequestDetailEntity.fromJson(Map<String, dynamic> json) => $UkLabourRequestDetailEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestDetailEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestDetailLocationList {
+	String? value;
+	String? txt;
+	String? selected;
+
+	UkLabourRequestDetailLocationList();
+
+	factory UkLabourRequestDetailLocationList.fromJson(Map<String, dynamic> json) => $UkLabourRequestDetailLocationListFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestDetailLocationListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestDetailTemplateList {
+	int? value;
+	String? txt;
+	String? selected;
+
+	UkLabourRequestDetailTemplateList();
+
+	factory UkLabourRequestDetailTemplateList.fromJson(Map<String, dynamic> json) => $UkLabourRequestDetailTemplateListFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestDetailTemplateListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestDetailDepartmentList {
+	int? value;
+	String? txt;
+	String? selected;
+
+	UkLabourRequestDetailDepartmentList();
+
+	factory UkLabourRequestDetailDepartmentList.fromJson(Map<String, dynamic> json) => $UkLabourRequestDetailDepartmentListFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestDetailDepartmentListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestDetailChargeList {
+	String? value;
+	String? txt;
+	String? checked;
+
+	UkLabourRequestDetailChargeList();
+
+	factory UkLabourRequestDetailChargeList.fromJson(Map<String, dynamic> json) => $UkLabourRequestDetailChargeListFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestDetailChargeListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestDetailEmploymentList {
+	int? value;
+	String? txt;
+	String? selected;
+
+	UkLabourRequestDetailEmploymentList();
+
+	factory UkLabourRequestDetailEmploymentList.fromJson(Map<String, dynamic> json) => $UkLabourRequestDetailEmploymentListFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestDetailEmploymentListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 46 - 0
packages/cs_domain/lib/entity/response/uk_labour_request_preselect_addstatff_list_entity.dart

@@ -0,0 +1,46 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_labour_request_preselect_addstatff_list_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_labour_request_preselect_addstatff_list_entity.g.dart';
+
+@JsonSerializable()
+class UkLabourRequestPreselectAddstatffListEntity {
+	int? total;
+	List<UkLabourRequestPreselectAddstatffListRows>? rows;
+
+	UkLabourRequestPreselectAddstatffListEntity();
+
+	factory UkLabourRequestPreselectAddstatffListEntity.fromJson(Map<String, dynamic> json) => $UkLabourRequestPreselectAddstatffListEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestPreselectAddstatffListEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestPreselectAddstatffListRows {
+	int? id;
+	String? name;
+	String? gender;
+	String? nric;
+	@JSONField(name: "profile_picture")
+	String? profilePicture;
+	int? status;
+	@JSONField(name: "apply_state")
+	int? applyState;
+	bool isSelected = false;
+
+	UkLabourRequestPreselectAddstatffListRows();
+
+	factory UkLabourRequestPreselectAddstatffListRows.fromJson(Map<String, dynamic> json) => $UkLabourRequestPreselectAddstatffListRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestPreselectAddstatffListRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 44 - 0
packages/cs_domain/lib/entity/response/uk_labour_request_preselected_list_entity.dart

@@ -0,0 +1,44 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_labour_request_preselected_list_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_labour_request_preselected_list_entity.g.dart';
+
+@JsonSerializable()
+class UkLabourRequestPreselectedListEntity {
+	int? total;
+	List<UkLabourRequestPreselectedListRows>? rows;
+
+	UkLabourRequestPreselectedListEntity();
+
+	factory UkLabourRequestPreselectedListEntity.fromJson(Map<String, dynamic> json) => $UkLabourRequestPreselectedListEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestPreselectedListEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestPreselectedListRows {
+	int? id;
+	@JSONField(name: "status_show")
+	String? statusShow;
+	String? message;
+	String? name;
+	String? sex;
+	String? nric;
+	String? avatar;
+
+	UkLabourRequestPreselectedListRows();
+
+	factory UkLabourRequestPreselectedListRows.fromJson(Map<String, dynamic> json) => $UkLabourRequestPreselectedListRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestPreselectedListRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 213 - 0
packages/cs_domain/lib/entity/response/uk_labour_request_review_detail_entity.dart

@@ -0,0 +1,213 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_labour_request_review_detail_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_labour_request_review_detail_entity.g.dart';
+
+@JsonSerializable()
+class UkLabourRequestReviewDetailEntity {
+	UkLabourRequestReviewDetailOrder? order;
+	@JSONField(name: "department_id")
+	int? departmentId;
+	List<UkLabourRequestReviewDetailRecords>? records;
+
+	UkLabourRequestReviewDetailEntity();
+
+	factory UkLabourRequestReviewDetailEntity.fromJson(Map<String, dynamic> json) => $UkLabourRequestReviewDetailEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestReviewDetailEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestReviewDetailOrder {
+	int? id;
+	@JSONField(name: "company_id")
+	int? companyId;
+	@JSONField(name: "request_id")
+	int? requestId;
+	int? status;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "updated_at")
+	String? updatedAt;
+	UkLabourRequestReviewDetailOrderRequest? request;
+	List<UkLabourRequestReviewDetailOrderRecords>? records;
+
+	UkLabourRequestReviewDetailOrder();
+
+	factory UkLabourRequestReviewDetailOrder.fromJson(Map<String, dynamic> json) => $UkLabourRequestReviewDetailOrderFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestReviewDetailOrderToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestReviewDetailOrderRequest {
+	int? id;
+	@JSONField(name: "employer_admin_id")
+	int? employerAdminId;
+	@JSONField(name: "job_title")
+	String? jobTitle;
+	@JSONField(name: "need_num")
+	int? needNum;
+	@JSONField(name: "job_start")
+	String? jobStart;
+	@JSONField(name: "job_end")
+	String? jobEnd;
+	@JSONField(name: "job_id")
+	int? jobId;
+	@JSONField(name: "remark_id")
+	int? remarkId;
+	String? status;
+	@JSONField(name: "add_time")
+	String? addTime;
+	String? from;
+	@JSONField(name: "reject_reason")
+	dynamic rejectReason;
+	dynamic banquet;
+	@JSONField(name: "hotel_job_id")
+	int? hotelJobId;
+	@JSONField(name: "work_content")
+	String? workContent;
+	@JSONField(name: "hourly_rate")
+	int? hourlyRate;
+	@JSONField(name: "co_department_id")
+	int? coDepartmentId;
+	@JSONField(name: "co_status")
+	int? coStatus;
+	@JSONField(name: "co_template_id")
+	int? coTemplateId;
+	@JSONField(name: "co_approved_at")
+	dynamic coApprovedAt;
+	@JSONField(name: "service_type")
+	int? serviceType;
+	@JSONField(name: "job_unit")
+	String? jobUnit;
+	@JSONField(name: "agency_rate")
+	String? agencyRate;
+	String? location;
+	String? vehicle;
+	@JSONField(name: "source_type")
+	int? sourceType;
+	@JSONField(name: "agency_id")
+	int? agencyId;
+	@JSONField(name: "agency_name")
+	String? agencyName;
+	@JSONField(name: "employment_type")
+	int? employmentType;
+	@JSONField(name: "event_name")
+	String? eventName;
+	@JSONField(name: "event_type")
+	String? eventType;
+	int? passengers;
+	@JSONField(name: "est_revenue")
+	String? estRevenue;
+	String? position;
+	@JSONField(name: "est_cost")
+	String? estCost;
+	String? description;
+	@JSONField(name: "att_url")
+	String? attUrl;
+
+	UkLabourRequestReviewDetailOrderRequest();
+
+	factory UkLabourRequestReviewDetailOrderRequest.fromJson(Map<String, dynamic> json) => $UkLabourRequestReviewDetailOrderRequestFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestReviewDetailOrderRequestToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestReviewDetailOrderRecords {
+	int? id;
+	@JSONField(name: "company_id")
+	int? companyId;
+	@JSONField(name: "order_id")
+	int? orderId;
+	@JSONField(name: "request_id")
+	int? requestId;
+	@JSONField(name: "flow_id")
+	int? flowId;
+	@JSONField(name: "serial_number")
+	int? serialNumber;
+	@JSONField(name: "node_name")
+	String? nodeName;
+	@JSONField(name: "assignee_type")
+	int? assigneeType;
+	@JSONField(name: "assignee_role_ids")
+	String? assigneeRoleIds;
+	@JSONField(name: "assignee_admin_ids")
+	String? assigneeAdminIds;
+	@JSONField(name: "audit_status")
+	int? auditStatus;
+	@JSONField(name: "audit_id")
+	int? auditId;
+	@JSONField(name: "audit_name")
+	String? auditName;
+	@JSONField(name: "audit_time")
+	dynamic auditTime;
+	@JSONField(name: "audit_mark")
+	String? auditMark;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "updated_at")
+	dynamic updatedAt;
+	@JSONField(name: "send_email")
+	int? sendEmail;
+
+	UkLabourRequestReviewDetailOrderRecords();
+
+	factory UkLabourRequestReviewDetailOrderRecords.fromJson(Map<String, dynamic> json) => $UkLabourRequestReviewDetailOrderRecordsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestReviewDetailOrderRecordsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestReviewDetailRecords {
+	@JSONField(name: "serial_number")
+	int? serialNumber;
+	@JSONField(name: "node_name")
+	String? nodeName;
+	@JSONField(name: "status_show")
+	String? statusShow;
+	@JSONField(name: "audit_name")
+	String? auditName;
+	@JSONField(name: "audit_time")
+	String? auditTime;
+	@JSONField(name: "audit_mark")
+	dynamic auditMark;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "assignee_type_show")
+	String? assigneeTypeShow;
+	@JSONField(name: "designation_show")
+	String? designationShow;
+
+	UkLabourRequestReviewDetailRecords();
+
+	factory UkLabourRequestReviewDetailRecords.fromJson(Map<String, dynamic> json) => $UkLabourRequestReviewDetailRecordsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestReviewDetailRecordsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 69 - 0
packages/cs_domain/lib/entity/response/uk_labour_request_review_list_entity.dart

@@ -0,0 +1,69 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/uk_labour_request_review_list_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/uk_labour_request_review_list_entity.g.dart';
+
+@JsonSerializable()
+class UkLabourRequestReviewListEntity {
+	int? total;
+	List<UkLabourRequestReviewListRows>? rows;
+
+	UkLabourRequestReviewListEntity();
+
+	factory UkLabourRequestReviewListEntity.fromJson(Map<String, dynamic> json) => $UkLabourRequestReviewListEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestReviewListEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class UkLabourRequestReviewListRows {
+	@JSONField(name: "record_id")
+	int? recordId;
+	@JSONField(name: "order_id")
+	int? orderId;
+	@JSONField(name: "request_id")
+	int? requestId;
+	@JSONField(name: "job_title")
+	String? jobTitle;
+	@JSONField(name: "job_full_time")
+	String? jobFullTime;
+	@JSONField(name: "job_date")
+	String? jobDate;
+	@JSONField(name: "job_time")
+	String? jobTime;
+	@JSONField(name: "department_name")
+	String? departmentName;
+	@JSONField(name: "need_num")
+	int? needNum;
+	String? salary;
+	@JSONField(name: "status_show")
+	String? statusShow;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	@JSONField(name: "service_type")
+	int? serviceType;
+	@JSONField(name: "job_hours")
+	String? jobHours;
+	@JSONField(name: "est_amount")
+	String? estAmount;
+	@JSONField(name: "event_name")
+	String? eventName;
+
+	bool isSelected = false;
+
+	UkLabourRequestReviewListRows();
+
+	factory UkLabourRequestReviewListRows.fromJson(Map<String, dynamic> json) => $UkLabourRequestReviewListRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $UkLabourRequestReviewListRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 0 - 0
packages/cs_domain/lib/entity/response/uk_labour_request_table_entity.dart


Некоторые файлы не были показаны из-за большого количества измененных файлов