瀏覽代碼

预选的逻辑

liukai 2 月之前
父節點
當前提交
69a411540d
共有 24 個文件被更改,包括 1777 次插入146 次删除
  1. 70 91
      packages/cpt_th/lib/modules/job_er/applied_er/applied_er_item.dart
  2. 38 25
      packages/cpt_th/lib/modules/job_er/applied_er/applied_er_page.dart
  3. 13 2
      packages/cpt_th/lib/modules/job_er/job_list_er/job_list_er_controller.dart
  4. 23 12
      packages/cpt_th/lib/modules/job_er/job_list_er/job_list_er_item.dart
  5. 3 0
      packages/cpt_th/lib/modules/job_er/job_list_er/job_list_er_page.dart
  6. 345 0
      packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_add_staff.dart
  7. 133 0
      packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_add_staff_controller.dart
  8. 322 0
      packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_selected_staff.dart
  9. 207 0
      packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_selected_staff_controller.dart
  10. 22 15
      packages/cpt_th/lib/modules/labour/labour_request_list/labour_request_item.dart
  11. 12 0
      packages/cpt_th/lib/modules/labour/labour_request_list/labour_request_list_controller.dart
  12. 3 0
      packages/cpt_th/lib/modules/labour/labour_request_list/labour_request_list_page.dart
  13. 16 1
      packages/cs_domain/lib/constants/api_constants.dart
  14. 28 0
      packages/cs_domain/lib/entity/response/t_h_pre_selected_option_entity.dart
  15. 46 0
      packages/cs_domain/lib/entity/response/t_h_pre_selected_staff_table_entity.dart
  16. 44 0
      packages/cs_domain/lib/entity/response/t_h_pre_selected_table_entity.dart
  17. 23 0
      packages/cs_domain/lib/generated/json/base/json_convert_content.dart
  18. 54 0
      packages/cs_domain/lib/generated/json/t_h_pre_selected_option_entity.g.dart
  19. 107 0
      packages/cs_domain/lib/generated/json/t_h_pre_selected_staff_table_entity.g.dart
  20. 100 0
      packages/cs_domain/lib/generated/json/t_h_pre_selected_table_entity.g.dart
  21. 159 0
      packages/cs_domain/lib/repository/th_er_repository.dart
  22. 3 0
      packages/cs_resources/lib/local/language/en_US.dart
  23. 3 0
      packages/cs_resources/lib/local/language/th_TH.dart
  24. 3 0
      packages/cs_resources/lib/local/language/zh_CN.dart

+ 70 - 91
packages/cpt_th/lib/modules/job_er/applied_er/applied_er_item.dart

@@ -57,27 +57,45 @@ class AppliedErItem extends StatelessWidget {
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               MyTextView(
-                "Staff Name:".tr,
+                "Name:".tr,
                 isFontRegular: true,
                 textColor: ColorConstants.textGrayAECAE5,
                 fontSize: 14,
               ),
 
-              //姓名
-              MyTextView(
-                item.labourerName ?? "-",
-                isFontMedium: true,
-                textColor: ColorConstants.textYellowFFBB1B,
-                fontSize: 14,
-                marginLeft: 5,
-                marginRight: 5,
-                textDecoration: TextDecoration.underline,
-                decorationColor: ColorConstants.textYellowFFBB1B,
-                // 可选,设置下划线的颜色
-                decorationThickness: 2.0,
-                // 可选,设置下划线的粗细
-                decorationStyle: TextDecorationStyle.solid,
-                onClick: onMemberAction,
+              Row(
+                children: [
+                  //姓名
+                  MyTextView(
+                    item.labourerName ?? "-",
+                    isFontMedium: true,
+                    textColor: ColorConstants.textYellowFFBB1B,
+                    fontSize: 14,
+                    marginLeft: 5,
+                    marginRight: 10,
+                    textDecoration: TextDecoration.underline,
+                    decorationColor: ColorConstants.textYellowFFBB1B,
+                    // 可选,设置下划线的颜色
+                    decorationThickness: 2.0,
+                    // 可选,设置下划线的粗细
+                    decorationStyle: TextDecorationStyle.solid,
+                    onClick: onMemberAction,
+                  ),
+
+                  //头像
+                  Hero(
+                    tag: '112cc8a34e13',
+                    child: MyLoadImage(
+                      item.avatar,
+                      width: 22,
+                      height: 22,
+                    ),
+                  ).onTap(() {
+                    if (Utils.isNotEmpty(item.avatar)) {
+                      ImagePreviewEngine.singleImagePreview(context, item.avatar ?? "", heroTag: '112cc8a34e13');
+                    }
+                  }),
+                ],
               ).expanded(),
 
               //是否选中
@@ -85,85 +103,50 @@ class AppliedErItem extends StatelessWidget {
                 item.isSelected ? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedIcon,
                 width: 20.5,
                 height: 20.5,
-              ),
+              ).marginOnly(left: 10),
             ],
           ),
 
           Row(
             children: [
-              //头像
-            /* if (ConfigService.to.isTHOAType)*/ Row(
-                  mainAxisSize: MainAxisSize.max,
-                  crossAxisAlignment: CrossAxisAlignment.center,
-                  children: [
-                    MyTextView(
-                      "${"Avatar".tr}:",
-                      isFontRegular: true,
-                      marginRight: 10,
-                      textColor: ColorConstants.textGrayAECAE5,
-                      fontSize: 14,
-                    ),
-                    MyLoadImage(
-                      item.avatar,
-                      width: 50,
-                      height: 50,
-                    ),
-                  ],
-                ).marginOnly(right: 10).expanded(),
-
-
-              Column(
-                mainAxisSize: MainAxisSize.max,
-                crossAxisAlignment: CrossAxisAlignment.start,
-                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              Row(
+                mainAxisSize: MainAxisSize.min,
                 children: [
-
                   MyTextView(
-                    item.clothingSize ?? "-",
-                    isFontMedium: true,
-                    textColor: ColorConstants.textYellowFFBB1B,
+                    "Status:".tr,
+                    isFontRegular: true,
+                    textColor: ColorConstants.textGrayAECAE5,
                     fontSize: 14,
-                    textDecoration: TextDecoration.underline,
-                    decorationColor: ColorConstants.textYellowFFBB1B,
-                    // 可选,设置下划线的颜色
-                    decorationThickness: 2.0,
-                    // 可选,设置下划线的粗细
-                    decorationStyle: TextDecorationStyle.solid,
                   ),
-
-                  Row(
-                    mainAxisSize: MainAxisSize.min,
-                    children: [
-                      MyTextView(
-                        "Status:".tr,
-                        isFontRegular: true,
-                        textColor: ColorConstants.textGrayAECAE5,
-                        fontSize: 14,
-                      ),
-
-                      MyTextView(
-                        item.statusShow ?? "-",
-                        isFontRegular: true,
-                        textColor: "Completed" == item.statusShow
-                            ? ColorConstants.textGreen05DC82
-                            : "Cancelled" == item.statusShow || "Rejected" == item.statusShow
+                  MyTextView(
+                    item.statusShow ?? "-",
+                    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,
-                      )
-
-                    ],
-                  ).marginOnly(top: 5),
-
+                                ? ColorConstants.textYellowFFBB1B
+                                : ColorConstants.textBlue06D9FF, //默认蓝色
+                    fontSize: 14,
+                  )
                 ],
-              ).expanded()
-
+              ).expanded(),
+              const SizedBox(width: 10),
+              MyTextView(
+                item.clothingSize ?? "-",
+                isFontMedium: true,
+                textColor: ColorConstants.textYellowFFBB1B,
+                fontSize: 14,
+                textDecoration: TextDecoration.underline,
+                decorationColor: ColorConstants.textYellowFFBB1B,
+                // 可选,设置下划线的颜色
+                decorationThickness: 2.0,
+                // 可选,设置下划线的粗细
+                decorationStyle: TextDecorationStyle.solid,
+              ).expanded(),
             ],
-          ).marginOnly(top: 10),
-
-
+          ).marginOnly(top: 6),
 
           // 工作开始时间,结束时间
           Row(
@@ -216,7 +199,7 @@ class AppliedErItem extends StatelessWidget {
                 ],
               ).expanded(),
             ],
-          ).marginOnly(top: 10),
+          ).marginOnly(top: 6),
 
           //门卫签到
           Row(
@@ -287,7 +270,7 @@ class AppliedErItem extends StatelessWidget {
                 ],
               ).expanded(),
             ],
-          ).marginOnly(top: 10),
+          ).marginOnly(top: 6),
 
           //工作地签到
           Row(
@@ -357,14 +340,12 @@ class AppliedErItem extends StatelessWidget {
                   ).expanded(),
                 ],
               ).expanded(),
-
             ],
-          ).marginOnly(top: 10),
+          ).marginOnly(top: 6),
 
           //工作时长
           Row(
             children: [
-
               // + - Hours
               Row(
                 mainAxisSize: MainAxisSize.max,
@@ -412,10 +393,8 @@ class AppliedErItem extends StatelessWidget {
                   ).expanded(),
                 ],
               ).expanded(),
-
             ],
-          ).marginOnly(top: 10),
-
+          ).marginOnly(top: 6),
 
           //按钮组
           Visibility(
@@ -478,7 +457,7 @@ class AppliedErItem extends StatelessWidget {
                   ).marginOnly(left: 12),
                 ),
               ],
-            ).marginOnly(top: 15),
+            ).marginOnly(top: 4),
           ),
         ],
       ).onTap(() {

+ 38 - 25
packages/cpt_th/lib/modules/job_er/applied_er/applied_er_page.dart

@@ -75,12 +75,25 @@ class _JobAppliedState extends BaseState<AppliedErPage, AppliedErController> {
           ),
           child: Column(
             children: [
-              MyAppBar.titleBar(
-                context,
-                state.jobInfo?.job?.jobTitle ?? "Title".tr,
-                subTitle: "(${state.jobInfo?.jobDate ?? "-"})",
-                subTitleColor: ColorConstants.textGrayAECAE5,
-              ),
+              MyAppBar.titleBar(context, state.jobInfo?.job?.jobTitle ?? "Title".tr,
+                  subTitle: "(${state.jobInfo?.jobDate ?? "-"})",
+                  subTitleColor: ColorConstants.textGrayAECAE5,
+                  actions: [
+                    Visibility(
+                      visible:  state.jobInfo?.canAppend == true,
+                      child: MyTextView(
+                        "Add".tr,
+                        textColor: Colors.white,
+                        fontSize: 17,
+                        isFontMedium: true,
+                        marginRight: 15,
+                        onClick: () {
+                          FocusScope.of(context).unfocus();
+                          controller.showAddStaffDialog();
+                        },
+                      ),
+                    ),
+                  ]),
 
               //搜索的条件
               Row(
@@ -132,26 +145,26 @@ class _JobAppliedState extends BaseState<AppliedErPage, AppliedErController> {
                     minHeight: 35,
                   ),
                 ],
-              ).marginOnly(top: 10, left: 15, right: 15, bottom: 5),
+              ).marginOnly(top: 10, left: 15, right: 15),
 
-              // 添加按钮
-              Visibility(
-                visible: state.jobInfo?.canAppend == true,
-                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,
-                ).marginOnly(left: 15, right: 15, top: 5, bottom: 10),
-              ),
+              // // 添加按钮
+              // Visibility(
+              //   visible: state.jobInfo?.canAppend == true,
+              //   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,
+              //   ).marginOnly(left: 15, right: 15, top: 5, bottom: 10),
+              // ),
 
               //底部的列表
               EasyRefresh(

+ 13 - 2
packages/cpt_th/lib/modules/job_er/job_list_er/job_list_er_controller.dart

@@ -17,6 +17,7 @@ import 'package:widgets/widget_export.dart';
 
 import 'job_list_er_filter.dart';
 import 'job_list_er_state.dart';
+import 'widget/pre_selected_staff.dart';
 
 class JobListController extends GetxController with DioCancelableMixin {
   final THERRepository _erRepository = Get.find();
@@ -172,7 +173,7 @@ class JobListController extends GetxController with DioCancelableMixin {
           selectedOutletId: state.selectedOutletId,
           selectedDivisionId: state.selectedDivisionId,
           selectedTrending: state.selectedTrending,
-          onFilterAction: (startDate, endDate, statusId, outletId, divisionId,trending) {
+          onFilterAction: (startDate, endDate, statusId, outletId, divisionId, trending) {
             state.selectedStartDate = startDate;
             state.selectedEndDate = endDate;
             state.selectedStatusId = statusId;
@@ -204,7 +205,7 @@ class JobListController extends GetxController with DioCancelableMixin {
 
   /// 去编辑页面
   void gotoJobEditPage(LabourListERRows data) {
-    LabourRequestERAddPage.startInstance(1, data.jobId, (result){
+    LabourRequestERAddPage.startInstance(1, data.jobId, (result) {
       refreshController.callRefresh();
     });
   }
@@ -242,4 +243,14 @@ class JobListController extends GetxController with DioCancelableMixin {
       ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
     }
   }
+
+  /// 预选员工
+  void doPreSelectedAction(LabourListERRows data) {
+    DialogEngine.show(
+      widget: PreSelectedStaff(
+        jobId: data.jobId,
+        jobStatus: data.status,
+      ),
+    );
+  }
 }

+ 23 - 12
packages/cpt_th/lib/modules/job_er/job_list_er/job_list_er_item.dart

@@ -17,6 +17,7 @@ class JobListErItem extends StatelessWidget {
   final VoidCallback? onEditAction;
   final VoidCallback? onDeleteAction;
   final VoidCallback? onAppliedAction;
+  final VoidCallback? onPreSelectedAction;
 
   JobListErItem({
     required this.index,
@@ -24,12 +25,13 @@ class JobListErItem extends StatelessWidget {
     this.onEditAction,
     this.onDeleteAction,
     this.onAppliedAction,
+    this.onPreSelectedAction,
   });
 
   @override
   Widget build(BuildContext context) {
     return Container(
-      padding: const EdgeInsets.symmetric(vertical: 23, horizontal: 21),
+      padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 21),
       margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
       decoration: BoxDecoration(
         color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
@@ -68,7 +70,7 @@ class JobListErItem extends StatelessWidget {
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top:10),
+          ).marginOnly(top: 6),
 
           // 工作日期时间
           Row(
@@ -84,14 +86,14 @@ class JobListErItem extends StatelessWidget {
 
               //日期时间
               MyTextView(
-                item.jobDate ?? "-",
+                "${item.jobDate} ${item.startTime}~${item.endTime}",
                 marginLeft: 5,
                 isFontRegular: true,
                 textColor: Colors.white,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top:10),
+          ).marginOnly(top: 6),
 
           // 人数
           Row(
@@ -110,12 +112,17 @@ class JobListErItem extends StatelessWidget {
                 item.hiringNum ?? "",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: ColorConstants.textYellowFFBB1B,
+                textColor: ColorConstants.textGreen0AC074,
                 onClick: onAppliedAction,
+                textDecoration: TextDecoration.underline,
+                //下拉选
+                decorationColor: ColorConstants.textGreen0AC074,
+                decorationThickness: 2.0,
+                decorationStyle: TextDecorationStyle.solid,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top:10),
+          ).marginOnly(top: 6),
 
           // 预选
           Row(
@@ -134,11 +141,16 @@ class JobListErItem extends StatelessWidget {
                 item.preNum ?? "-",
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: Colors.white,
                 fontSize: 14,
+                textColor: ColorConstants.textYellowFFBB1B,
+                textDecoration: TextDecoration.underline,
+                decorationColor: ColorConstants.textYellowFFBB1B,
+                decorationThickness: 2.0,
+                decorationStyle: TextDecorationStyle.solid,
+                onClick: onPreSelectedAction,
               ).expanded(),
             ],
-          ).marginOnly(top:10),
+          ).marginOnly(top: 6),
 
           // 时薪
           // Row(
@@ -161,7 +173,7 @@ class JobListErItem extends StatelessWidget {
           //       fontSize: 14,
           //     ).expanded(),
           //   ],
-          // ).marginOnly(top:10),
+          // ).marginOnly(top: 6),
 
           // 状态
           Row(
@@ -190,7 +202,7 @@ class JobListErItem extends StatelessWidget {
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top:10),
+          ).marginOnly(top: 6),
 
           //按钮组
           Visibility(
@@ -237,9 +249,8 @@ class JobListErItem extends StatelessWidget {
                     minHeight: 35,
                   ).marginOnly(left: 12),
                 ),
-
               ],
-            ).marginOnly(top: 18, bottom: 2),
+            ).marginOnly(top: 5),
           ),
         ],
       ),

+ 3 - 0
packages/cpt_th/lib/modules/job_er/job_list_er/job_list_er_page.dart

@@ -139,6 +139,9 @@ class _JobListState extends BaseState<JobListERPage, JobListController> {
                           onDeleteAction: (){
                             controller.doDeleteAction(state.datas[index]);
                           },
+                          onPreSelectedAction: (){
+                            controller.doPreSelectedAction(state.datas[index]);
+                          },
                         );
                       },
                       childCount: state.datas.length,

+ 345 - 0
packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_add_staff.dart

@@ -0,0 +1,345 @@
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/t_h_applied_employee_entity.dart';
+import 'package:domain/entity/response/t_h_pre_selected_staff_table_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 'pre_add_staff_controller.dart';
+
+/*
+ * 添加员工的弹窗
+ */
+class PreAddStaff extends StatefulWidget {
+  String? jobId;
+  String? requestId;
+  void Function(String selectIds)? confirmAction;
+
+  PreAddStaff({this.jobId, this.requestId, this.confirmAction});
+
+  @override
+  State<PreAddStaff> createState() => _AppliedAddStaffState();
+}
+
+class _AppliedAddStaffState extends State<PreAddStaff> {
+  @override
+  void initState() {
+    super.initState();
+    PreAddStaffController controller = Get.put(PreAddStaffController());
+    controller.jobId = widget.jobId;
+    controller.requestId = widget.requestId;
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    Get.delete<PreAddStaffController>();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return GetBuilder<PreAddStaffController>(
+      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].applyState = controller.datas[index].applyState == 1 ? 0 : 1;
+                            controller.update();
+                          });
+                        },
+                        childCount: controller.datas.length,
+                      ))
+                    ],
+                  ),
+                ).paddingZero,
+              ).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(PreAddStaffController controller) {
+    onCancel();
+
+    //找到当前选中的
+    var selectedList = controller.datas.where((element) => element.applyState == 1).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);
+    }
+  }
+
+  Widget _buildStaffItem(THPreSelectedStaffTableRows item, VoidCallback callback) {
+    return Stack(
+      children: [
+        Column(
+          children: [
+            //姓名
+            Row(
+              children: [
+                MyTextView(
+                  "Staff:",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  marginRight: 3,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.name ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ),
+
+            //头像
+            Row(
+              children: [
+                MyTextView(
+                  "Avatar:",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  marginRight: 3,
+                  isFontRegular: true,
+                ),
+                MyLoadImage(
+                  item.profilePicture ?? "",
+                  width: 25,
+                  height: 25,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            //性别
+            Row(
+              children: [
+                MyTextView(
+                  "Gender:",
+                  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(
+                  "NRIC:",
+                  marginRight: 3,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.nric ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            //电话
+            Row(
+              children: [
+                MyTextView(
+                  "Phone:",
+                  marginRight: 3,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.mobile ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            Container(
+              margin: const EdgeInsets.only(top: 19),
+              width: double.infinity,
+              height: 1,
+              color: const Color(0XFFF7F7F7),
+            )
+          ],
+        ).paddingOnly(left: 19, right: 20, top: 17),
+
+        //是否勾选
+        MyAssetImage(
+          item.applyState == 1 ? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedGrayIcon,
+          width: 20.5,
+          height: 20.5,
+        ).alignRight().marginOnly(right: 20, top: 17.5),
+      ],
+    ).onTap(callback);
+  }
+}

+ 133 - 0
packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_add_staff_controller.dart

@@ -0,0 +1,133 @@
+import 'package:domain/entity/response/t_h_applied_employee_entity.dart';
+import 'package:domain/entity/response/t_h_pre_selected_staff_table_entity.dart';
+import 'package:domain/repository/th_er_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:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+class PreAddStaffController extends GetxController with DioCancelableMixin {
+  final THERRepository _erRepository = Get.find();
+
+  TextEditingController searchController = TextEditingController();
+
+  var _curPage = 1;
+  var _needShowPlaceholder = true;
+
+  //页面PlaceHolder的展示
+  LoadState loadingState = LoadState.State_Success;
+  String? errorMessage;
+
+  String keyword = "";
+  String? jobId;
+  String? requestId;
+  List<THPreSelectedStaffTableRows> 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 _erRepository.fetchPreSelectedStaffTable(
+      jobId: jobId,
+      requestId: requestId,
+      keyword: keyword,
+      curPage: _curPage,
+      cancelToken: cancelToken,
+    );
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<THPreSelectedStaffTableRows>? 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();
+  }
+}

+ 322 - 0
packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_selected_staff.dart

@@ -0,0 +1,322 @@
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/t_h_pre_selected_table_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_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'pre_selected_staff_controller.dart';
+
+/*
+ * 已经预选员工的弹窗
+ */
+class PreSelectedStaff extends StatefulWidget {
+  String? jobId;
+  String? requestId;
+  int jobStatus = 0;
+
+  PreSelectedStaff({ this.jobId, this.requestId,required this.jobStatus});
+
+  @override
+  State<PreSelectedStaff> createState() => _AppliedAddStaffState();
+}
+
+class _AppliedAddStaffState extends State<PreSelectedStaff> {
+  @override
+  void initState() {
+    super.initState();
+    PreSelectedStaffController controller = Get.put(PreSelectedStaffController());
+    controller.jobId = widget.jobId;
+    controller.requestId = widget.requestId;
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    Get.delete<PreSelectedStaffController>();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return GetBuilder<PreSelectedStaffController>(
+      assignId: true,
+      builder: (controller) {
+        return Container(
+          width: 300,
+          height: 555,
+          color: const Color(0XFFF7F7F7),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Stack(
+                children: [
+                  MyTextView(
+                    "Pre-selected Staff".tr,
+                    fontSize: 19,
+                    isFontMedium: true,
+                    textColor: ColorConstants.black,
+                    marginTop: 22,
+                    marginLeft: 22,
+                    marginRight: 22,
+                  ).alignCenter(),
+                  const MyAssetImage(Assets.baseServiceRedDeleteIcon, width: 20, height: 20).marginOnly(top: 15, right: 15).onTap(() {
+                    onCancel();
+                  }).alignRight(),
+                ],
+              ),
+
+              //只有在工作状态 = pending 的时候才可以展示
+              Visibility(
+                visible: widget.jobStatus == 1,
+                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,
+                  minHeight: 30,
+                  backgroundColor: hexToColor("#FFBB1B"),
+                  fontWeight: FontWeight.w500,
+                ).marginOnly(left: 17, right: 17),
+              ),
+
+              //工作标题与时间
+              MyTextView(
+                "${controller.indexOptions?.jobTitle} ${controller.indexOptions?.jobDate}",
+                fontSize: 14,
+                marginLeft: 17,
+                marginRight: 17,
+                textColor: Colors.black,
+                isFontRegular: true,
+                marginBottom: 10,
+              ),
+
+              //列表容器
+              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], controller);
+                        },
+                        childCount: controller.datas.length,
+                      ))
+                    ],
+                  ),
+                ).paddingZero,
+              ).expanded(),
+            ],
+          ),
+        ).clipRRect(bottomLeft: 15, bottomRight: 15, topLeft: 15, topRight: 15);
+      },
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  Widget _buildStaffItem(THPreSelectedTableRows item, PreSelectedStaffController controller) {
+    return Stack(
+      children: [
+        Column(
+          children: [
+            //姓名
+            Row(
+              children: [
+                MyTextView(
+                  "Staff:",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  marginRight: 3,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.name ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ),
+
+            //头像
+            Row(
+              children: [
+                MyTextView(
+                  "Avatar:",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  marginRight: 3,
+                  isFontRegular: true,
+                ),
+                MyLoadImage(
+                  item.avatar ?? "",
+                  width: 25,
+                  height: 25,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            //性别
+            Row(
+              children: [
+                MyTextView(
+                  "Gender:",
+                  marginRight: 3,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.sex ?? "-",
+                  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),
+
+            //状态
+            Row(
+              children: [
+                MyTextView(
+                  "${"Status".tr}:",
+                  marginRight: 3,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.statusShow ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            //消息
+            Row(
+              children: [
+                MyTextView(
+                  "${"Message".tr}:",
+                  marginRight: 3,
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+                MyTextView(
+                  item.message ?? "",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            Container(
+              margin: const EdgeInsets.only(top: 19),
+              width: double.infinity,
+              height: 1,
+              color: const Color(0XFFF7F7F7),
+            )
+          ],
+        ).paddingOnly(left: 19, right: 20, top: 17),
+
+        //删除按钮
+        MyButton(
+          onPressed: () {
+            FocusScope.of(context).unfocus();
+            controller.doDeleteAction(item);
+          },
+          text: "Delete".tr,
+          textColor: ColorConstants.white,
+          fontSize: 13,
+          backgroundColor: hexToColor("#DC4462"),
+          radius: 17.25,
+          padding: const EdgeInsets.only(left: 12, right: 12, top: 5, bottom: 5),
+          minWidth: 50,
+          minHeight: 35,
+        ).marginOnly(right: 17, top: 18).alignRight()
+      ],
+    );
+  }
+}

+ 207 - 0
packages/cpt_th/lib/modules/job_er/job_list_er/widget/pre_selected_staff_controller.dart

@@ -0,0 +1,207 @@
+import 'package:domain/entity/response/t_h_pre_selected_option_entity.dart';
+import 'package:domain/entity/response/t_h_pre_selected_table_entity.dart';
+import 'package:domain/repository/th_er_repository.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/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/event_bus.dart';
+import 'package:widgets/dialog/app_default_dialog.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'pre_add_staff.dart';
+
+class PreSelectedStaffController extends GetxController with DioCancelableMixin {
+  final THERRepository _erRepository = Get.find();
+
+  String? jobId;
+  String? requestId;
+  var _curPage = 1;
+  var _needShowPlaceholder = true;
+
+  //页面PlaceHolder的展示
+  LoadState loadingState = LoadState.State_Success;
+  String? errorMessage;
+
+  List<THPreSelectedTableRows> datas = [];
+  THPreSelectedOptionEntity? indexOptions;
+
+  //刷新页面状态
+  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();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取列表数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    // 并发执行两个请求
+    var futures = [
+      _erRepository.fetchPreSelectedTable(
+        jobId: jobId,
+        requestId: requestId,
+        curPage: _curPage,
+        cancelToken: cancelToken,
+      ),
+      indexOptions == null
+          ? _erRepository.fetchPreSelectedOption(
+              jobId: jobId,
+              requestId: requestId,
+              cancelToken: cancelToken,
+            )
+          : Future(() => HttpResult(isSuccess: true).convert(data: indexOptions!)),
+    ];
+
+    //拿到结果
+    var results = await Future.wait(futures);
+    var listResult = results[0] as HttpResult<THPreSelectedTableEntity>;
+    var optionResult = results[1] as HttpResult<THPreSelectedOptionEntity>;
+
+    //选项数据
+    if (indexOptions == null && optionResult.isSuccess) {
+      indexOptions = optionResult.data!;
+    }
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<THPreSelectedTableRows>? 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);
+      }
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchList();
+  }
+
+  @override
+  void onClose() {
+    datas.clear();
+    super.onClose();
+  }
+
+  // 展示添加员工的弹窗
+  void showAddStaffDialog() {
+    DialogEngine.show(
+      widget: PreAddStaff(
+        jobId: jobId,
+        requestId: requestId,
+        confirmAction: (selectedIds) {
+          //调用接口添加员工
+          _requestAddStaff2Pre(selectedIds);
+        },
+      ),
+    );
+  }
+
+  //从预选列表中删除指定的员工
+  void doDeleteAction(THPreSelectedTableRows item) {
+    DialogEngine.show(
+        widget: AppDefaultDialog(
+      title: "Confirmation".tr,
+      message: "Are you sure you want to remove this employee from the pre-selected list?".tr,
+      confirmAction: () {
+        _requestDeleteStaff(item.id);
+      },
+    ));
+  }
+
+  //网络请求-删除员工
+  void _requestDeleteStaff(String? staffId) async {
+    var result = await _erRepository.deleteStaffFormPreSelected(selectedId: staffId, cancelToken: cancelToken);
+
+    //处理数据
+    if (result.isSuccess) {
+      datas.removeWhere((element) => element.id == staffId);
+      update();
+
+      //刷新指定JobId 的 JobList 列表
+      bus.emit(AppConstant.eventLabourRequestRefresh, jobId);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  //网络请求-添加员工
+  void _requestAddStaff2Pre(String selectedIds) async {
+    var result = await _erRepository.submitStaff2PreSelected(jobId: jobId, requestId: requestId, staffIds: selectedIds, cancelToken: cancelToken);
+
+    //处理数据
+    if (result.isSuccess) {
+      refreshController.callRefresh();
+
+      //刷新指定JobId 的 JobList 列表
+      bus.emit(AppConstant.eventLabourRequestRefresh, jobId);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+}

+ 22 - 15
packages/cpt_th/lib/modules/labour/labour_request_list/labour_request_item.dart

@@ -23,6 +23,7 @@ class LabourRequestItem extends StatelessWidget {
   final VoidCallback? onEditAction;
   final VoidCallback? onDeleteAction;
   final VoidCallback? onAttAction;
+  final VoidCallback? onPreSelectedAction;
 
   LabourRequestItem({
     required this.index,
@@ -34,12 +35,13 @@ class LabourRequestItem extends StatelessWidget {
     this.onEditAction,
     this.onDeleteAction,
     this.onAttAction,
+    this.onPreSelectedAction,
   });
 
   @override
   Widget build(BuildContext context) {
     return Container(
-      padding: const EdgeInsets.symmetric(vertical: 23, horizontal: 21),
+      padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 21),
       margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
       decoration: BoxDecoration(
         color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
@@ -84,7 +86,7 @@ class LabourRequestItem extends StatelessWidget {
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 13),
+          ).marginOnly(top: 6),
 
           // 工作日期时间
           Row(
@@ -107,7 +109,7 @@ class LabourRequestItem extends StatelessWidget {
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 13),
+          ).marginOnly(top: 6),
 
           // 人数
           Row(
@@ -141,7 +143,7 @@ class LabourRequestItem extends StatelessWidget {
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 13),
+          ).marginOnly(top: 6),
 
           // 预选人数
           Row(
@@ -160,11 +162,16 @@ class LabourRequestItem extends StatelessWidget {
                 item.preNum.toString(),
                 marginLeft: 5,
                 isFontRegular: true,
-                textColor: Colors.white,
+                textColor: ColorConstants.textYellowFFBB1B,
+                textDecoration: TextDecoration.underline,
+                decorationColor: ColorConstants.textYellowFFBB1B,
+                decorationThickness: 2.0,
+                decorationStyle: TextDecorationStyle.solid,
+                onClick: onPreSelectedAction,
                 fontSize: 14,
               ).expanded(),
             ],
-          ).marginOnly(top: 13),
+          ).marginOnly(top: 6),
 
           // 最后操作人员
           Row(
@@ -195,7 +202,7 @@ class LabourRequestItem extends StatelessWidget {
                 },
               ).expanded(),
             ],
-          ).marginOnly(top: 5),
+          ),
 
           // 状态
           Row(
@@ -238,7 +245,7 @@ class LabourRequestItem extends StatelessWidget {
                 ],
               ).expanded(),
             ],
-          ).marginOnly(top: 0),
+          ),
 
           //按钮组
           Visibility(
@@ -260,7 +267,7 @@ class LabourRequestItem extends StatelessWidget {
                     textColor: ColorConstants.white,
                     backgroundColor: hexToColor("#56AAFF"),
                     radius: 17.25,
-                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    padding: const EdgeInsets.symmetric(horizontal: 8),
                     minWidth: 50,
                     minHeight: 35,
                   ).marginOnly(left: 10),
@@ -277,7 +284,7 @@ class LabourRequestItem extends StatelessWidget {
                     textColor: ColorConstants.white,
                     backgroundColor: hexToColor("#56AAFF"),
                     radius: 17.25,
-                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    padding: const EdgeInsets.symmetric(horizontal: 8),
                     minWidth: 50,
                     minHeight: 35,
                   ).marginOnly(left: 10),
@@ -295,7 +302,7 @@ class LabourRequestItem extends StatelessWidget {
                     textColor: ColorConstants.white,
                     backgroundColor: hexToColor("#CA28E4"),
                     radius: 17.25,
-                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    padding: const EdgeInsets.symmetric(horizontal: 8),
                     minWidth: 50,
                     minHeight: 35,
                   ).marginOnly(left: 10),
@@ -313,7 +320,7 @@ class LabourRequestItem extends StatelessWidget {
                     textColor: ColorConstants.white,
                     backgroundColor: hexToColor("#FFBB1B"),
                     radius: 17.25,
-                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    padding: const EdgeInsets.symmetric(horizontal: 8),
                     minWidth: 50,
                     minHeight: 35,
                   ).marginOnly(left: 10),
@@ -331,7 +338,7 @@ class LabourRequestItem extends StatelessWidget {
                     textColor: ColorConstants.white,
                     backgroundColor: hexToColor("#FFBB1B"),
                     radius: 17.25,
-                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    padding: const EdgeInsets.symmetric(horizontal: 8),
                     minWidth: 50,
                     minHeight: 35,
                   ).marginOnly(left: 10),
@@ -349,13 +356,13 @@ class LabourRequestItem extends StatelessWidget {
                     textColor: ColorConstants.white,
                     backgroundColor: hexToColor("#0AC074"),
                     radius: 17.25,
-                    padding: const EdgeInsets.symmetric(horizontal: 10),
+                    padding: const EdgeInsets.symmetric(horizontal: 8),
                     minWidth: 50,
                     minHeight: 35,
                   ).marginOnly(left: 10),
                 ),
               ],
-            ).marginOnly(top: 18, bottom: 2),
+            ).marginOnly(top: 6, bottom: 2),
           ),
         ],
       ),

+ 12 - 0
packages/cpt_th/lib/modules/labour/labour_request_list/labour_request_list_controller.dart

@@ -2,6 +2,7 @@ import 'package:domain/entity/response/t_h_o_a_labour_table_entity.dart';
 import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 
+import '../../job_er/job_list_er/widget/pre_selected_staff.dart';
 import '../labour_request_add/labour_request_add_page.dart';
 import 'package:domain/entity/response/labour_request_index_entity.dart';
 import 'package:domain/repository/th_oa_repository.dart';
@@ -343,4 +344,15 @@ class LabourRequestListController extends GetxController with DioCancelableMixin
       ),
     );
   }
+
+  // 预选的弹窗
+  void doPreSelectedAction(THOALabourTableRows data) {
+    DialogEngine.show(
+      widget: PreSelectedStaff(
+        requestId: data.id,
+        jobStatus: data.status??0,
+      ),
+    );
+  }
+
 }

+ 3 - 0
packages/cpt_th/lib/modules/labour/labour_request_list/labour_request_list_page.dart

@@ -158,6 +158,9 @@ class _LabourRequestListState extends BaseState<LabourRequestListPage, LabourReq
                           onDeleteAction: (){
                             controller.doDeleteAction(state.datas[index].id!, index);
                           },
+                          onPreSelectedAction: (){
+                            controller.doPreSelectedAction(state.datas[index]);
+                          },
                         );
                       },
                       childCount: state.datas.length,

+ 16 - 1
packages/cs_domain/lib/constants/api_constants.dart

@@ -2,7 +2,7 @@
 
 class ApiConstants {
   //当前服务器环境
-  static const isServerRelease = true;
+  static const isServerRelease = false;
 
   //新加坡的域名
   static const sgBaseUrl = isServerRelease ? 'https://casualabour.com/' : 'http://singapore-dev.casualabour.com';
@@ -592,6 +592,21 @@ class ApiConstants {
   // 工作已申请员工列表-评价员工的提交
   static const apiERAppliedStaffStateWorkflowTH = "/index.php/api/er/applied/view-status";
 
+  // 预选员工选项
+  static const apiERPreSelectOptionTH = "/index.php/api/er/selected/index";
+
+  // 预选员工列表
+  static const apiERPreSelectTableTH = "/index.php/api/er/selected/table";
+
+  // 预选员工-员工列表
+  static const apiERPreSelectStaffTableTH = "/index.php/api/er/selected/staff";
+
+  //预选员工-添加员工
+  static const apiERPreSelectAddEmployeeTH = "/index.php/api/er/selected/staff-submit";
+
+  //预选员工-删除员工
+  static const apiERPreSelectDeleteEmployeeTH = "/index.php/api/er/selected/destroy";
+
   // OA 用工请求的选项
   static const apiOALabourRequestOptionTH = "/index.php/api/oa/lab-req/index";
 

+ 28 - 0
packages/cs_domain/lib/entity/response/t_h_pre_selected_option_entity.dart

@@ -0,0 +1,28 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/t_h_pre_selected_option_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/t_h_pre_selected_option_entity.g.dart';
+
+@JsonSerializable()
+class THPreSelectedOptionEntity {
+	@JSONField(name: "job_id")
+	String? jobId;
+	@JSONField(name: "request_id")
+	String? requestId;
+	@JSONField(name: "job_title")
+	String? jobTitle;
+	@JSONField(name: "job_date")
+	String? jobDate;
+	String? action;
+
+	THPreSelectedOptionEntity();
+
+	factory THPreSelectedOptionEntity.fromJson(Map<String, dynamic> json) => $THPreSelectedOptionEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $THPreSelectedOptionEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

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

@@ -0,0 +1,46 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/t_h_pre_selected_staff_table_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/t_h_pre_selected_staff_table_entity.g.dart';
+
+@JsonSerializable()
+class THPreSelectedStaffTableEntity {
+	int total = 0;
+	List<THPreSelectedStaffTableRows> rows = [];
+
+	THPreSelectedStaffTableEntity();
+
+	factory THPreSelectedStaffTableEntity.fromJson(Map<String, dynamic> json) => $THPreSelectedStaffTableEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $THPreSelectedStaffTableEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class THPreSelectedStaffTableRows {
+	String? id;
+	String? name;
+	String? gender;
+	String? mobile;
+	String? nric;
+	@JSONField(name: "profile_picture")
+	String? profilePicture;
+	int status = 0;
+	@JSONField(name: "apply_state")
+	int applyState = 0;
+
+	THPreSelectedStaffTableRows();
+
+	factory THPreSelectedStaffTableRows.fromJson(Map<String, dynamic> json) => $THPreSelectedStaffTableRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $THPreSelectedStaffTableRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

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

@@ -0,0 +1,44 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/t_h_pre_selected_table_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/t_h_pre_selected_table_entity.g.dart';
+
+@JsonSerializable()
+class THPreSelectedTableEntity {
+	int total = 0;
+	List<THPreSelectedTableRows> rows = [];
+
+	THPreSelectedTableEntity();
+
+	factory THPreSelectedTableEntity.fromJson(Map<String, dynamic> json) => $THPreSelectedTableEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $THPreSelectedTableEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class THPreSelectedTableRows {
+	String? id;
+	@JSONField(name: "status_show")
+	String? statusShow;
+	String? message;
+	String? name;
+	String? sex;
+	String? nric;
+	String? avatar;
+
+	THPreSelectedTableRows();
+
+	factory THPreSelectedTableRows.fromJson(Map<String, dynamic> json) => $THPreSelectedTableRowsFromJson(json);
+
+	Map<String, dynamic> toJson() => $THPreSelectedTableRowsToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 23 - 0
packages/cs_domain/lib/generated/json/base/json_convert_content.dart

@@ -95,6 +95,9 @@ import 'package:domain/entity/response/t_h_o_a_attachment_entity.dart';
 import 'package:domain/entity/response/t_h_o_a_labour_detail_entity.dart';
 import 'package:domain/entity/response/t_h_o_a_labour_review_table_entity.dart';
 import 'package:domain/entity/response/t_h_o_a_labour_table_entity.dart';
+import 'package:domain/entity/response/t_h_pre_selected_option_entity.dart';
+import 'package:domain/entity/response/t_h_pre_selected_staff_table_entity.dart';
+import 'package:domain/entity/response/t_h_pre_selected_table_entity.dart';
 import 'package:domain/entity/response/t_h_upload_file_entity.dart';
 import 'package:domain/entity/response/u_k_attendance_entity.dart';
 import 'package:domain/entity/response/u_k_report_attendance_entity.dart';
@@ -810,6 +813,21 @@ class JsonConvert {
     if (<THOALabourTableRows>[] is M) {
       return data.map<THOALabourTableRows>((Map<String, dynamic> e) => THOALabourTableRows.fromJson(e)).toList() as M;
     }
+    if (<THPreSelectedOptionEntity>[] is M) {
+      return data.map<THPreSelectedOptionEntity>((Map<String, dynamic> e) => THPreSelectedOptionEntity.fromJson(e)).toList() as M;
+    }
+    if (<THPreSelectedStaffTableEntity>[] is M) {
+      return data.map<THPreSelectedStaffTableEntity>((Map<String, dynamic> e) => THPreSelectedStaffTableEntity.fromJson(e)).toList() as M;
+    }
+    if (<THPreSelectedStaffTableRows>[] is M) {
+      return data.map<THPreSelectedStaffTableRows>((Map<String, dynamic> e) => THPreSelectedStaffTableRows.fromJson(e)).toList() as M;
+    }
+    if (<THPreSelectedTableEntity>[] is M) {
+      return data.map<THPreSelectedTableEntity>((Map<String, dynamic> e) => THPreSelectedTableEntity.fromJson(e)).toList() as M;
+    }
+    if (<THPreSelectedTableRows>[] is M) {
+      return data.map<THPreSelectedTableRows>((Map<String, dynamic> e) => THPreSelectedTableRows.fromJson(e)).toList() as M;
+    }
     if (<THUploadFileEntity>[] is M) {
       return data.map<THUploadFileEntity>((Map<String, dynamic> e) => THUploadFileEntity.fromJson(e)).toList() as M;
     }
@@ -1081,6 +1099,11 @@ class JsonConvertClassCollection {
     (THOALabourReviewTableRows).toString(): THOALabourReviewTableRows.fromJson,
     (THOALabourTableEntity).toString(): THOALabourTableEntity.fromJson,
     (THOALabourTableRows).toString(): THOALabourTableRows.fromJson,
+    (THPreSelectedOptionEntity).toString(): THPreSelectedOptionEntity.fromJson,
+    (THPreSelectedStaffTableEntity).toString(): THPreSelectedStaffTableEntity.fromJson,
+    (THPreSelectedStaffTableRows).toString(): THPreSelectedStaffTableRows.fromJson,
+    (THPreSelectedTableEntity).toString(): THPreSelectedTableEntity.fromJson,
+    (THPreSelectedTableRows).toString(): THPreSelectedTableRows.fromJson,
     (THUploadFileEntity).toString(): THUploadFileEntity.fromJson,
     (UKAttendanceEntity).toString(): UKAttendanceEntity.fromJson,
     (UKAttendanceRows).toString(): UKAttendanceRows.fromJson,

+ 54 - 0
packages/cs_domain/lib/generated/json/t_h_pre_selected_option_entity.g.dart

@@ -0,0 +1,54 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/response/t_h_pre_selected_option_entity.dart';
+
+THPreSelectedOptionEntity $THPreSelectedOptionEntityFromJson(Map<String, dynamic> json) {
+  final THPreSelectedOptionEntity tHPreSelectedOptionEntity = THPreSelectedOptionEntity();
+  final String? jobId = jsonConvert.convert<String>(json['job_id']);
+  if (jobId != null) {
+    tHPreSelectedOptionEntity.jobId = jobId;
+  }
+  final String? requestId = jsonConvert.convert<String>(json['request_id']);
+  if (requestId != null) {
+    tHPreSelectedOptionEntity.requestId = requestId;
+  }
+  final String? jobTitle = jsonConvert.convert<String>(json['job_title']);
+  if (jobTitle != null) {
+    tHPreSelectedOptionEntity.jobTitle = jobTitle;
+  }
+  final String? jobDate = jsonConvert.convert<String>(json['job_date']);
+  if (jobDate != null) {
+    tHPreSelectedOptionEntity.jobDate = jobDate;
+  }
+  final String? action = jsonConvert.convert<String>(json['action']);
+  if (action != null) {
+    tHPreSelectedOptionEntity.action = action;
+  }
+  return tHPreSelectedOptionEntity;
+}
+
+Map<String, dynamic> $THPreSelectedOptionEntityToJson(THPreSelectedOptionEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['job_id'] = entity.jobId;
+  data['request_id'] = entity.requestId;
+  data['job_title'] = entity.jobTitle;
+  data['job_date'] = entity.jobDate;
+  data['action'] = entity.action;
+  return data;
+}
+
+extension THPreSelectedOptionEntityExtension on THPreSelectedOptionEntity {
+  THPreSelectedOptionEntity copyWith({
+    String? jobId,
+    String? requestId,
+    String? jobTitle,
+    String? jobDate,
+    String? action,
+  }) {
+    return THPreSelectedOptionEntity()
+      ..jobId = jobId ?? this.jobId
+      ..requestId = requestId ?? this.requestId
+      ..jobTitle = jobTitle ?? this.jobTitle
+      ..jobDate = jobDate ?? this.jobDate
+      ..action = action ?? this.action;
+  }
+}

+ 107 - 0
packages/cs_domain/lib/generated/json/t_h_pre_selected_staff_table_entity.g.dart

@@ -0,0 +1,107 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/response/t_h_pre_selected_staff_table_entity.dart';
+
+THPreSelectedStaffTableEntity $THPreSelectedStaffTableEntityFromJson(Map<String, dynamic> json) {
+  final THPreSelectedStaffTableEntity tHPreSelectedStaffTableEntity = THPreSelectedStaffTableEntity();
+  final int? total = jsonConvert.convert<int>(json['total']);
+  if (total != null) {
+    tHPreSelectedStaffTableEntity.total = total;
+  }
+  final List<THPreSelectedStaffTableRows>? rows = (json['rows'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<THPreSelectedStaffTableRows>(e) as THPreSelectedStaffTableRows).toList();
+  if (rows != null) {
+    tHPreSelectedStaffTableEntity.rows = rows;
+  }
+  return tHPreSelectedStaffTableEntity;
+}
+
+Map<String, dynamic> $THPreSelectedStaffTableEntityToJson(THPreSelectedStaffTableEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['total'] = entity.total;
+  data['rows'] = entity.rows.map((v) => v.toJson()).toList();
+  return data;
+}
+
+extension THPreSelectedStaffTableEntityExtension on THPreSelectedStaffTableEntity {
+  THPreSelectedStaffTableEntity copyWith({
+    int? total,
+    List<THPreSelectedStaffTableRows>? rows,
+  }) {
+    return THPreSelectedStaffTableEntity()
+      ..total = total ?? this.total
+      ..rows = rows ?? this.rows;
+  }
+}
+
+THPreSelectedStaffTableRows $THPreSelectedStaffTableRowsFromJson(Map<String, dynamic> json) {
+  final THPreSelectedStaffTableRows tHPreSelectedStaffTableRows = THPreSelectedStaffTableRows();
+  final String? id = jsonConvert.convert<String>(json['id']);
+  if (id != null) {
+    tHPreSelectedStaffTableRows.id = id;
+  }
+  final String? name = jsonConvert.convert<String>(json['name']);
+  if (name != null) {
+    tHPreSelectedStaffTableRows.name = name;
+  }
+  final String? gender = jsonConvert.convert<String>(json['gender']);
+  if (gender != null) {
+    tHPreSelectedStaffTableRows.gender = gender;
+  }
+  final String? mobile = jsonConvert.convert<String>(json['mobile']);
+  if (mobile != null) {
+    tHPreSelectedStaffTableRows.mobile = mobile;
+  }
+  final String? nric = jsonConvert.convert<String>(json['nric']);
+  if (nric != null) {
+    tHPreSelectedStaffTableRows.nric = nric;
+  }
+  final String? profilePicture = jsonConvert.convert<String>(json['profile_picture']);
+  if (profilePicture != null) {
+    tHPreSelectedStaffTableRows.profilePicture = profilePicture;
+  }
+  final int? status = jsonConvert.convert<int>(json['status']);
+  if (status != null) {
+    tHPreSelectedStaffTableRows.status = status;
+  }
+  final int? applyState = jsonConvert.convert<int>(json['apply_state']);
+  if (applyState != null) {
+    tHPreSelectedStaffTableRows.applyState = applyState;
+  }
+  return tHPreSelectedStaffTableRows;
+}
+
+Map<String, dynamic> $THPreSelectedStaffTableRowsToJson(THPreSelectedStaffTableRows entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['id'] = entity.id;
+  data['name'] = entity.name;
+  data['gender'] = entity.gender;
+  data['mobile'] = entity.mobile;
+  data['nric'] = entity.nric;
+  data['profile_picture'] = entity.profilePicture;
+  data['status'] = entity.status;
+  data['apply_state'] = entity.applyState;
+  return data;
+}
+
+extension THPreSelectedStaffTableRowsExtension on THPreSelectedStaffTableRows {
+  THPreSelectedStaffTableRows copyWith({
+    String? id,
+    String? name,
+    String? gender,
+    String? mobile,
+    String? nric,
+    String? profilePicture,
+    int? status,
+    int? applyState,
+  }) {
+    return THPreSelectedStaffTableRows()
+      ..id = id ?? this.id
+      ..name = name ?? this.name
+      ..gender = gender ?? this.gender
+      ..mobile = mobile ?? this.mobile
+      ..nric = nric ?? this.nric
+      ..profilePicture = profilePicture ?? this.profilePicture
+      ..status = status ?? this.status
+      ..applyState = applyState ?? this.applyState;
+  }
+}

+ 100 - 0
packages/cs_domain/lib/generated/json/t_h_pre_selected_table_entity.g.dart

@@ -0,0 +1,100 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/response/t_h_pre_selected_table_entity.dart';
+
+THPreSelectedTableEntity $THPreSelectedTableEntityFromJson(Map<String, dynamic> json) {
+  final THPreSelectedTableEntity tHPreSelectedTableEntity = THPreSelectedTableEntity();
+  final int? total = jsonConvert.convert<int>(json['total']);
+  if (total != null) {
+    tHPreSelectedTableEntity.total = total;
+  }
+  final List<THPreSelectedTableRows>? rows = (json['rows'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<THPreSelectedTableRows>(e) as THPreSelectedTableRows).toList();
+  if (rows != null) {
+    tHPreSelectedTableEntity.rows = rows;
+  }
+  return tHPreSelectedTableEntity;
+}
+
+Map<String, dynamic> $THPreSelectedTableEntityToJson(THPreSelectedTableEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['total'] = entity.total;
+  data['rows'] = entity.rows.map((v) => v.toJson()).toList();
+  return data;
+}
+
+extension THPreSelectedTableEntityExtension on THPreSelectedTableEntity {
+  THPreSelectedTableEntity copyWith({
+    int? total,
+    List<THPreSelectedTableRows>? rows,
+  }) {
+    return THPreSelectedTableEntity()
+      ..total = total ?? this.total
+      ..rows = rows ?? this.rows;
+  }
+}
+
+THPreSelectedTableRows $THPreSelectedTableRowsFromJson(Map<String, dynamic> json) {
+  final THPreSelectedTableRows tHPreSelectedTableRows = THPreSelectedTableRows();
+  final String? id = jsonConvert.convert<String>(json['id']);
+  if (id != null) {
+    tHPreSelectedTableRows.id = id;
+  }
+  final String? statusShow = jsonConvert.convert<String>(json['status_show']);
+  if (statusShow != null) {
+    tHPreSelectedTableRows.statusShow = statusShow;
+  }
+  final String? message = jsonConvert.convert<String>(json['message']);
+  if (message != null) {
+    tHPreSelectedTableRows.message = message;
+  }
+  final String? name = jsonConvert.convert<String>(json['name']);
+  if (name != null) {
+    tHPreSelectedTableRows.name = name;
+  }
+  final String? sex = jsonConvert.convert<String>(json['sex']);
+  if (sex != null) {
+    tHPreSelectedTableRows.sex = sex;
+  }
+  final String? nric = jsonConvert.convert<String>(json['nric']);
+  if (nric != null) {
+    tHPreSelectedTableRows.nric = nric;
+  }
+  final String? avatar = jsonConvert.convert<String>(json['avatar']);
+  if (avatar != null) {
+    tHPreSelectedTableRows.avatar = avatar;
+  }
+  return tHPreSelectedTableRows;
+}
+
+Map<String, dynamic> $THPreSelectedTableRowsToJson(THPreSelectedTableRows entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['id'] = entity.id;
+  data['status_show'] = entity.statusShow;
+  data['message'] = entity.message;
+  data['name'] = entity.name;
+  data['sex'] = entity.sex;
+  data['nric'] = entity.nric;
+  data['avatar'] = entity.avatar;
+  return data;
+}
+
+extension THPreSelectedTableRowsExtension on THPreSelectedTableRows {
+  THPreSelectedTableRows copyWith({
+    String? id,
+    String? statusShow,
+    String? message,
+    String? name,
+    String? sex,
+    String? nric,
+    String? avatar,
+  }) {
+    return THPreSelectedTableRows()
+      ..id = id ?? this.id
+      ..statusShow = statusShow ?? this.statusShow
+      ..message = message ?? this.message
+      ..name = name ?? this.name
+      ..sex = sex ?? this.sex
+      ..nric = nric ?? this.nric
+      ..avatar = avatar ?? this.avatar;
+  }
+}

+ 159 - 0
packages/cs_domain/lib/repository/th_er_repository.dart

@@ -25,6 +25,9 @@ import '../entity/response/staff_labour_history_entity.dart';
 import '../entity/response/staff_remark_history_entity.dart';
 import '../entity/response/t_h_employee_detail_entity.dart';
 import '../entity/response/t_h_employee_remarks_entity.dart';
+import '../entity/response/t_h_pre_selected_option_entity.dart';
+import '../entity/response/t_h_pre_selected_staff_table_entity.dart';
+import '../entity/response/t_h_pre_selected_table_entity.dart';
 
 /// 泰国的 ER 的数据仓库
 class THERRepository extends GetxService {
@@ -798,4 +801,160 @@ class THERRepository extends GetxService {
     }
     return result.convert();
   }
+
+  // 预选员工选项
+  Future<HttpResult<THPreSelectedOptionEntity>> fetchPreSelectedOption({
+    String? requestId,
+    String? jobId,
+    CancelToken? cancelToken,
+  }) async {
+    //参数
+    Map<String, String> params = {};
+    if (!Utils.isEmpty(requestId)) {
+      params["request_id"] = requestId!;
+    }
+    if (!Utils.isEmpty(jobId)) {
+      params["job_id"] = jobId!;
+    }
+
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiERPreSelectOptionTH,
+      params: params,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = THPreSelectedOptionEntity.fromJson(json!);
+      return result.convert<THPreSelectedOptionEntity>(data: data);
+    }
+    return result.convert();
+  }
+
+  // 预选员工列表
+  Future<HttpResult<THPreSelectedTableEntity>> fetchPreSelectedTable({
+    String? requestId,
+    String? jobId,
+    required int curPage,
+    CancelToken? cancelToken,
+  }) async {
+    //参数
+    Map<String, String> params = {};
+    if (!Utils.isEmpty(requestId)) {
+      params["request_id"] = requestId!;
+    }
+    if (!Utils.isEmpty(jobId)) {
+      params["job_id"] = jobId!;
+    }
+    params["cur_page"] = curPage.toString();
+    params["page_size"] = "10";
+
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiERPreSelectTableTH,
+      params: params,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = THPreSelectedTableEntity.fromJson(json!);
+      return result.convert<THPreSelectedTableEntity>(data: data);
+    }
+    return result.convert();
+  }
+
+  // 预选员工-员工列表
+  Future<HttpResult<THPreSelectedStaffTableEntity>> fetchPreSelectedStaffTable({
+    String? requestId,
+    String? jobId,
+    String? keyword,
+    required int curPage,
+    CancelToken? cancelToken,
+  }) async {
+    //参数
+    Map<String, String> params = {};
+    if (!Utils.isEmpty(requestId)) {
+      params["request_id"] = requestId!;
+    }
+    if (!Utils.isEmpty(jobId)) {
+      params["job_id"] = jobId!;
+    }
+    if (!Utils.isEmpty(keyword)) {
+      params["keyword"] = keyword!;
+    }
+    params["cur_page"] = curPage.toString();
+    params["page_size"] = "10";
+
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiERPreSelectStaffTableTH,
+      params: params,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = THPreSelectedStaffTableEntity.fromJson(json!);
+      return result.convert<THPreSelectedStaffTableEntity>(data: data);
+    }
+    return result.convert();
+  }
+
+  //预选添加员工
+  Future<HttpResult> submitStaff2PreSelected({
+    String? requestId,
+    String? jobId,
+    String? staffIds,
+    CancelToken? cancelToken,
+  }) async {
+    //参数
+    Map<String, dynamic> params = {};
+    if (!Utils.isEmpty(requestId)) {
+      params["request_id"] = requestId!;
+    }
+    if (!Utils.isEmpty(jobId)) {
+      params["job_id"] = jobId!;
+    }
+    if (!Utils.isEmpty(staffIds)) {
+      params["staff_ids"] = staffIds!;
+    }
+
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiERPreSelectAddEmployeeTH,
+      isShowLoadingDialog: true,
+      method: HttpMethod.POST,
+      params: params,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
+
+  //预选删除员工
+  Future<HttpResult> deleteStaffFormPreSelected({
+    String? selectedId,
+    CancelToken? cancelToken,
+  }) async {
+    //参数
+    Map<String, dynamic> params = {};
+    if (!Utils.isEmpty(selectedId)) {
+      params["selected_id"] = selectedId!;
+    }
+
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiERPreSelectDeleteEmployeeTH,
+      isShowLoadingDialog: true,
+      method: HttpMethod.POST,
+      params: params,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
+
 }

+ 3 - 0
packages/cs_resources/lib/local/language/en_US.dart

@@ -317,7 +317,10 @@ const Map<String, String> en_US = {
   'Choose Attachment': 'Choose Attachment',
   'Add File': 'Add File',
   'Url': 'Url',
+  'Add': 'Add',
   'Avatar': 'Avatar',
+  'Pre-selected Staff': 'Pre-selected Staff',
+  'Are you sure you want to remove this employee from the pre-selected list?': 'Are you sure you want to remove this employee from the pre-selected list?',
 
   //插件的国际化
   'Pull to refresh': 'Pull to refresh',

+ 3 - 0
packages/cs_resources/lib/local/language/th_TH.dart

@@ -317,7 +317,10 @@ const Map<String, String> th_TH = {
   'Choose Attachment': 'เลือกไฟล์แนบ',
   'Add File': 'เพิ่มไฟล์',
   'Url': 'ลิงก์',
+  'Add': 'เพิ่ม',
   'Avatar': 'อวาตาร์',
+  'Pre-selected Staff': 'การคัดเลือกพนักงานล่วงหน้า',
+  'Are you sure you want to remove this employee from the pre-selected list?': 'คุณแน่ใจว่าต้องการลบพนักงานคนนี้ออกจากรายการคัดเลือก?',
 
   // การแปลของปลั๊กอิน
   'Pull to refresh': 'ดึงเพื่อรีเฟรช',

+ 3 - 0
packages/cs_resources/lib/local/language/zh_CN.dart

@@ -317,7 +317,10 @@ const Map<String, String> zh_CN = {
   'Choose Attachment': '选择附件',
   'Add File': '添加文件',
   'Url': '链接',
+  'Add': '添加',
   'Avatar': '头像',
+  'Pre-selected Staff': '预选员工',
+  'Are you sure you want to remove this employee from the pre-selected list?': '你确定你想要从预选列表中删除此员工吗?',
 
   //插件的国际化
   'Pull to refresh': '下拉刷新',