Sfoglia il codice sorgente

UK的一些模板与页面的添加

liukai 1 settimana fa
parent
commit
90b1addb47
100 ha cambiato i file con 15585 aggiunte e 56 eliminazioni
  1. 9 13
      packages/cpt_auth/lib/modules/login/login_controller.dart
  2. 6 0
      packages/cpt_auth/lib/router/auth_service_impl.dart
  3. 4 4
      packages/cpt_job_sg/lib/modules/revise_list/revise_list_item.dart
  4. 1 1
      packages/cpt_job_sg/lib/modules/revise_list/revise_list_page.dart
  5. 0 0
      packages/cpt_uk/lib/modules/attendance/attendance_export.dart
  6. 132 0
      packages/cpt_uk/lib/modules/attendance/device_list/device_list_controller.dart
  7. 155 0
      packages/cpt_uk/lib/modules/attendance/device_list/device_list_item.dart
  8. 206 0
      packages/cpt_uk/lib/modules/attendance/device_list/device_list_page.dart
  9. 10 0
      packages/cpt_uk/lib/modules/attendance/device_list/device_list_state.dart
  10. 197 0
      packages/cpt_uk/lib/modules/attendance/e_attendance_list/e_attendance_list_controller.dart
  11. 133 0
      packages/cpt_uk/lib/modules/attendance/e_attendance_list/e_attendance_list_page.dart
  12. 16 0
      packages/cpt_uk/lib/modules/attendance/e_attendance_list/e_attendance_list_state.dart
  13. 343 0
      packages/cpt_uk/lib/modules/attendance/e_attendance_list/item_e_attendance.dart
  14. 160 0
      packages/cpt_uk/lib/modules/attendance/e_attendance_list/widget/attendance_sign_in_out.dart
  15. 356 0
      packages/cpt_uk/lib/modules/attendance/e_attendance_list/widget/job_list_filter.dart
  16. 327 0
      packages/cpt_uk/lib/modules/attendance/security_registration/item_security_registration.dart
  17. 141 0
      packages/cpt_uk/lib/modules/attendance/security_registration/security_registration_controller.dart
  18. 136 0
      packages/cpt_uk/lib/modules/attendance/security_registration/security_registration_page.dart
  19. 16 0
      packages/cpt_uk/lib/modules/attendance/security_registration/security_registration_state.dart
  20. 356 0
      packages/cpt_uk/lib/modules/attendance/security_registration/widget/job_list_filter.dart
  21. 430 0
      packages/cpt_uk/lib/modules/job/job_applied/applied_staff_item.dart
  22. 395 0
      packages/cpt_uk/lib/modules/job/job_applied/job_applied_controller.dart
  23. 210 0
      packages/cpt_uk/lib/modules/job/job_applied/job_applied_page.dart
  24. 14 0
      packages/cpt_uk/lib/modules/job/job_applied/job_applied_state.dart
  25. 342 0
      packages/cpt_uk/lib/modules/job/job_applied/widget/applied_add_staff.dart
  26. 134 0
      packages/cpt_uk/lib/modules/job/job_applied/widget/applied_add_staff_controller.dart
  27. 241 0
      packages/cpt_uk/lib/modules/job/job_applied/widget/applied_butch_modify.dart
  28. 313 0
      packages/cpt_uk/lib/modules/job/job_applied/widget/applied_staff_reviews.dart
  29. 178 0
      packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_controller.dart
  30. 515 0
      packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_page.dart
  31. 40 0
      packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_state.dart
  32. 158 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_controller.dart
  33. 139 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_page.dart
  34. 15 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_state.dart
  35. 296 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_detail_widget.dart
  36. 333 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_labour_history_item.dart
  37. 108 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_controller.dart
  38. 151 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_item.dart
  39. 162 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_page.dart
  40. 10 0
      packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_state.dart
  41. 98 0
      packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_controller.dart
  42. 228 0
      packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_item.dart
  43. 102 0
      packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_page.dart
  44. 10 0
      packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_state.dart
  45. 13 8
      packages/cpt_uk/lib/modules/job/job_category/job_category_controller.dart
  46. 204 0
      packages/cpt_uk/lib/modules/job/job_list/job_list_controller.dart
  47. 360 0
      packages/cpt_uk/lib/modules/job/job_list/job_list_filter.dart
  48. 210 0
      packages/cpt_uk/lib/modules/job/job_list/job_list_item.dart
  49. 143 0
      packages/cpt_uk/lib/modules/job/job_list/job_list_page.dart
  50. 18 0
      packages/cpt_uk/lib/modules/job/job_list/job_list_state.dart
  51. 42 0
      packages/cpt_uk/lib/modules/job/job_list_detail/job_list_detail_controller.dart
  52. 240 0
      packages/cpt_uk/lib/modules/job/job_list_detail/job_list_detail_page.dart
  53. 30 0
      packages/cpt_uk/lib/modules/job/job_list_detail/job_list_detail_state.dart
  54. 219 0
      packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_controller.dart
  55. 362 0
      packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_page.dart
  56. 40 0
      packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_state.dart
  57. 361 0
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_filter.dart
  58. 286 0
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_item.dart
  59. 295 0
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_controller.dart
  60. 166 0
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_page.dart
  61. 17 0
      packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_state.dart
  62. 96 0
      packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_request_workflow_controller.dart
  63. 102 0
      packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_request_workflow_page.dart
  64. 10 0
      packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_request_workflow_state.dart
  65. 230 0
      packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_workflow_item.dart
  66. 128 0
      packages/cpt_uk/lib/modules/job/template_add/template_add_controller.dart
  67. 327 0
      packages/cpt_uk/lib/modules/job/template_add/template_add_page.dart
  68. 45 0
      packages/cpt_uk/lib/modules/job/template_add/template_add_state.dart
  69. 7 0
      packages/cpt_uk/lib/modules/job/template_list/add_edit_template.dart
  70. 175 0
      packages/cpt_uk/lib/modules/job/template_list/item_template.dart
  71. 215 0
      packages/cpt_uk/lib/modules/job/template_list/template_list_controller.dart
  72. 153 0
      packages/cpt_uk/lib/modules/job/template_list/template_list_page.dart
  73. 13 0
      packages/cpt_uk/lib/modules/job/template_list/template_list_state.dart
  74. 32 29
      packages/cpt_uk/lib/modules/main/main_controller.dart
  75. 0 0
      packages/cpt_uk/lib/modules/report/report_export.dart
  76. 79 0
      packages/cpt_uk/lib/modules/report/report_list/report_list_controller.dart
  77. 55 0
      packages/cpt_uk/lib/modules/report/report_list/report_list_item.dart
  78. 95 0
      packages/cpt_uk/lib/modules/report/report_list/report_list_page.dart
  79. 20 0
      packages/cpt_uk/lib/modules/report/report_list/report_list_state.dart
  80. 249 0
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_controller.dart
  81. 329 0
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_item.dart
  82. 173 0
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_page.dart
  83. 187 0
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_reject_dialog.dart
  84. 12 0
      packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_state.dart
  85. 196 0
      packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_controller.dart
  86. 357 0
      packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_page.dart
  87. 41 0
      packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_state.dart
  88. 345 0
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_controller.dart
  89. 318 0
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_filter.dart
  90. 292 0
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_item.dart
  91. 189 0
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_page.dart
  92. 190 0
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_reject_dialog.dart
  93. 16 0
      packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_state.dart
  94. 102 0
      packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_request_workflow_page.dart
  95. 10 0
      packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_request_workflow_state.dart
  96. 96 0
      packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_review_workflow_controller.dart
  97. 228 0
      packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_review_workflow_item.dart
  98. 0 0
      packages/cpt_uk/lib/modules/review/review_export.dart
  99. 141 1
      packages/cpt_uk/lib/router/uk_router.dart
  100. 0 0
      packages/cs_domain/lib/constants/api_constants.dart

+ 9 - 13
packages/cpt_auth/lib/modules/login/login_controller.dart

@@ -63,19 +63,15 @@ class LoginController extends GetxController with DioCancelableMixin {
 
   /// 请求接口执行登录
   void _request2LoginPassword() async {
-    // var result = await authRepository.userLogin(state.code, state.password, cancelToken: cancelToken);
-    //
-    // //处理数据
-    // if (result.isSuccess) {
-    //   //保存Token,去首页
-    //   _handleLoginSuccess(result.data!);
-    // } else {
-    //   ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
-    // }
-
-    //todo 英国的假登录
-    await Future.delayed(const Duration(seconds: 2));
-    _handleLoginSuccess(HotelInfoEntity()..token = "123");
+    var result = await authRepository.userLogin(state.code, state.password, cancelToken: cancelToken);
+
+    //处理数据
+    if (result.isSuccess) {
+      //保存Token,去首页
+      _handleLoginSuccess(result.data!);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
   }
 
   /// 登录成功的统一处理 - 去首页

+ 6 - 0
packages/cpt_auth/lib/router/auth_service_impl.dart

@@ -1,6 +1,7 @@
 import 'package:cpt_auth/modules/login/login_page.dart';
 import 'package:cpt_auth/modules/main/main_page.dart';
 import 'package:cpt_auth/modules/reset_psd/reset_psd_page.dart';
+import 'package:cpt_auth/modules/setting/setting_page.dart';
 import 'package:plugin_basic/basic_export.dart';
 import 'package:router/componentRouter/auth_service.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -43,4 +44,9 @@ class AuthServiceImpl extends GetxService implements AuthService {
   void startPopAllMainPage() {
     MainPage.startWithPopAll();
   }
+
+  @override
+  void startSettingPage() {
+    SettingPage.startInstance();
+  }
 }

+ 4 - 4
packages/cpt_job_sg/lib/modules/revise_list/revise_list_item.dart

@@ -8,7 +8,7 @@ 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 {
@@ -33,10 +33,10 @@ class ReviseListItem extends StatelessWidget {
   @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),
+      padding: const EdgeInsets.symmetric(vertical: 23, horizontal: 21),
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
       decoration: BoxDecoration(
-        color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
         borderRadius: BorderRadius.circular(5), // 设置圆角
       ),
       child: Column(

+ 1 - 1
packages/cpt_job_sg/lib/modules/revise_list/revise_list_page.dart

@@ -94,7 +94,7 @@ class _JobListState extends BaseState<ReviseListPage, ReviseListController> {
                   ).marginOnly(right: 15),
 
                   //筛选图标
-                  MyAssetImage(
+                  const MyAssetImage(
                     Assets.baseServiceTitleBarFilterIcon,
                     width: 24,
                     height: 16.5,

+ 0 - 0
packages/cpt_uk/lib/modules/attendance/attendance_export.dart


+ 132 - 0
packages/cpt_uk/lib/modules/attendance/device_list/device_list_controller.dart

@@ -0,0 +1,132 @@
+import 'package:domain/entity/response/device_list_entity.dart';
+import 'package:domain/repository/other_repository.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.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 'device_list_state.dart';
+
+class DeviceListController extends GetxController with DioCancelableMixin{
+  final OtherRepository _otherRepository = Get.find();
+  final DeviceListState state = DeviceListState();
+
+  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;
+    fetchDeviceList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchDeviceList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchDeviceList();
+  }
+
+  /// 获取服务器数据,通知消息列表
+  Future fetchDeviceList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    // 获取 Applied 列表
+    var listResult = await _otherRepository.fetchDeviceList(
+      curPage: _curPage,
+      cancelToken: cancelToken,
+    );
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<DeviceListRows>? 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();
+    fetchDeviceList();
+
+  }
+
+  @override
+  void onClose() {
+    state.datas.clear();
+    super.onClose();
+  }
+
+  /// 执行搜索
+  void doSearch() {
+   String? deviceName = state.searchController.text;
+   ToastEngine.show('执行搜索:$deviceName');
+  }
+
+  /// Pick 在线状态
+  void pickOnLineStatus() {
+    ToastEngine.show('Pick 在线状态');
+  }
+
+}

+ 155 - 0
packages/cpt_uk/lib/modules/attendance/device_list/device_list_item.dart

@@ -0,0 +1,155 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/device_list_entity.dart';
+import 'package:domain/entity/response/job_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_button.dart';
+import 'package:widgets/my_text_view.dart';
+
+/**
+ * 设备列表
+ */
+class DeviceListItem extends StatelessWidget {
+  final int index;
+  final DeviceListRows item;
+
+  DeviceListItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: EdgeInsets.symmetric(vertical: 24, 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: [
+          // 设备Mac
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Device MAC:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //部门
+              MyTextView(
+                item.deviceMac ?? "-",
+                marginLeft: 5,
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ),
+
+          // 设备别名
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Device Alias:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.deviceAlias ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 位置
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Location:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+
+              MyTextView(
+                item.siteTypeShow ?? "",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Alive State:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //状态
+              MyTextView(
+                item.aliveState == 0 ? "Offline".tr : "Online".tr,
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor:  item.aliveState == 0 ? ColorConstants.textRedFF6262 : ColorConstants.textGreen0AC074,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created 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),
+
+        ],
+      ),
+    );
+  }
+}

+ 206 - 0
packages/cpt_uk/lib/modules/attendance/device_list/device_list_page.dart

@@ -0,0 +1,206 @@
+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:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/search_app_bar.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'device_list_controller.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 'device_list_item.dart';
+import 'device_list_state.dart';
+
+/*
+ * 该酒店对于的设备的列表
+ */
+class UKDeviceListPage extends BaseStatefulPage<DeviceListController> {
+  UKDeviceListPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKDeviceList);
+  }
+
+  @override
+  DeviceListController createRawController() {
+    return DeviceListController();
+  }
+
+  @override
+  State<UKDeviceListPage> createState() => _DeviceListState();
+}
+
+class _DeviceListState extends BaseState<UKDeviceListPage, DeviceListController> {
+  late DeviceListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: true,
+        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, "Device List".tr),
+
+              //搜索的条件
+              Row(
+                children: [
+                  //下拉选
+                  Container(
+                    padding: const EdgeInsets.only(left: 12, right: 10),
+                    margin: const EdgeInsets.only(right: 10),
+                    height: 40,
+                    decoration: BoxDecoration(
+                      color: const Color(0xFF4DCFF6).withOpacity(0.2),
+                      borderRadius: const BorderRadius.all(Radius.circular(20)),
+                    ),
+                    child: Row(
+                      mainAxisSize: MainAxisSize.max,
+                      crossAxisAlignment: CrossAxisAlignment.center,
+                      mainAxisAlignment: MainAxisAlignment.start,
+                      children: [
+                        MyTextView(
+                          "Online",
+                          fontSize: 14,
+                          hint: "Choose Outlet".tr,
+                          textHintColor: ColorConstants.textGrayAECAE5,
+                          textColor: ColorConstants.white,
+                        ).expanded(),
+
+                        //下拉选图标
+                        const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                      ],
+                    ),
+                  ).onTap(() {
+                    FocusScope.of(context).unfocus();
+                    controller.pickOnLineStatus();
+                  }).expanded(flex: 1),
+
+                  //搜索框
+                  Container(
+                    height: 40,
+                    margin: const EdgeInsets.only(right: 10),
+                    padding: const EdgeInsets.only(left: 12, right: 10),
+                    decoration: BoxDecoration(
+                      color: const Color(0xFF4DCFF6).withOpacity(0.2),
+                      borderRadius: const BorderRadius.all(Radius.circular(20)),
+                    ),
+                    child: Row(
+                      mainAxisSize: MainAxisSize.max,
+                      crossAxisAlignment: CrossAxisAlignment.center,
+                      children: [
+                        IgnoreKeyboardDismiss(
+                          child: TextField(
+                            cursorColor: Colors.white,
+                            cursorWidth: 1.5,
+                            autofocus: false,
+                            maxLines: 1,
+                            minLines: 1,
+                            focusNode: state.focusNode,
+                            controller: state.searchController,
+                            decoration: InputDecoration(
+                              isDense: true,
+                              //清除垂直方向的填充
+                              isCollapsed: true,
+                              //让文字垂直居中
+                              border: InputBorder.none,
+                              hintText: 'Device'.tr,
+                              hintStyle: const TextStyle(
+                                color: ColorConstants.textGrayAECAE5,
+                                fontSize: 14.0,
+                                fontWeight: FontWeight.w400,
+                              ),
+                            ),
+                            style: const TextStyle(
+                              color: ColorConstants.white,
+                              fontSize: 14.0,
+                              fontWeight: FontWeight.w400,
+                            ),
+                            // 键盘动作右下角图标
+                            textInputAction: TextInputAction.done,
+                            textAlignVertical: TextAlignVertical.center,
+                          ),
+                        ).expanded(),
+                      ],
+                    ),
+                  ).expanded(flex: 1),
+
+                  //筛选按钮
+                  MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      controller.doSearch();
+                    },
+                    text: "Filter".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+                    radius: 20,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ),
+                ],
+              ).marginOnly(top: 10, left: 15, right: 15, bottom: 5),
+
+              //底部的列表
+              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 DeviceListItem(index: index, item: state.datas[index]);
+                      },
+                      childCount: state.datas.length,
+                    ))
+                  ],
+                ),
+              ).expanded(),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}

+ 10 - 0
packages/cpt_uk/lib/modules/attendance/device_list/device_list_state.dart

@@ -0,0 +1,10 @@
+import 'package:domain/entity/response/device_list_entity.dart';
+import 'package:flutter/material.dart';
+
+class DeviceListState {
+  List<DeviceListRows> datas = [];
+
+  String? keyword; //列表数据
+  TextEditingController searchController = TextEditingController();
+  FocusNode focusNode = FocusNode();
+}

+ 197 - 0
packages/cpt_uk/lib/modules/attendance/e_attendance_list/e_attendance_list_controller.dart

@@ -0,0 +1,197 @@
+import 'dart:typed_data';
+
+import 'package:domain/entity/response/attendance_entity.dart';
+import 'package:domain/entity/response/check_success_entity.dart';
+import 'package:domain/repository/job_repository.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/service/user_service.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:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../job/job_applied_staff_detail/applied_staff_detail_page.dart';
+import 'e_attendance_list_state.dart';
+import 'widget/attendance_sign_in_out.dart';
+import 'widget/job_list_filter.dart';
+
+class EAttendanceListController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final EAttendanceListState state = EAttendanceListState();
+
+  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 {
+    fetchAttendanceList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _needShowPlaceholder = true;
+    fetchAttendanceList();
+  }
+
+  /// 获取服务器数据,成员考勤列表
+  Future fetchAttendanceList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    //获取到数据
+    var result = await _jobRepository.fetchAttendanceList(
+      state.keyword,
+      DateTimeUtils.formatDate(state.selectedStartDate, format: "yyyy-MM-dd"),
+      DateTimeUtils.formatDate(state.selectedEndDate, format: "yyyy-MM-dd"),
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      handleList(result.data?.rows);
+      refreshController.finishRefresh(IndicatorResult.success);
+    } else {
+      errorMessage = result.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+      refreshController.finishRefresh(IndicatorResult.fail);
+    }
+
+    //最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<AttendanceList>? 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);
+    }
+  }
+
+  /// 签到签出
+  void requestCheckInCheckOut(bool isCheckIn, AttendanceList item, ByteData byteData) async {
+    //请求接口
+
+    var result = await _jobRepository.submitCheckInOut(
+      item.appliedId.toString(),
+      byteData,
+      isCheckIn: isCheckIn,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      CheckSuccessEntity entity = result.data!;
+      if (isCheckIn) {
+        item.checkInImg = entity.checkImg;
+        item.checkInTime = entity.checkTime;
+      } else {
+        item.checkOutImg = entity.checkImg;
+        item.checkOutTime = entity.checkTime;
+      }
+      //更新状态
+      update();
+    } else {
+      errorMessage = result.errorMsg;
+      ToastEngine.show(errorMessage ?? "Network Load Error".tr);
+    }
+  }
+
+  //执行搜索
+  void doSearch(String keyword) {
+    state.keyword = keyword;
+    refreshController.callRefresh();
+  }
+
+  @override
+  void onReady() async {
+    super.onReady();
+    fetchAttendanceList();
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+    state.datas.clear();
+  }
+
+  /// 用户签到
+  void userSignIn(AttendanceList item) {
+    DialogEngine.show(
+      widget: AttendanceSignInOut(
+        confirmAction: (byteData) {
+          requestCheckInCheckOut(true, item, byteData);
+        },
+      ),
+    );
+  }
+
+  /// 用户签出
+  void userSignOut(AttendanceList item) {
+    DialogEngine.show(
+      widget: AttendanceSignInOut(
+        confirmAction: (byteData) {
+          requestCheckInCheckOut(false, item, byteData);
+        },
+      ),
+    );
+  }
+
+
+  /// 展示标题栏的 Filter 弹窗
+  void showFilterDialog() {
+    DialogEngine.show(
+      widget: JobListFilter(
+        selectedStartDate: state.selectedStartDate,
+        selectedEndDate: state.selectedEndDate,
+        staffName: state.selectedStaffName,
+        selectedDepartmentId: state.selectedDepartmentId,
+        onFilterAction: (startDate, endDate, staffName, departmentId) {
+          Log.d("startDate:$startDate endDate:$endDate staffName:$staffName departmentId:$departmentId");
+
+          state.selectedStartDate = startDate;
+          state.selectedEndDate = endDate;
+          state.selectedStaffName = staffName;
+          state.selectedDepartmentId = departmentId;
+
+          //赋值之后刷新
+          refreshController.callRefresh();
+        },
+      ),
+      position: DialogPosition.top,
+      animType: DialogAnimation.fade,
+    );
+  }
+
+  //查看UK员工的详情
+  void gotoStaffDetailPage(AttendanceList data) {
+    UKAppliedStaffDetailPage.startInstance(data.staffId.toString());
+  }
+
+}

+ 133 - 0
packages/cpt_uk/lib/modules/attendance/e_attendance_list/e_attendance_list_page.dart

@@ -0,0 +1,133 @@
+import 'dart:ui';
+
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:plugin_basic/base/base_state.dart';
+import 'package:plugin_basic/base/mixin_state_lifecycle.dart';
+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/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/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+import 'e_attendance_list_controller.dart';
+import 'e_attendance_list_state.dart';
+import 'item_e_attendance.dart';
+
+/*
+ * 电子考勤列表
+ */
+class UKEAttendanceListPage extends BaseStatefulPage<EAttendanceListController> {
+  UKEAttendanceListPage({super.key});
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKAttendanceList);
+  }
+
+  @override
+  State<UKEAttendanceListPage> createState() => _SignInSignOutPageState();
+
+  @override
+  EAttendanceListController createRawController() {
+    return EAttendanceListController();
+  }
+}
+
+class _SignInSignOutPageState extends BaseState<UKEAttendanceListPage, EAttendanceListController> with StateLifecycle {
+  late EAttendanceListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  void dispose() {
+    Get.delete<EAttendanceListController>();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(
+      builder: (controller) {
+        return SafeArea(
+          bottom: true,
+          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, "E-Attendance".tr, actions: [
+                  //筛选图标
+                  const MyAssetImage(
+                    Assets.baseServiceTitleBarFilterIcon,
+                    width: 24,
+                    height: 16.5,
+                  ).onTap(() {
+                    controller.showFilterDialog();
+                  }).marginOnly(right: 15),
+                ]),
+
+                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 EAttendanceItem(
+                            index: index,
+                            item: state.datas[index],
+                            onMemberAction: () {
+                              controller.gotoStaffDetailPage(state.datas[index]);
+                            },
+                          );
+                        },
+                        childCount: state.datas.length,
+                      ))
+                    ],
+                  ),
+                ).marginOnly(top: 5).expanded(),
+              ],
+            ),
+          ),
+        );
+      },
+    );
+  }
+}

+ 16 - 0
packages/cpt_uk/lib/modules/attendance/e_attendance_list/e_attendance_list_state.dart

@@ -0,0 +1,16 @@
+import 'package:domain/entity/response/attendance_entity.dart';
+import 'package:flutter/material.dart';
+
+
+class EAttendanceListState {
+
+  final TextEditingController searchController = TextEditingController();
+  //页面的列表数据
+  List<AttendanceList> datas = [];
+  String keyword = "";
+  DateTime? selectedStartDate = DateTime.now();
+  DateTime? selectedEndDate = DateTime.now();
+  String? selectedStaffName;
+  String? selectedDepartmentId;
+
+}

+ 343 - 0
packages/cpt_uk/lib/modules/attendance/e_attendance_list/item_e_attendance.dart

@@ -0,0 +1,343 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/attendance_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';
+
+/*
+ * 电子考勤Item
+ */
+class EAttendanceItem extends StatelessWidget {
+  final int index;
+  final AttendanceList item;
+  final VoidCallback? onMemberAction;
+
+  EAttendanceItem({
+    required this.index,
+    required this.item,
+    this.onMemberAction,
+  });
+
+  @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(
+                "${"Date".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期文本
+              MyTextView(
+                item.jobDate ?? "-",
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ),
+
+          //员工姓名
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Staff Name".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //姓名
+              MyTextView(
+                item.staffName ?? "-",
+                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,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          //员工电话
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Mobile".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //电话文本
+              MyTextView(
+                "等待接口返回电话号码",
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          //工作对应的部门
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Outlet".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //电话文本
+              MyTextView(
+                "等待接口返回部门",
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作开始时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Start Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.startTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 门卫签到时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security In:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: /* item.securityIn?.changed == 1 ? ColorConstants.textRedFF6262 :*/ Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作地签到时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Work In:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: /*item.workIn?.changed == 1 ? ColorConstants.textRedFF6262 : */Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          //工作结束时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "End Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.endTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作地签出时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Work Out:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: /*item.workOut?.changed == 1 ? ColorConstants.textRedFF6262 :*/ Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 门卫签出时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security Out:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: /*item.securityOut?.changed == 1 ? ColorConstants.textRedFF6262 : */Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 申请时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Applied At:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Status:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                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(),
+            ],
+          ).marginOnly(top: 12),
+
+        ],
+      ),
+    );
+  }
+}

+ 160 - 0
packages/cpt_uk/lib/modules/attendance/e_attendance_list/widget/attendance_sign_in_out.dart

@@ -0,0 +1,160 @@
+import 'dart:typed_data';
+import 'dart:ui';
+
+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/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 签到签出的签名弹窗
+ */
+class AttendanceSignInOut extends StatelessWidget {
+  VoidCallback? cancelAction;
+  void Function(ByteData byteData)? confirmAction;
+
+  //签名版配置
+  HandSignatureControl handSignatureControl = HandSignatureControl(
+    threshold: 3.0,
+    smoothRatio: 200 / 240,
+    velocityRange: 2.0,
+  );
+
+  AttendanceSignInOut({this.cancelAction, this.confirmAction});
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: 283,
+      height: 320,
+      decoration: BoxDecoration(
+        color: Colors.white, // 设置背景颜色
+        borderRadius: BorderRadius.circular(15), // 设置圆角
+      ),
+      child: Column(
+        children: [
+          MyTextView(
+            "Sign Here".tr,
+            fontSize: 19,
+            isFontMedium: true,
+            textColor: ColorConstants.black,
+            marginTop: 15,
+            marginBottom: 12,
+          ),
+
+          Stack(
+            children: [
+              //签名
+              Center(
+                child: Container(
+                  width: 240,
+                  height: 200,
+                  color: Color(0XFFF0F0F0),
+                  child: HandSignature(
+                    control: handSignatureControl,
+                    color: ColorConstants.black404A5B,
+                    width: 1.0,
+                    maxWidth: 3.5,
+                    type: SignatureDrawType.shape,
+                  ),
+                ),
+              ),
+
+              //清除签名
+              Align(
+                alignment: Alignment.bottomLeft,
+                child: MyTextView(
+                  "Clean".tr,
+                  fontSize: 12,
+                  textColor: ColorConstants.white,
+                  cornerRadius: 10.37,
+                  backgroundColor: Color(0XFFFFBB1B),
+                  paddingTop: 4,
+                  paddingBottom: 4,
+                  paddingLeft: 11,
+                  paddingRight: 11,
+                  margin: 10,
+                  onClick: () {
+                    handSignatureControl.clear();
+                  },
+                ),
+              ),
+            ],
+          ).constrained(
+            width: 240,
+            height: 200,
+          ),
+
+          Container(
+            color: Color(0XFFCECECE),
+            height: 0.5,
+            margin: EdgeInsets.only(top: 18),
+          ),
+
+          //Buttons
+          Row(
+            children: [
+              Expanded(
+                  flex: 1,
+                  child: InkWell(
+                    onTap: () {
+                      onCancel();
+                      cancelAction?.call();
+                    },
+                    child: MyTextView(
+                      "Cancel".tr,
+                      fontSize: 17.5,
+                      isFontMedium: true,
+                      textAlign: TextAlign.center,
+                      textColor: Color(0XFF0085C4),
+                      cornerRadius: 3,
+                      borderWidth: 1,
+                    ),
+                  )),
+              Container(
+                color: Color(0XFFCECECE),
+                width: 0.5,
+              ),
+              Expanded(
+                  flex: 1,
+                  child: InkWell(
+                    onTap: () async {
+                      //签名数据
+                      var byteData = await handSignatureControl.toImage(
+                        format: ImageByteFormat.png,
+                        border: 0,
+                        width: 240,
+                        height: 200,
+                        background: Colors.white,
+                      ) as ByteData;
+
+                      onCancel();
+                      confirmAction?.call(byteData);
+                    },
+                    child: MyTextView(
+                      "Confirm".tr,
+                      marginLeft: 10,
+                      fontSize: 17.5,
+                      isFontMedium: true,
+                      textAlign: TextAlign.center,
+                      textColor: Color(0XFF0085C4),
+                      cornerRadius: 3,
+                    ),
+                  )),
+            ],
+          ).expanded(),
+        ],
+      ),
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+}

+ 356 - 0
packages/cpt_uk/lib/modules/attendance/e_attendance_list/widget/job_list_filter.dart

@@ -0,0 +1,356 @@
+import 'dart:ui';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_index_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:shared/utils/screen_util.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_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 用工请求列表的筛选
+ */
+class JobListFilter extends StatefulWidget {
+  void Function(DateTime? selectedStartDate, DateTime? selectedEndDate, String? staffName, String? selectedDepartmentId)? onFilterAction;
+
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? staffName;
+  String? selectedDepartmentId;
+
+  JobListFilter({
+
+    required this.selectedStartDate,
+    required this.selectedEndDate,
+    required this.staffName,
+    required this.selectedDepartmentId,
+    this.onFilterAction,
+  });
+
+  @override
+  State<JobListFilter> createState() => _JobListFilterState();
+}
+
+class _JobListFilterState extends State<JobListFilter> {
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? staffName;
+  String? selectedDepartmentId;
+  late TextEditingController textController;
+  late FocusNode textFocusNode;
+
+  @override
+  void initState() {
+    super.initState();
+    this.selectedStartDate = widget.selectedStartDate;
+    this.selectedEndDate = widget.selectedEndDate;
+    this.staffName = widget.staffName;
+    this.selectedDepartmentId = widget.selectedDepartmentId;
+    textController = TextEditingController();
+    textFocusNode = FocusNode();
+    if (Utils.isNotEmpty(staffName)){
+      textController.text = staffName!;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        SizedBox(
+          height: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1,
+        ),
+        Container(
+          padding: const EdgeInsets.only(left: 15, right: 15, top: 17.5, bottom: 20),
+          width: double.infinity,
+          decoration: const BoxDecoration(
+            color: Colors.white,
+          ),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+
+              //姓名的搜索
+              MyTextView(
+                "Staff Name".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              IgnoreKeyboardDismiss(
+                child: MyTextField(
+                  "staff",
+                  staffName == null ? "" : staffName!,
+                  hintText: "Enter...".tr,
+                  hintStyle: const TextStyle(
+                    color: ColorConstants.gray88,
+                    fontSize: 14,
+                    fontWeight: FontWeight.w400,
+                  ),
+                  controller: textController,
+                  focusNode: textFocusNode,
+                  margin: const EdgeInsets.only(left: 0, right: 0, top: 8),
+                  showDivider: false,
+                  fillBackgroundColor: ColorConstants.grayECECEC,
+                  fillCornerRadius: 5,
+                  padding: const EdgeInsets.only(left: 16, right: 16, top: 0, bottom: 0),
+                  height: 40,
+                  style: const TextStyle(
+                    color: ColorConstants.black33,
+                    fontSize: 14,
+                    fontWeight: FontWeight.w400,
+                  ),
+                  inputType: TextInputType.text,
+                  textInputAction: TextInputAction.done,
+                  enabled: true,
+                  onSubmit: (key, value) {},
+                  cursorColor: ColorConstants.black33,
+                  showLeftIcon: false,
+                  showRightIcon: false,
+                ),
+              ),
+
+              //部门
+              MyTextView(
+                "Outlet".tr,
+                fontSize: 14,
+                marginTop: 11,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择部门
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      "等待接口数据的部门",
+                      // selectedDepartmentId == null || selectedDepartmentId == "0"
+                      //     ? ""
+                      //     : widget.optionResult.departmentList!.firstWhere((element) => element.value.toString() == selectedDepartmentId).txt!,
+                      hint: "Choose Outlet".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      fontSize: 14,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                // pickerOutlet();
+              }),
+
+              //开始时间
+              MyTextView(
+                "Start Date".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                marginTop: 11,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择时间
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStartDate == null ? "" : DateTimeUtils.formatDate(selectedStartDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose Start Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStartDate();
+              }),
+
+              //结束日期
+              MyTextView(
+                "End Date".tr,
+                fontSize: 14,
+                marginTop: 11,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择结束日期
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedEndDate == null ? "" : DateTimeUtils.formatDate(selectedEndDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose End Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerEndDate();
+              }),
+
+              //按钮组
+              Row(
+                children: [
+                  MyButton(
+                    onPressed: () {
+                      //只是Reset当前的弹窗筛选选项
+                      widget.selectedStartDate = null;
+                      widget.selectedEndDate = null;
+                      widget.staffName = null;
+                      widget.selectedDepartmentId = null;
+
+                      setState(() {
+                        selectedStartDate = null;
+                        selectedEndDate = null;
+                        staffName = null;
+                        selectedDepartmentId = null;
+                        textController.text = "";
+                      });
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#FFBB1B"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                  const SizedBox(width: 15),
+                  MyButton(
+                    onPressed: () {
+                      onCancel();
+                      //取消软键盘
+                      textFocusNode.unfocus();
+                      //确定的时候取输入框的值
+                      staffName = textController.text;
+                      widget.onFilterAction?.call(selectedStartDate, selectedEndDate, staffName, selectedDepartmentId);
+                    },
+                    text: "Filter".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#0AC074"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                ],
+              ).marginOnly(top: 20),
+            ],
+          ),
+        ),
+        Center(child: const MyAssetImage(Assets.baseServiceDialogDeleteIcon, width: 26.5, height: 26.5).marginOnly(top: 35)).onTap(() {
+          onCancel();
+        }),
+      ],
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  /// 筛选开始日期
+  void pickerStartDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedStartDate = date;
+        });
+      },
+      title: "Start Date".tr,
+    );
+  }
+
+  /// 筛选结束日期
+  void pickerEndDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedEndDate ?? selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedEndDate = date;
+        });
+      },
+      title: "End Date".tr,
+    );
+  }
+
+/// 筛选部门
+// void pickerOutlet() {
+//   int selectedDepartmentIndex;
+//   if (selectedDepartmentId == null) {
+//     selectedDepartmentIndex = 0;
+//   } else {
+//     selectedDepartmentIndex = widget.optionResult.departmentList!.indexWhere((department) => department.value.toString() == selectedDepartmentId);
+//   }
+//
+//   if (selectedDepartmentIndex < 0) {
+//     selectedDepartmentIndex = 0;
+//   }
+//
+//   OptionPickerUtil.showCupertinoOptionPicker(
+//     items: widget.optionResult.departmentList!.map((e) => e.txt!).toList(growable: false),
+//     initialSelectIndex: selectedDepartmentIndex,
+//     onPickerChanged: (_, index) {
+//       setState(() {
+//         selectedDepartmentId = widget.optionResult.departmentList![index].value!.toString();
+//       });
+//     },
+//   );
+// }
+
+
+}

+ 327 - 0
packages/cpt_uk/lib/modules/attendance/security_registration/item_security_registration.dart

@@ -0,0 +1,327 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/attendance_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';
+
+/*
+ * 电子考勤Item
+ */
+class SecurityRegistrationItem extends StatelessWidget {
+  final int index;
+  final AttendanceList item;
+  final VoidCallback? onMemberAction;
+  final VoidCallback? onEditAction;
+
+  SecurityRegistrationItem({
+    required this.index,
+    required this.item,
+    this.onMemberAction,
+    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(
+                "${"Date".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期文本
+              MyTextView(
+                item.jobDate ?? "-",
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ),
+
+          //员工姓名
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Staff Name".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //姓名
+              MyTextView(
+                item.staffName ?? "-",
+                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,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          //员工电话
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Mobile".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //电话文本
+              MyTextView(
+                "等待接口返回电话号码",
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          //工作对应的部门
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Outlet".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //电话文本
+              MyTextView(
+                "等待接口返回部门",
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作日期
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Job Date".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.startTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Job Time".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.startTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 门卫签到时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security In:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: /* item.securityIn?.changed == 1 ? ColorConstants.textRedFF6262 :*/ Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+
+          // 门卫签出时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security Out:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: /*item.securityOut?.changed == 1 ? ColorConstants.textRedFF6262 : */Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 申请时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Applied At:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                "等待接口返回的时间",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Status:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                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(),
+            ],
+          ).marginOnly(top: 12),
+
+          //操作按钮
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            mainAxisAlignment: MainAxisAlignment.end,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //编辑按钮
+              Visibility(
+                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),
+              ),
+
+            ],
+          ).marginOnly(top: 15),
+
+        ],
+      ),
+    );
+  }
+}

+ 141 - 0
packages/cpt_uk/lib/modules/attendance/security_registration/security_registration_controller.dart

@@ -0,0 +1,141 @@
+import 'dart:typed_data';
+
+import 'package:domain/entity/response/attendance_entity.dart';
+import 'package:domain/repository/job_repository.dart';
+import 'package:get/get.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:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+import '../security_registration/widget/job_list_filter.dart';
+import '../../job/job_applied_staff_detail/applied_staff_detail_page.dart';
+import 'security_registration_state.dart';
+
+class SecurityRegistrationController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final EAttendanceListState state = EAttendanceListState();
+
+  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 {
+    fetchAttendanceList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _needShowPlaceholder = true;
+    fetchAttendanceList();
+  }
+
+  /// 获取服务器数据,成员考勤列表
+  Future fetchAttendanceList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    //获取到数据
+    var result = await _jobRepository.fetchAttendanceList(
+      state.keyword,
+      DateTimeUtils.formatDate(state.selectedStartDate, format: "yyyy-MM-dd"),
+      DateTimeUtils.formatDate(state.selectedEndDate, format: "yyyy-MM-dd"),
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      handleList(result.data?.rows);
+      refreshController.finishRefresh(IndicatorResult.success);
+    } else {
+      errorMessage = result.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+      refreshController.finishRefresh(IndicatorResult.fail);
+    }
+
+    //最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<AttendanceList>? 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();
+    fetchAttendanceList();
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+    state.datas.clear();
+  }
+
+
+  /// 展示标题栏的 Filter 弹窗
+  void showFilterDialog() {
+    DialogEngine.show(
+      widget: JobListFilter(
+        selectedStartDate: state.selectedStartDate,
+        selectedEndDate: state.selectedEndDate,
+        staffName: state.selectedStaffName,
+        selectedDepartmentId: state.selectedDepartmentId,
+        onFilterAction: (startDate, endDate, staffName, departmentId) {
+          Log.d("startDate:$startDate endDate:$endDate staffName:$staffName departmentId:$departmentId");
+
+          state.selectedStartDate = startDate;
+          state.selectedEndDate = endDate;
+          state.selectedStaffName = staffName;
+          state.selectedDepartmentId = departmentId;
+
+          //赋值之后刷新
+          refreshController.callRefresh();
+        },
+      ),
+      position: DialogPosition.top,
+      animType: DialogAnimation.fade,
+    );
+  }
+
+  //查看UK员工的详情
+  void gotoStaffDetailPage(AttendanceList data) {
+    UKAppliedStaffDetailPage.startInstance(data.staffId.toString());
+  }
+
+  //展示编辑的弹窗
+  void showEditDialog(AttendanceList data) {
+    ToastEngine.show("展示编辑的弹窗");
+  }
+
+}

+ 136 - 0
packages/cpt_uk/lib/modules/attendance/security_registration/security_registration_page.dart

@@ -0,0 +1,136 @@
+import 'dart:ui';
+
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:plugin_basic/base/base_state.dart';
+import 'package:plugin_basic/base/mixin_state_lifecycle.dart';
+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/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/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+import 'security_registration_controller.dart';
+import 'security_registration_state.dart';
+import 'item_security_registration.dart';
+
+/*
+ * 门卫登记列表
+ */
+class UKSecurityRegistrationPage extends BaseStatefulPage<SecurityRegistrationController> {
+  UKSecurityRegistrationPage({super.key});
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKSecurityRegistration);
+  }
+
+  @override
+  State<UKSecurityRegistrationPage> createState() => _SignInSignOutPageState();
+
+  @override
+  SecurityRegistrationController createRawController() {
+    return SecurityRegistrationController();
+  }
+}
+
+class _SignInSignOutPageState extends BaseState<UKSecurityRegistrationPage, SecurityRegistrationController> with StateLifecycle {
+  late EAttendanceListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  void dispose() {
+    Get.delete<SecurityRegistrationController>();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(
+      builder: (controller) {
+        return SafeArea(
+          bottom: true,
+          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, "Security Registration".tr, actions: [
+                  //筛选图标
+                  const MyAssetImage(
+                    Assets.baseServiceTitleBarFilterIcon,
+                    width: 24,
+                    height: 16.5,
+                  ).onTap(() {
+                    controller.showFilterDialog();
+                  }).marginOnly(right: 15),
+                ]),
+
+                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 SecurityRegistrationItem(
+                            index: index,
+                            item: state.datas[index],
+                            onMemberAction: () {
+                              controller.gotoStaffDetailPage(state.datas[index]);
+                            },
+                            onEditAction: (){
+                              controller.showEditDialog(state.datas[index]);
+                            },
+                          );
+                        },
+                        childCount: state.datas.length,
+                      ))
+                    ],
+                  ),
+                ).marginOnly(top: 5).expanded(),
+              ],
+            ),
+          ),
+        );
+      },
+    );
+  }
+}

+ 16 - 0
packages/cpt_uk/lib/modules/attendance/security_registration/security_registration_state.dart

@@ -0,0 +1,16 @@
+import 'package:domain/entity/response/attendance_entity.dart';
+import 'package:flutter/material.dart';
+
+
+class EAttendanceListState {
+
+  final TextEditingController searchController = TextEditingController();
+  //页面的列表数据
+  List<AttendanceList> datas = [];
+  String keyword = "";
+  DateTime? selectedStartDate = DateTime.now();
+  DateTime? selectedEndDate = DateTime.now();
+  String? selectedStaffName;
+  String? selectedDepartmentId;
+
+}

+ 356 - 0
packages/cpt_uk/lib/modules/attendance/security_registration/widget/job_list_filter.dart

@@ -0,0 +1,356 @@
+import 'dart:ui';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_index_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:shared/utils/screen_util.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_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 用工请求列表的筛选
+ */
+class JobListFilter extends StatefulWidget {
+  void Function(DateTime? selectedStartDate, DateTime? selectedEndDate, String? staffName, String? selectedDepartmentId)? onFilterAction;
+
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? staffName;
+  String? selectedDepartmentId;
+
+  JobListFilter({
+
+    required this.selectedStartDate,
+    required this.selectedEndDate,
+    required this.staffName,
+    required this.selectedDepartmentId,
+    this.onFilterAction,
+  });
+
+  @override
+  State<JobListFilter> createState() => _JobListFilterState();
+}
+
+class _JobListFilterState extends State<JobListFilter> {
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? staffName;
+  String? selectedDepartmentId;
+  late TextEditingController textController;
+  late FocusNode textFocusNode;
+
+  @override
+  void initState() {
+    super.initState();
+    this.selectedStartDate = widget.selectedStartDate;
+    this.selectedEndDate = widget.selectedEndDate;
+    this.staffName = widget.staffName;
+    this.selectedDepartmentId = widget.selectedDepartmentId;
+    textController = TextEditingController();
+    textFocusNode = FocusNode();
+    if (Utils.isNotEmpty(staffName)){
+      textController.text = staffName!;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        SizedBox(
+          height: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1,
+        ),
+        Container(
+          padding: const EdgeInsets.only(left: 15, right: 15, top: 17.5, bottom: 20),
+          width: double.infinity,
+          decoration: const BoxDecoration(
+            color: Colors.white,
+          ),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+
+              //姓名的搜索
+              MyTextView(
+                "Staff Name".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              IgnoreKeyboardDismiss(
+                child: MyTextField(
+                  "staff",
+                  staffName == null ? "" : staffName!,
+                  hintText: "Enter...".tr,
+                  hintStyle: const TextStyle(
+                    color: ColorConstants.gray88,
+                    fontSize: 14,
+                    fontWeight: FontWeight.w400,
+                  ),
+                  controller: textController,
+                  focusNode: textFocusNode,
+                  margin: const EdgeInsets.only(left: 0, right: 0, top: 8),
+                  showDivider: false,
+                  fillBackgroundColor: ColorConstants.grayECECEC,
+                  fillCornerRadius: 5,
+                  padding: const EdgeInsets.only(left: 16, right: 16, top: 0, bottom: 0),
+                  height: 40,
+                  style: const TextStyle(
+                    color: ColorConstants.black33,
+                    fontSize: 14,
+                    fontWeight: FontWeight.w400,
+                  ),
+                  inputType: TextInputType.text,
+                  textInputAction: TextInputAction.done,
+                  enabled: true,
+                  onSubmit: (key, value) {},
+                  cursorColor: ColorConstants.black33,
+                  showLeftIcon: false,
+                  showRightIcon: false,
+                ),
+              ),
+
+              //部门
+              MyTextView(
+                "Outlet".tr,
+                fontSize: 14,
+                marginTop: 11,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择部门
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      "等待接口数据的部门",
+                      // selectedDepartmentId == null || selectedDepartmentId == "0"
+                      //     ? ""
+                      //     : widget.optionResult.departmentList!.firstWhere((element) => element.value.toString() == selectedDepartmentId).txt!,
+                      hint: "Choose Outlet".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      fontSize: 14,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                // pickerOutlet();
+              }),
+
+              //开始时间
+              MyTextView(
+                "Start Date".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                marginTop: 11,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择时间
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStartDate == null ? "" : DateTimeUtils.formatDate(selectedStartDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose Start Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStartDate();
+              }),
+
+              //结束日期
+              MyTextView(
+                "End Date".tr,
+                fontSize: 14,
+                marginTop: 11,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择结束日期
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedEndDate == null ? "" : DateTimeUtils.formatDate(selectedEndDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose End Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerEndDate();
+              }),
+
+              //按钮组
+              Row(
+                children: [
+                  MyButton(
+                    onPressed: () {
+                      //只是Reset当前的弹窗筛选选项
+                      widget.selectedStartDate = null;
+                      widget.selectedEndDate = null;
+                      widget.staffName = null;
+                      widget.selectedDepartmentId = null;
+
+                      setState(() {
+                        selectedStartDate = null;
+                        selectedEndDate = null;
+                        staffName = null;
+                        selectedDepartmentId = null;
+                        textController.text = "";
+                      });
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#FFBB1B"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                  const SizedBox(width: 15),
+                  MyButton(
+                    onPressed: () {
+                      onCancel();
+                      //取消软键盘
+                      textFocusNode.unfocus();
+                      //确定的时候取输入框的值
+                      staffName = textController.text;
+                      widget.onFilterAction?.call(selectedStartDate, selectedEndDate, staffName, selectedDepartmentId);
+                    },
+                    text: "Filter".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#0AC074"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                ],
+              ).marginOnly(top: 20),
+            ],
+          ),
+        ),
+        Center(child: const MyAssetImage(Assets.baseServiceDialogDeleteIcon, width: 26.5, height: 26.5).marginOnly(top: 35)).onTap(() {
+          onCancel();
+        }),
+      ],
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  /// 筛选开始日期
+  void pickerStartDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedStartDate = date;
+        });
+      },
+      title: "Start Date".tr,
+    );
+  }
+
+  /// 筛选结束日期
+  void pickerEndDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedEndDate ?? selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedEndDate = date;
+        });
+      },
+      title: "End Date".tr,
+    );
+  }
+
+  /// 筛选部门
+  // void pickerOutlet() {
+  //   int selectedDepartmentIndex;
+  //   if (selectedDepartmentId == null) {
+  //     selectedDepartmentIndex = 0;
+  //   } else {
+  //     selectedDepartmentIndex = widget.optionResult.departmentList!.indexWhere((department) => department.value.toString() == selectedDepartmentId);
+  //   }
+  //
+  //   if (selectedDepartmentIndex < 0) {
+  //     selectedDepartmentIndex = 0;
+  //   }
+  //
+  //   OptionPickerUtil.showCupertinoOptionPicker(
+  //     items: widget.optionResult.departmentList!.map((e) => e.txt!).toList(growable: false),
+  //     initialSelectIndex: selectedDepartmentIndex,
+  //     onPickerChanged: (_, index) {
+  //       setState(() {
+  //         selectedDepartmentId = widget.optionResult.departmentList![index].value!.toString();
+  //       });
+  //     },
+  //   );
+  // }
+
+
+}

+ 430 - 0
packages/cpt_uk/lib/modules/job/job_applied/applied_staff_item.dart

@@ -0,0 +1,430 @@
+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: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';
+
+/**
+ * 已申请的员工列表Item
+ */
+class AppliedStaffItem extends StatelessWidget {
+  final int index;
+  final JobListAppliedInfoEntity? jobInfo;
+  final JobListAppliedStaffListRows item;
+  final VoidCallback? onStatusAction;
+  final VoidCallback? onEditAction;
+  final VoidCallback? onRemarkAction;
+  final VoidCallback? onItemAction;
+  final VoidCallback? onMemberAction;
+
+  AppliedStaffItem({
+    required this.index,
+    required this.item,
+    required this.jobInfo,
+    this.onStatusAction,
+    this.onRemarkAction,
+    this.onEditAction,
+    this.onItemAction,
+    this.onMemberAction,
+  });
+
+  @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(
+                "Staff Name:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //姓名
+              MyTextView(
+                item.staffName ?? "-",
+                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,
+              ).expanded(),
+
+              //是否选中
+              Visibility(
+                visible: item.status == 3,
+                child: MyAssetImage(
+                  item.isSelected ? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedIcon,
+                  width: 20.5,
+                  height: 20.5,
+                ),
+              ),
+            ],
+          ),
+
+          // 工作开始时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Start Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.startTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 门卫签到时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security In:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.securityIn?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.securityIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作地签到时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Work In:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.workIn?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.workIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          //工作结束时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "End Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.endTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作地签出时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Work Out:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.workOut?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.workOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 门卫签出时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security Out:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.securityOut?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.securityOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // + - Hours
+          Visibility(
+            visible: jobInfo?.jobUnit == "hour",
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                MyTextView(
+                  "+/- Hours:".tr,
+                  isFontRegular: true,
+                  textColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                ),
+
+                //小时
+                MyTextView(
+                  Utils.isNotEmpty(item.adjustShow) ? item.adjustShow! : "0",
+                  marginLeft: 5,
+                  isFontRegular: true,
+                  textColor: Colors.white,
+                  fontSize: 14,
+                ).expanded(),
+              ],
+            ).marginOnly(top: 12),
+          ),
+
+          // Total Hours
+          Visibility(
+            visible: jobInfo?.jobUnit == "hour",
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                MyTextView(
+                  "Total Hours:".tr,
+                  isFontRegular: true,
+                  textColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                ),
+
+                //小时
+                MyTextView(
+                  item.totalShow.toString(),
+                  marginLeft: 5,
+                  isFontRegular: true,
+                  textColor: Colors.white,
+                  fontSize: 14,
+                ).expanded(),
+              ],
+            ).marginOnly(top: 12),
+          ),
+
+          // Total Rooms
+          Visibility(
+            visible: jobInfo?.jobUnit != "hour",
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                MyTextView(
+                  "Total Rooms:".tr,
+                  isFontRegular: true,
+                  textColor: ColorConstants.textGrayAECAE5,
+                  fontSize: 14,
+                ),
+
+                //小时
+                MyTextView(
+                  item.totalRooms.toString(),
+                  marginLeft: 5,
+                  isFontRegular: true,
+                  textColor: Colors.white,
+                  fontSize: 14,
+                ).expanded(),
+              ],
+            ).marginOnly(top: 12),
+          ),
+
+          // 申请时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Applied At:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                item.appliedAt ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Status:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                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(),
+            ],
+          ).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),
+          ),
+        ],
+      ).onTap(() {
+        onItemAction?.call();
+      }),
+    );
+  }
+}

+ 395 - 0
packages/cpt_uk/lib/modules/job/job_applied/job_applied_controller.dart

@@ -0,0 +1,395 @@
+import 'package:domain/entity/response/job_list_applied_staff_list_entity.dart';
+import 'package:domain/repository/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';
+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/date_time_utils.dart';
+import 'package:shared/utils/event_bus.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 'job_applied_state.dart';
+import 'widget/applied_add_staff.dart';
+import 'widget/applied_butch_modify.dart';
+import 'widget/applied_staff_reviews.dart';
+
+class JobAppliedController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final JobAppliedState state = JobAppliedState();
+
+  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;
+    fetchAppliedStaffList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchAppliedStaffList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchAppliedStaffList();
+  }
+
+  /// 获取服务器数据,通知消息列表
+  Future fetchAppliedStaffList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    if (state.jobInfo == null) {
+      //不是并发的,顺序执行接口
+      var jobInfoResult = await _jobRepository.fetchJobAppliedInfo(
+        state.jobId,
+        cancelToken: cancelToken,
+      );
+
+      if (jobInfoResult.isSuccess) {
+        state.jobInfo = jobInfoResult.data;
+        update();
+      } else {
+        errorMessage = jobInfoResult.errorMsg;
+        changeLoadingState(LoadState.State_Error);
+        return;
+      }
+    }
+
+    // 获取 Applied 列表
+    var listResult = await _jobRepository.fetchJobAppliedStaffs(
+      state.jobId,
+      state.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<JobListAppliedStaffListRows>? 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();
+    fetchAppliedStaffList();
+    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() {
+    DialogEngine.show(
+      widget: AppliedAddStaff(
+        jobId: state.jobId!,
+        confirmAction: (selectedIds) {
+          //调用接口添加员工
+          _requestAddStaff2Applied(selectedIds);
+        },
+      ),
+    );
+  }
+
+  //调用接口添加员工
+  void _requestAddStaff2Applied(String selectedIds) async {
+    var result = await _jobRepository.addStaff2Job(state.jobId, 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 gotoAppliedEditPage(JobListAppliedStaffListRows data) {
+    UKJobAppliedEditPage.startInstance(data.appliedId.toString());
+  }
+
+  /// 展示评论的弹窗
+  void showRemarkDialog(JobListAppliedStaffListRows data) async {
+    //请求接口获取到已评论的数据
+    var result = await _jobRepository.fetchAppliedStaffReviewView(data.appliedId.toString());
+
+    if (result.isSuccess) {
+      //接口数据获取成功,展示弹窗
+      DialogEngine.show(
+        widget: AppliedStaffReviews(
+          appliedReviews: result.data!,
+          confirmAction: (attitudeRate, performanceRate, experienceRate, groomingRate, content) async {
+            //请求接口,提交评论
+            var submitResult = await _jobRepository.remarkAppliedSingleStaffSubmit(
+              data.appliedId.toString(),
+              attitudeRate,
+              groomingRate,
+              performanceRate,
+              experienceRate,
+              content,
+            );
+
+            if (submitResult.isSuccess) {
+              NotifyEngine.showSuccess("Successful".tr);
+            } else {
+              ToastEngine.show(submitResult.errorMsg ?? "Network Load Error".tr);
+            }
+          },
+        ),
+      );
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  /// 去展示员工状态的审核流程页面
+  void gotoAppliedWorkflowPage(JobListAppliedStaffListRows data) {
+    UKAppliedWorkflowPage.startInstance(data.appliedId.toString());
+  }
+
+  /// 去查看员工详情页面
+  void gotoStaffDetailPage(JobListAppliedStaffListRows data) {
+    UKAppliedStaffDetailPage.startInstance(data.memberId.toString());
+  }
+
+  /// Item选中与未选中设置
+  void doSelectedOrNot(JobListAppliedStaffListRows data) {
+    //只有 Approve = 3 的状态才能选中
+    if (data.status == 3) {
+      data.isSelected = !data.isSelected;
+      update();
+    }
+  }
+
+  /// 批量修改的弹窗
+  void showBatchModifyDialog() async {
+    if (state.jobInfo == null) return;
+    //找出已经选中的员工(只有状态为3 Approve的状态才能修改)
+    var selectedList = state.datas.where((element) => element.isSelected && element.status == 3).toList(growable: false);
+    if (selectedList.isNotEmpty) {
+      var ids = selectedList.map((e) => e.appliedId.toString()).toList(growable: false);
+      var separatedIds = ids.join(',');
+
+      DialogEngine.show(
+          widget: AppliedButchModify(
+              selectedStartDate: DateTimeUtils.getDateTime(state.jobInfo?.startTime ?? ""),
+              selectedEndDate: DateTimeUtils.getDateTime(state.jobInfo?.endTime ?? ""),
+              confirmAction: (start, end) {
+                _requestBatchModify(start, end, separatedIds);
+              }));
+    } else {
+      ToastEngine.show("Please select the applied record".tr);
+    }
+  }
+
+  /// 执行批量修改的请求
+  void _requestBatchModify(DateTime start, DateTime end, String separatedIds) async {
+    //执行请求
+    var result = await _jobRepository.batchEditStaffCheckTime(
+      state.jobId,
+      separatedIds,
+      DateTimeUtils.formatDate(start),
+      DateTimeUtils.formatDate(end),
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //调用接口刷新指定的Staff的信息
+      fetchItemByIdAndRefreshItem(separatedIds);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  /// 批准的操作
+  void operationApprove() async {
+    //找出已经选中的员工(只有状态为3 Approve的状态才能修改)
+    var selectedList = state.datas.where((element) => element.isSelected && element.status == 3).toList(growable: false);
+    if (selectedList.isNotEmpty) {
+      var ids = selectedList.map((e) => e.appliedId.toString()).toList(growable: false);
+      var separatedIds = ids.join(',');
+
+      // Are you sure 的弹窗
+      DialogEngine.show(
+        widget: AppDefaultDialog(
+          title: "Message".tr,
+          message: "Are you sure you want to setting approved?".tr,
+          confirmAction: () async {
+            //执行请求
+            var result = await _jobRepository.submitBatchStaffApprove(separatedIds, cancelToken: cancelToken);
+
+            if (result.isSuccess) {
+              NotifyEngine.showSuccess("Successful".tr);
+
+              //调用接口刷新指定的Staff的信息
+              fetchItemByIdAndRefreshItem(separatedIds);
+            } else {
+              ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+              return;
+            }
+          },
+        ),
+      );
+    } else {
+      ToastEngine.show("Please select the applied record".tr);
+    }
+  }
+
+  /// 根据ID获取Item对象,用于刷新
+  void fetchItemByIdAndRefreshItem(String appliedIds) async {
+    var result = await _jobRepository.fetchItemByAppliedIds(
+      state.jobId,
+      appliedIds,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      var data = result.data;
+      if (data != null && data.rows != null && data.rows!.isNotEmpty) {
+        List<JobListAppliedStaffListRows> newItem = data.rows!;
+
+        // 创建一个 Map 来加速查找
+        Map<int, JobListAppliedStaffListRows> newItemMap = {for (var item in newItem) item.appliedId: item};
+
+        // 遍历 state.datas 进行替换
+        for (int i = 0; i < state.datas.length; i++) {
+          if (newItemMap.containsKey(state.datas[i].appliedId)) {
+            state.datas[i] = newItemMap[state.datas[i].appliedId]!;
+          }
+        }
+
+        //刷新
+        update();
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+}

+ 210 - 0
packages/cpt_uk/lib/modules/job/job_applied/job_applied_page.dart

@@ -0,0 +1,210 @@
+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 'applied_staff_item.dart';
+import 'job_applied_controller.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_state.dart';
+
+/*
+ * 已申请的页面,可以签到签出、加人、修改状态、评论等操作
+ */
+class UKJobAppliedPage extends BaseStatefulPage<JobAppliedController> {
+  UKJobAppliedPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? jobId) {
+    return Get.start(RouterPath.UKJobApplied, arguments: {'jobId': jobId});
+  }
+
+  @override
+  JobAppliedController createRawController() {
+    return JobAppliedController();
+  }
+
+  @override
+  State<UKJobAppliedPage> createState() => _JobAppliedState();
+}
+
+class _JobAppliedState extends BaseState<UKJobAppliedPage, JobAppliedController> {
+  late JobAppliedState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.jobId = Get.arguments['jobId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return  SafeArea(
+          bottom: true,
+          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,
+                  state.jobInfo?.jobTitle ?? "Title".tr,
+                  subTitle: "(${state.jobInfo?.jobDate ?? "-"})",
+                  subTitleColor: ColorConstants.textGrayAECAE5,
+                ),
+
+                //搜索的条件
+                Row(
+                  children: [
+                    SearchAppBar(
+                      value: state.keyword,
+                      onSearch: (keyword) {
+                        controller.doSearch(keyword);
+                      },
+                      hintText: "Staff Name".tr,
+                      controller: state.searchController,
+                    ).expanded(),
+                    MyButton(
+                      onPressed: () {
+                        FocusScope.of(context).unfocus();
+                        controller.resetFiltering();
+                      },
+                      text: "Reset".tr,
+                      textColor: ColorConstants.white,
+                      backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+                      radius: 20,
+                      minWidth: 60,
+                      minHeight: 35,
+                    ),
+                  ],
+                ).marginOnly(top: 10, left: 15, right: 15, bottom: 5),
+
+                // 添加按钮
+                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(
+                  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 AppliedStaffItem(
+                            index: index,
+                            jobInfo: state.jobInfo,
+                            item: state.datas[index],
+                            onEditAction: () {
+                              controller.gotoAppliedEditPage(state.datas[index]);
+                            },
+                            onRemarkAction: () {
+                              controller.showRemarkDialog(state.datas[index]);
+                            },
+                            onStatusAction: () {
+                              controller.gotoAppliedWorkflowPage(state.datas[index]);
+                            },
+                            onItemAction: () {
+                              controller.doSelectedOrNot(state.datas[index]);
+                            },
+                            onMemberAction: (){
+                              controller.gotoStaffDetailPage(state.datas[index]);
+                            },
+                          );
+                        },
+                        childCount: state.datas.length,
+                      ))
+                    ],
+                  ),
+                ).expanded(),
+
+                Row(
+                  mainAxisSize: MainAxisSize.max,
+                  children: [
+                    //批量Approve
+                    MyTextView(
+                      "Operation Approve".tr,
+                      fontSize: 17,
+                      isFontMedium: true,
+                      boxHeight: 48,
+                      onClick: () {
+                        controller.operationApprove();
+                      },
+                      alignment: Alignment.center,
+                      textAlign: TextAlign.center,
+                      textColor: Colors.white,
+                      backgroundColor: Color(0XFF0AC074),
+                    ).expanded(),
+
+                    //批量修改时间
+                    MyTextView(
+                      "Batch Modify".tr,
+                      fontSize: 17,
+                      isFontMedium: true,
+                      boxHeight: 48,
+                      onClick: () {
+                        controller.showBatchModifyDialog();
+                      },
+                      alignment: Alignment.center,
+                      textAlign: TextAlign.center,
+                      textColor: Colors.white,
+                      backgroundColor: Color(0XFFFFBB1B),
+                    ).expanded(),
+                  ],
+                ),
+              ],
+            ),
+          ),
+        );
+    });
+  }
+}

+ 14 - 0
packages/cpt_uk/lib/modules/job/job_applied/job_applied_state.dart

@@ -0,0 +1,14 @@
+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:flutter/material.dart';
+
+class JobAppliedState {
+  //筛选条件
+  final TextEditingController searchController = TextEditingController();
+  String keyword = "";
+
+  String? jobId;
+  JobListAppliedInfoEntity? jobInfo; //指定工作的简短信息
+
+  List<JobListAppliedStaffListRows> datas = []; //Applied的员工列表
+}

+ 342 - 0
packages/cpt_uk/lib/modules/job/job_applied/widget/applied_add_staff.dart

@@ -0,0 +1,342 @@
+import 'dart:ui';
+
+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: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 'applied_add_staff_controller.dart';
+
+/*
+ * 添加员工的弹窗
+ */
+class AppliedAddStaff extends StatefulWidget {
+  String jobId;
+  void Function(String selectIds)? confirmAction;
+
+  AppliedAddStaff({required this.jobId, this.confirmAction});
+
+  @override
+  State<AppliedAddStaff> createState() => _AppliedAddStaffState();
+}
+
+class _AppliedAddStaffState extends State<AppliedAddStaff> {
+  @override
+  void initState() {
+    super.initState();
+    Get.put(AppliedAddStaffController());
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+    Get.delete<AppliedAddStaffController>();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return GetBuilder<AppliedAddStaffController>(
+      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(AppliedAddStaffController 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);
+    }
+
+  }
+
+  Widget _buildStaffItem(JobListAppliedStaffSearchRows 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.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(
+                  "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.phone ?? "-",
+                  textColor: ColorConstants.black66,
+                  fontSize: 13,
+                  isFontRegular: true,
+                ),
+              ],
+            ).marginOnly(top: 5),
+
+            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);
+  }
+}

+ 134 - 0
packages/cpt_uk/lib/modules/job/job_applied/widget/applied_add_staff_controller.dart

@@ -0,0 +1,134 @@
+import 'package:domain/entity/response/job_list_applied_staff_search_entity.dart';
+import 'package:domain/repository/job_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 AppliedAddStaffController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = 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<JobListAppliedStaffSearchRows> 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 _jobRepository.searchStaffList(
+      jobId,
+      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<JobListAppliedStaffSearchRows>? 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();
+  }
+}

+ 241 - 0
packages/cpt_uk/lib/modules/job/job_applied/widget/applied_butch_modify.dart

@@ -0,0 +1,241 @@
+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/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: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/widget_export.dart';
+
+/*
+ * 批量操作修改时间的弹窗
+ */
+class AppliedButchModify extends StatefulWidget {
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  void Function(DateTime startTime, DateTime endTime)? confirmAction;
+
+  AppliedButchModify({this.selectedStartDate, this.selectedEndDate, this.confirmAction});
+
+  @override
+  State<AppliedButchModify> createState() => _AppliedButchModifyState();
+}
+
+class _AppliedButchModifyState extends State<AppliedButchModify> {
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+
+  @override
+  void initState() {
+    super.initState();
+    selectedStartDate = widget.selectedStartDate;
+    selectedEndDate = widget.selectedEndDate;
+  }
+
+  @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(
+                  "Batch Modify".tr,
+                  fontSize: 19,
+                  isFontMedium: true,
+                  textColor: ColorConstants.black,
+                  marginTop: 22,
+                  marginBottom: 20,
+                ),
+              ),
+
+              FormRequireText(
+                fontSize: 14,
+                textColor: ColorConstants.black33,
+                fontWeight: FontWeight.w400,
+                text: "Job Start Time".tr,
+              ),
+
+              //选择时间
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStartDate == null ? "" : DateTimeUtils.formatDate(selectedStartDate),
+                      fontSize: 14,
+                      hint: "Choose Start Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStartDate();
+              }),
+
+              //结束日期
+              FormRequireText(
+                fontSize: 14,
+                textColor: ColorConstants.black33,
+                fontWeight: FontWeight.w400,
+                text: "Job End Time".tr,
+              ).marginOnly(top: 11),
+
+              //选择结束日期
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedEndDate == null ? "" : DateTimeUtils.formatDate(selectedEndDate),
+                      fontSize: 14,
+                      hint: "Choose End Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerEndDate();
+              }),
+
+              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 {
+                          if (selectedStartDate == null) {
+                            ToastEngine.show("Choose Start Date".tr);
+                            return;
+                          }
+
+                          if (selectedEndDate == null) {
+                            ToastEngine.show("Choose End Date".tr);
+                            return;
+                          }
+
+                          widget.confirmAction?.call(selectedStartDate!, selectedEndDate!);
+                          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 pickerStartDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedStartDate,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedStartDate = date;
+        });
+      },
+      title: "Start Date".tr,
+    );
+  }
+
+  /// 筛选结束日期
+  void pickerEndDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedEndDate ?? selectedStartDate,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedEndDate = date;
+        });
+      },
+      title: "End Date".tr,
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+}

+ 313 - 0
packages/cpt_uk/lib/modules/job/job_applied/widget/applied_staff_reviews.dart

@@ -0,0 +1,313 @@
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_remark_view_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_text_view.dart';
+import 'package:widgets/shatter/rating_widget.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 员工的评价弹窗
+ */
+class AppliedStaffReviews extends StatefulWidget {
+  JobListRemarkViewEntity appliedReviews;
+  void Function(String attitudeRate, String performanceRate, String experienceRate, String groomingRate, String content)? confirmAction;
+
+  AppliedStaffReviews({required this.appliedReviews, this.confirmAction});
+
+  @override
+  State<AppliedStaffReviews> createState() => _AppliedStaffReviewsState();
+}
+
+class _AppliedStaffReviewsState extends State<AppliedStaffReviews> {
+  late JobListRemarkViewEntity reviews;
+  late String attitudeRate;
+  late String groomingRate;
+  late String performanceRate;
+  late String experienceRate;
+  late String content;
+  late TextEditingController _controller;
+  late FocusNode _focusNode;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = TextEditingController();
+    _focusNode = FocusNode();
+
+    reviews = widget.appliedReviews;
+    attitudeRate = reviews.attitudeRate.toString();
+    groomingRate = reviews.groomingRate.toString();
+    performanceRate = reviews.performanceRate.toString();
+    experienceRate = reviews.experienceRate.toString();
+    _controller.text = reviews.content ?? "";
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        //Title (如果使用 Container 为最外层容器则默认为 match_parent 的效果,除非我们限制宽度和最大高度最小高度)
+        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,
+                  marginBottom: 19,
+                  marginLeft: 22,
+                  marginRight: 22,
+                ),
+              ),
+
+              MyTextView(
+                reviews.memberName ?? "",
+                isFontRegular: true,
+                textColor: Colors.black,
+                marginLeft: 22,
+                marginRight: 22,
+                fontSize: 17,
+              ),
+
+              //态度评分
+              Row(
+                children: [
+                  MyTextView(
+                    "Attitude".tr,
+                    isFontRegular: true,
+                    textColor: ColorConstants.black66,
+                    fontSize: 15,
+                  ).expanded(),
+                  RatingWidget(
+                    nomalImage: Assets.baseServiceRatingUnselected,
+                    selectImage: Assets.baseServiceRatingSelected,
+                    size: 21,
+                    padding: 5,
+                    selectAble: Utils.isEmpty(reviews.content),
+                    integerOnly: true,
+                    value: reviews.attitudeRate,
+                    onRatingUpdate: (value) {
+                      attitudeRate = value;
+                    },
+                  )
+                ],
+              ).marginOnly(top: 15, left: 22, right: 22),
+
+              //表现评分
+              Row(
+                children: [
+                  MyTextView(
+                    "Performance".tr,
+                    isFontRegular: true,
+                    textColor: ColorConstants.black66,
+                    fontSize: 15,
+                  ).expanded(),
+                  RatingWidget(
+                    nomalImage: Assets.baseServiceRatingUnselected,
+                    selectImage: Assets.baseServiceRatingSelected,
+                    size: 21,
+                    padding: 5,
+                    selectAble: Utils.isEmpty(reviews.content),
+                    integerOnly: true,
+                    value: reviews.performanceRate,
+                    onRatingUpdate: (value) {
+                      performanceRate = value;
+                    },
+                  )
+                ],
+              ).marginOnly(top: 15, left: 22, right: 22),
+
+              //经验评分
+              Row(
+                children: [
+                  MyTextView(
+                    "Experience".tr,
+                    isFontRegular: true,
+                    textColor: ColorConstants.black66,
+                    fontSize: 15,
+                  ).expanded(),
+                  RatingWidget(
+                    nomalImage: Assets.baseServiceRatingUnselected,
+                    selectImage: Assets.baseServiceRatingSelected,
+                    size: 21,
+                    padding: 5,
+                    selectAble: Utils.isEmpty(reviews.content),
+                    integerOnly: true,
+                    value: reviews.experienceRate,
+                    onRatingUpdate: (value) {
+                      experienceRate = value;
+                    },
+                  )
+                ],
+              ).marginOnly(top: 15, left: 22, right: 22),
+
+              //着装评分
+              Row(
+                children: [
+                  MyTextView(
+                    "Grooming".tr,
+                    isFontRegular: true,
+                    textColor: ColorConstants.black66,
+                    fontSize: 15,
+                  ).expanded(),
+                  RatingWidget(
+                    nomalImage: Assets.baseServiceRatingUnselected,
+                    selectImage: Assets.baseServiceRatingSelected,
+                    size: 21,
+                    padding: 5,
+                    selectAble: Utils.isEmpty(reviews.content),
+                    integerOnly: true,
+                    value: reviews.groomingRate,
+                    onRatingUpdate: (value) {
+                      groomingRate = value;
+                    },
+                  )
+                ],
+              ).marginOnly(top: 15, left: 22, right: 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: Utils.isEmpty(reviews.content),
+                    focusNode: _focusNode,
+                    controller: _controller,
+                    // 装饰
+                    decoration: InputDecoration(
+                      isDense: true,
+                      isCollapsed: true,
+                      border: InputBorder.none,
+                      hintText: "Enter...".tr,
+                      hintStyle: const 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,
+              ),
+
+              //按钮组
+              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();
+                        },
+                        child: MyTextView(
+                          "Submit".tr,
+                          marginLeft: 10,
+                          fontSize: 17.5,
+                          isFontMedium: true,
+                          textAlign: TextAlign.center,
+                          textColor: Color(0XFF0085C4),
+                          cornerRadius: 3,
+                        ),
+                      )),
+                ],
+              ).constrained(height: 46),
+            ],
+          ),
+        ),
+      ],
+    ).constrained(width: 285);
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  //执行回调
+  void doCallbackAction() {
+    _focusNode.unfocus();
+
+    content = _controller.text.toString();
+
+    if (attitudeRate == "0" || experienceRate == "0" || performanceRate == "0" || groomingRate == "0") {
+      ToastEngine.show("Rate First");
+      return;
+    }
+
+    if (Utils.isEmpty(content)) {
+      ToastEngine.show("Please Enter Remark".tr);
+      return;
+    }
+
+    onCancel();
+
+    widget.confirmAction?.call(attitudeRate, performanceRate, experienceRate, groomingRate, content);
+  }
+}

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

@@ -0,0 +1,178 @@
+import 'package:domain/repository/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/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/date_time_utils.dart';
+import 'package:shared/utils/event_bus.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+
+import 'job_applied_edit_state.dart';
+
+class JobAppliedEditController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final JobAppliedEditState state = JobAppliedEditState();
+
+  // 获取编辑的详情
+  void fetchAppliedEditView() async {
+    var result = await _jobRepository.fetchAppliedEditView(state.appliedId, cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+      state.appliedEditView = result.data;
+
+      var addHourController = state.formData['add_hours']!['controller'];
+      var totalRoomController = state.formData['total_room']!['controller'];
+      var reasonController = state.formData['reason']!['controller'];
+
+      addHourController.text = state.appliedEditView?.adjustHours ?? "0";
+      totalRoomController.text = state.appliedEditView?.totalRooms.toString();
+      reasonController.text = state.appliedEditView?.coReason ?? "";
+
+      update();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchAppliedEditView();
+  }
+
+  /// 选择时间
+  void pickStartTime() {
+    if (state.appliedEditView == null) return;
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: DateTimeUtils.getDateTime(state.appliedEditView!.startTime ?? ""),
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.appliedEditView!.startTime = DateTimeUtils.formatDate(date);
+        update();
+      },
+      title: "Start Time".tr,
+    );
+  }
+
+  /// 选择时间
+  void pickEndTime() {
+    if (state.appliedEditView == null) return;
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: DateTimeUtils.getDateTime(state.appliedEditView!.endTime ?? ""),
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.appliedEditView!.endTime = DateTimeUtils.formatDate(date);
+        update();
+      },
+      title: "End Time".tr,
+    );
+  }
+
+  /// 选择时间
+  void pickSecurityInTime() {
+    if (state.appliedEditView == null) return;
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: DateTimeUtils.getDateTime(state.appliedEditView!.securityIn ?? ""),
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.appliedEditView!.securityIn = DateTimeUtils.formatDate(date);
+        update();
+      },
+      title: "Security In".tr,
+    );
+  }
+
+  /// 选择时间
+  void pickSecurityOutTime() {
+    if (state.appliedEditView == null) return;
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: DateTimeUtils.getDateTime(state.appliedEditView!.securityOut ?? ""),
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.appliedEditView!.securityOut = DateTimeUtils.formatDate(date);
+        update();
+      },
+      title: "Security Out".tr,
+    );
+  }
+
+  /// 选择时间
+  void pickWorkInTime() {
+    if (state.appliedEditView == null) return;
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: DateTimeUtils.getDateTime(state.appliedEditView!.workIn ?? ""),
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.appliedEditView!.workIn = DateTimeUtils.formatDate(date);
+        update();
+      },
+      title: "Work In".tr,
+    );
+  }
+
+  /// 选择时间
+  void pickWorkOutTime() {
+    if (state.appliedEditView == null) return;
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: DateTimeUtils.getDateTime(state.appliedEditView!.workOut ?? ""),
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.appliedEditView!.workOut = DateTimeUtils.formatDate(date);
+        update();
+      },
+      title: "Work Out".tr,
+    );
+  }
+
+  /// 提交修改
+  void doSubmit() async {
+    if (state.appliedEditView == null) return;
+
+    //输入框的数据赋值
+    TextEditingController totalRoomController = state.formData['total_room']!['controller'];
+    TextEditingController addHourController = state.formData['add_hours']!['controller'];
+    TextEditingController reasonController = state.formData['reason']!['controller'];
+    // 获取文本并尝试转换为整数
+    String totalRoomText = totalRoomController.text;
+    if (totalRoomText.isNotEmpty) {
+      try {
+        // 尝试将文本转换为整数
+        int totalRooms = int.parse(totalRoomText);
+        // 赋值给 state.appliedEditView!.totalRooms
+        state.appliedEditView!.totalRooms = totalRooms;
+      } catch (e) {
+        // 如果转换失败,可以进行错误处理
+        print('Error parsing totalRooms: $e');
+      }
+    } else {
+      // 文本为空时的处理逻辑,例如设置默认值或提示用户
+      print('Total rooms input is empty');
+    }
+
+    state.appliedEditView!.adjustHours = addHourController.text.toString();
+    state.appliedEditView!.coReason = reasonController.text.toString();
+
+    //请求网络提交修改
+    var result = await _jobRepository.editAppliedSingleStaffInfo(state.appliedId, state.appliedEditView!);
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      bus.emit(AppConstant.eventAppliedListRefresh, state.appliedId);
+
+      Get.back();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+}

+ 515 - 0
packages/cpt_uk/lib/modules/job/job_applied_edit/job_applied_edit_page.dart

@@ -0,0 +1,515 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:get/get.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/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 'job_applied_edit_controller.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_edit_state.dart';
+
+/*
+ * Applied列表中,编辑用户的此次工作打卡信息
+ */
+class UKJobAppliedEditPage extends BaseStatefulPage<JobAppliedEditController> {
+  UKJobAppliedEditPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? appliedId) {
+    return Get.start(RouterPath.UKJobAppliedEdit, arguments: {'appliedId': appliedId});
+  }
+
+  @override
+  JobAppliedEditController createRawController() {
+    return JobAppliedEditController();
+  }
+
+  @override
+  State<UKJobAppliedEditPage> createState() => _JobAppliedEditState();
+}
+
+class _JobAppliedEditState extends BaseState<UKJobAppliedEditPage, JobAppliedEditController> {
+  late JobAppliedEditState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.appliedId = Get.arguments['appliedId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return Scaffold(
+        extendBodyBehindAppBar: true,
+        appBar: MyAppBar.appBar(context, "Edit".tr),
+        body: SafeArea(
+          bottom: true,
+          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: [
+                      //工作标题,选择模板
+                      MyTextView(
+                        "Staff Name".tr,
+                        textColor: Colors.white,
+                        fontSize: 15,
+                        marginTop: 15,
+                        isFontRegular: true,
+                      ),
+
+                      //工作标题
+                      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(
+                              state.appliedEditView?.memberName ?? "-",
+                              fontSize: 15,
+                              hint: "Choose Job Title".tr,
+                              textHintColor: ColorConstants.textGrayAECAE5,
+                              isFontMedium: true,
+                              textColor: ColorConstants.white,
+                            ).expanded(),
+                          ],
+                        ),
+                      ),
+
+                      //开始时间
+                      FormRequireText(
+                        text: "Start Time".tr,
+                      ).marginOnly(top: 15),
+
+                      //选择时间
+                      Container(
+                        padding: EdgeInsets.only(left: 16, right: 10),
+                        margin: EdgeInsets.only(top: 10),
+                        height: 45,
+                        decoration: BoxDecoration(
+                          color: 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(
+                              state.appliedEditView?.startTime ?? "-",
+                              fontSize: 14,
+                              hint: "Job Start 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.pickStartTime();
+                      }),
+
+                      //门卫签到时间
+                      MyTextView(
+                        "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),
+                        height: 45,
+                        decoration: BoxDecoration(
+                          color: 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(
+                              state.appliedEditView?.securityIn ?? "-",
+                              fontSize: 14,
+                              hint: "Security In".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();
+                      }),
+
+                      //工作地签到时间
+                      MyTextView(
+                        "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),
+                        height: 45,
+                        decoration: BoxDecoration(
+                          color: 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(
+                              state.appliedEditView?.workIn ?? "-",
+                              fontSize: 14,
+                              hint: "Work In".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.pickWorkInTime();
+                      }),
+
+                      //结束时间
+                      FormRequireText(
+                        text: "End Time".tr,
+                      ).marginOnly(top: 15),
+
+                      //结束时间
+                      Container(
+                        padding: EdgeInsets.only(left: 16, right: 10),
+                        margin: EdgeInsets.only(top: 10),
+                        height: 45,
+                        decoration: BoxDecoration(
+                          color: 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(
+                              state.appliedEditView?.endTime ?? "-",
+                              fontSize: 14,
+                              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.pickEndTime();
+                      }),
+
+                      //门卫签出时间
+                      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),
+                        height: 45,
+                        decoration: BoxDecoration(
+                          color: 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(
+                              state.appliedEditView?.securityOut ?? "-",
+                              fontSize: 14,
+                              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.pickSecurityOutTime();
+                      }),
+
+                      //工作地签出时间
+                      MyTextView(
+                        "Work Out".tr,
+                        textColor: Colors.white,
+                        fontSize: 15,
+                        marginTop: 15,
+                        isFontRegular: true,
+                      ),
+
+                      //工作地签出时间
+                      Container(
+                        padding: EdgeInsets.only(left: 16, right: 10),
+                        margin: EdgeInsets.only(top: 10),
+                        height: 45,
+                        decoration: BoxDecoration(
+                          color: 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(
+                              state.appliedEditView?.workOut ?? "-",
+                              fontSize: 14,
+                              hint: "Work 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.pickWorkOutTime();
+                      }),
+
+                      // + - 小时
+                      Visibility(
+                        visible: state.appliedEditView?.jobUnit == "hour",
+                        child: MyTextView(
+                          "+/- Hours".tr,
+                          textColor: Colors.white,
+                          fontSize: 15,
+                          marginTop: 15,
+                          isFontRegular: true,
+                        ),
+                      ),
+
+                      //+ - 小时输入框
+                      Visibility(
+                        visible: state.appliedEditView?.jobUnit == "hour",
+                        child: CustomTextField(
+                          formKey: "add_hours",
+                          marginLeft: 0,
+                          marginRight: 0,
+                          paddingTop: 0,
+                          paddingBottom: 0,
+                          height: 45,
+                          fillBackgroundColor: Color(0xFF4DCFF6).withOpacity(0.2),
+                          enabled: true,
+                          textInputType: TextInputType.number,
+                          formData: state.formData,
+                          textInputAction: TextInputAction.done,
+                          onSubmit: (key, value) {
+                            FocusScope.of(context).unfocus();
+                          },
+                          marginTop: 10,
+                        ),
+                      ),
+
+                      // 房间计费,房间数量
+                      Visibility(
+                        visible: state.appliedEditView?.jobUnit != "hour",
+                        child: MyTextView(
+                          "Total Rooms".tr,
+                          textColor: Colors.white,
+                          fontSize: 15,
+                          marginTop: 15,
+                          isFontRegular: true,
+                        ),
+                      ),
+
+                      // 房间计费,房间数量输入框
+                      Visibility(
+                        visible: state.appliedEditView?.jobUnit != "hour",
+                        child: CustomTextField(
+                          formKey: "total_room",
+                          marginLeft: 0,
+                          marginRight: 0,
+                          paddingTop: 0,
+                          paddingBottom: 0,
+                          height: 45,
+                          fillBackgroundColor: Color(0xFF4DCFF6).withOpacity(0.2),
+                          enabled: true,
+                          inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
+                          textInputType: TextInputType.number,
+                          formData: state.formData,
+                          textInputAction: TextInputAction.done,
+                          onSubmit: (key, value) {
+                            FocusScope.of(context).unfocus();
+                          },
+                          marginTop: 10,
+                        ),
+                      ),
+
+                      // 修改的理由
+                      MyTextView(
+                        "Reason".tr,
+                        textColor: Colors.white,
+                        fontSize: 15,
+                        marginTop: 15,
+                        isFontRegular: true,
+                      ),
+
+                      //理由的单选
+                      state.appliedEditView != null
+                          ? CustomRadioCheck(
+                              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) {
+                                //修改内存的值
+                                state.appliedEditView!.reasonType = state.appliedEditView!.reasonList![index].value;
+                              },
+                            ).marginOnly(top: 15, bottom: 20)
+                          : CircularProgressIndicator(),
+
+                      IgnoreKeyboardDismiss(
+                        child: Container(
+                          height: 130,
+                          padding: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
+                          decoration: BoxDecoration(
+                            color: Color(0xFF4DCFF6).withOpacity(0.2),
+                            borderRadius: const BorderRadius.all(Radius.circular(5)),
+                          ),
+                          child: TextField(
+                            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.white,
+                                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();
+                            },
+                          ),
+                        ),
+                      ),
+
+                      //提交按钮
+                      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),
+                    ],
+                  ).paddingOnly(left: 15, right: 15),
+                ),
+              ),
+            ),
+          ),
+        ),
+      );
+    });
+  }
+}

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

@@ -0,0 +1,40 @@
+import 'package:domain/entity/response/job_list_applied_edit_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class JobAppliedEditState {
+  //表单的校验与数据
+  Map<String, Map<String, dynamic>> formData = {
+    'add_hours': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': '0',
+      'obsecure': false,
+    },
+    'total_room': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': '0',
+      'obsecure': false,
+    },
+    'reason': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+  };
+
+  JobListAppliedEditEntity? appliedEditView;
+
+  String? appliedId;
+
+  //功能选项
+  final editOption = ['None'.tr, 'Forgot to clock in/out'.tr, 'Technical issue'.tr, 'Others'.tr];
+
+  //选项默认选中索引为0
+  int editOptionPosition = 0;
+}

+ 158 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_controller.dart

@@ -0,0 +1,158 @@
+import 'package:domain/entity/response/staff_detail_entity.dart';
+import 'package:domain/entity/response/staff_labour_history_entity.dart';
+import 'package:domain/repository/job_repository.dart';
+import 'package:get/get.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: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';
+
+class AppliedStaffDetailController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final AppliedStaffDetailState state = AppliedStaffDetailState();
+
+  var _curPage = 1;
+  var _isSearch = false;
+  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;
+    fetchStaffDetail();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchStaffDetail();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchStaffDetail();
+  }
+
+  /// 获取列表数据
+  Future fetchStaffDetail() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    } else if (_isSearch) {
+      LoadingEngine.show();
+    }
+
+    // 并发执行两个请求
+    var futures = [
+      _jobRepository.fetchStaffLabourHistory(
+        state.memberId,
+        state.keyword,
+        curPage: _curPage,
+        cancelToken: cancelToken,
+      ),
+      state.detail == null
+          ? _jobRepository.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>;
+
+    //详情数据
+    if (state.detail == null && detailResult.isSuccess) {
+      state.detail = detailResult.data!;
+    }
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    _isSearch = false;
+    LoadingEngine.dismiss();
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<StaffLabourHistoryRows>? 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) {
+    state.keyword = keyword;
+    //赋值之后刷新
+    // refreshController.callRefresh();
+    _isSearch = true;
+    onRefresh();
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchStaffDetail();
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+  }
+
+  // 去员工的评论列表页面
+  void gotoRemarkHistoryPage() {
+    UKAppliedStaffReviewsPage.startInstance(state.memberId,state.detail?.name,state.detail?.remRate,state.detail?.remNum.toString());
+  }
+
+}

+ 139 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_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:widgets/ext/ex_widget.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 'applied_staff_detail_controller.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 'applied_staff_detail_state.dart';
+import 'staff_detail_widget.dart';
+import 'staff_labour_history_item.dart';
+
+class UKAppliedStaffDetailPage extends BaseStatefulPage<AppliedStaffDetailController> {
+  UKAppliedStaffDetailPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? memberId) {
+    return Get.start(RouterPath.UKJobAppliedStaffDetail, arguments: {'memberId': memberId});
+  }
+
+  @override
+  AppliedStaffDetailController createRawController() {
+    return AppliedStaffDetailController();
+  }
+
+  @override
+  State<UKAppliedStaffDetailPage> createState() => _AppliedStaffDetailState();
+}
+
+class _AppliedStaffDetailState extends BaseState<UKAppliedStaffDetailPage, AppliedStaffDetailController> {
+  late AppliedStaffDetailState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.memberId = Get.arguments['memberId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+          bottom: true,
+          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, "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();
+                        }),
+                      ),
+
+                      //中间搜索布局
+                      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(),
+              ],
+            ),
+          ),
+        );
+    });
+  }
+
+  // 搜索的布局
+  Widget _buildSearchWidget() {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        MyTextView(
+          "Job History",
+          marginLeft: 15,
+          marginTop: 10,
+          fontSize: 17,
+          textColor: ColorConstants.white,
+          isFontMedium: true,
+        ),
+        SearchAppBar(
+          value: state.keyword,
+          searchBarHeight: 38,
+          onSearch: (keyword) {
+            controller.doSearch(keyword);
+          },
+          hintText: "Job Title".tr,
+        ).marginOnly(left: 16.5, right: 1.5, bottom: 10, top: 10),
+      ],
+    );
+  }
+}

+ 15 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/applied_staff_detail_state.dart

@@ -0,0 +1,15 @@
+import 'package:domain/entity/response/staff_detail_entity.dart';
+import 'package:domain/entity/response/staff_labour_history_entity.dart';
+import 'package:flutter/cupertino.dart';
+
+class AppliedStaffDetailState {
+
+  TextEditingController? searchController;
+
+  String? memberId;
+  String keyword = "";
+
+  StaffDetailEntity? detail;
+  List<StaffLabourHistoryRows> datas = [];
+
+}

+ 296 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_detail_widget.dart

@@ -0,0 +1,296 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/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/util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+/*
+ * 员工的信息
+ */
+class StaffDetailWidget extends StatelessWidget {
+  final StaffDetailEntity? detail;
+  final void Function() onRemarkAction;
+
+  StaffDetailWidget({
+    required this.detail,
+    required this.onRemarkAction,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 10),
+      decoration: BoxDecoration(
+        color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(5), // 设置圆角
+      ),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          //头像
+          Center(
+              child: Hero(
+            tag: '112cc8a34e13',
+            child: MyLoadImage(
+              detail?.avatar,
+              width: 100,
+              height: 100,
+            ),
+          )).onTap(() {
+            if (Utils.isNotEmpty(detail?.avatar)) {
+              ImagePreviewEngine.singleImagePreview(context, detail!.avatar!, heroTag: '112cc8a34e13');
+            }
+          }).marginOnly(top: 25, bottom: 15),
+
+          //姓名
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            children: [
+              MyTextView(
+                "Name:".tr,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+                isFontRegular: true,
+              ),
+              MyTextView(
+                detail?.name ?? "-",
+                marginLeft: 5,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+                isFontMedium: true,
+              ).expanded(),
+            ],
+          ).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,
+            children: [
+              MyTextView(
+                "${"NRIC".tr}:",
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+                isFontRegular: true,
+              ),
+              MyTextView(
+                detail?.nric ?? "-",
+                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(
+                detail?.emerPhone ?? "-",
+                marginLeft: 5,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+                isFontMedium: true,
+              ).expanded(),
+            ],
+          ).marginOnly(left: 22, right: 22, top: 10),
+
+          //评分
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            children: [
+              MyTextView(
+                "${"Reviews".tr}:",
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+                isFontRegular: true,
+              ),
+              MyTextView(
+                "${detail?.remRate.toString() ?? "-"} (${detail?.remNum.toString() ?? "0"} Reviews)",
+                marginLeft: 5,
+                textColor: ColorConstants.textGreen0AC074,
+                fontSize: 14,
+                onClick: onRemarkAction,
+                isFontMedium: true,
+              ).expanded(),
+            ],
+          ).marginOnly(left: 22, right: 22, top: 10, bottom: 26),
+
+        ],
+      ),
+    );
+  }
+}

+ 333 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_detail/staff_labour_history_item.dart

@@ -0,0 +1,333 @@
+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: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';
+
+/**
+ * 员工的做工记录
+ */
+class StaffLabourHistoryItem extends StatelessWidget {
+  final int index;
+  final StaffLabourHistoryRows item;
+
+  StaffLabourHistoryItem({
+    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(
+                "Job Date".tr+":",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期
+              MyTextView(
+                item.jobDate ?? "-",
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ),
+
+          //员工姓名
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Staff Name:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //姓名
+              MyTextView(
+                item.staffName ?? "-",
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          //工作标题(模板)
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Job Title:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //标题
+              MyTextView(
+                item.jobTitle ?? "-",
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          //部门
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Outlet:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //部门
+              MyTextView(
+                item.outletName ?? "-",
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作开始时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Start Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.startTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 门卫签到时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security In:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.securityIn?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.securityIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作地签到时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Work In:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.workIn?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.workIn?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          //工作结束时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "End Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.endTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作地签出时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Work Out:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.workOut?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.workOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 门卫签出时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Security Out:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.securityOut?.time ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: item.securityOut?.changed == 1 ? ColorConstants.textRedFF6262 : Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 申请时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Applied At:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                item.appliedAt ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Status:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                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(),
+            ],
+          ).marginOnly(top: 12),
+
+        ],
+      ),
+    );
+  }
+}

+ 108 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_controller.dart

@@ -0,0 +1,108 @@
+import 'package:domain/entity/response/staff_remark_history_entity.dart';
+import 'package:domain/repository/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 'applied_staff_reviews_state.dart';
+
+class AppliedStaffReviewsController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final AppliedStaffReviewsState state = AppliedStaffReviewsState();
+
+  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;
+    fetchStaffReviews();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchStaffReviews();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchStaffReviews();
+  }
+
+  /// 获取列表数据
+  Future fetchStaffReviews() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    var listResult = await _jobRepository.fetchStaffRemarkHistory(state.memberId, curPage: _curPage, cancelToken: cancelToken);
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<StaffRemarkHistoryRows>? 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();
+    fetchStaffReviews();
+  }
+}

+ 151 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_item.dart

@@ -0,0 +1,151 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/staff_remark_history_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';
+import 'package:widgets/shatter/rating_widget.dart';
+
+/**
+ * 员工的评价记录
+ */
+class StaffReviewsItem extends StatelessWidget {
+  final int index;
+  final StaffRemarkHistoryRows item;
+
+  StaffReviewsItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: EdgeInsets.only(bottom: 25, left: 21,right: 21,top: 18.5),
+      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(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            item.company ?? "",
+            isFontRegular: true,
+            textColor: Colors.white,
+            fontSize: 17,
+          ),
+
+          //态度评分
+          Row(
+            children: [
+              MyTextView(
+                "Attitude".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 15,
+              ).expanded(flex: 2),
+              RatingWidget(
+                nomalImage: Assets.baseServiceRatingUnselected,
+                selectImage: Assets.baseServiceRatingSelected,
+                size: 21,
+                padding: 5,
+                selectAble: false,
+                integerOnly: true,
+                value: item.attitudeRate,
+                onRatingUpdate: (value) {},
+              ).expanded(flex: 3)
+            ],
+          ).marginOnly(top: 15),
+
+          //表现评分
+          Row(
+            children: [
+              MyTextView(
+                "Performance".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 15,
+              ).expanded(flex: 2),
+              RatingWidget(
+                nomalImage: Assets.baseServiceRatingUnselected,
+                selectImage: Assets.baseServiceRatingSelected,
+                size: 21,
+                padding: 5,
+                selectAble: false,
+                integerOnly: true,
+                value: item.performanceRate,
+                onRatingUpdate: (value) {},
+              ).expanded(flex: 3)
+            ],
+          ).marginOnly(top: 15),
+
+          //经验评分
+          Row(
+            children: [
+              MyTextView(
+                "Experience".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 15,
+              ).expanded(flex: 2),
+              RatingWidget(
+                nomalImage: Assets.baseServiceRatingUnselected,
+                selectImage: Assets.baseServiceRatingSelected,
+                size: 21,
+                padding: 5,
+                selectAble: false,
+                integerOnly: true,
+                value: item.experienceRate,
+                onRatingUpdate: (value) {},
+              ).expanded(flex: 3)
+            ],
+          ).marginOnly(top: 15),
+
+          //着装评分
+          Row(
+            children: [
+              MyTextView(
+                "Grooming".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 15,
+              ).expanded(flex: 2),
+              RatingWidget(
+                nomalImage: Assets.baseServiceRatingUnselected,
+                selectImage: Assets.baseServiceRatingSelected,
+                size: 21,
+                padding: 5,
+                selectAble: false,
+                integerOnly: true,
+                value: item.groomingRate,
+                onRatingUpdate: (value) {},
+              ).expanded(flex: 3)
+            ],
+          ).marginOnly(top: 15),
+
+          MyTextView(
+            item.feedback ?? "",
+            textColor: Colors.white,
+            fontSize: 15,
+            isFontRegular: true,
+            borderColor: Color(0XFF6D92BA),
+            borderWidth: 0.5,
+            boxHeight: 130,
+            boxWidth: double.infinity,
+            paddingTop: 15,
+            paddingLeft: 12.5,
+            paddingRight: 12.5,
+            paddingBottom: 15,
+            marginTop: 18,
+          ),
+
+        ],
+      ),
+    );
+  }
+}

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

@@ -0,0 +1,162 @@
+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:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/shatter/rating_widget.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'applied_staff_reviews_controller.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 'applied_staff_reviews_item.dart';
+import 'applied_staff_reviews_state.dart';
+
+/*
+ * 员工的评论页面
+ */
+class UKAppliedStaffReviewsPage extends BaseStatefulPage<AppliedStaffReviewsController> {
+  UKAppliedStaffReviewsPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? memberId, String? staffName, double? reviews, String? reviewCount) {
+    return Get.start(
+      RouterPath.UKJobAppliedStaffReview,
+      arguments: {'memberId': memberId, 'staffName': staffName, 'reviews': reviews, 'reviewCount': reviewCount},
+    );
+  }
+
+  @override
+  AppliedStaffReviewsController createRawController() {
+    return AppliedStaffReviewsController();
+  }
+
+  @override
+  State<UKAppliedStaffReviewsPage> createState() => _AppliedStaffReviewsState();
+}
+
+class _AppliedStaffReviewsState extends BaseState<UKAppliedStaffReviewsPage, AppliedStaffReviewsController> {
+  late AppliedStaffReviewsState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.memberId = Get.arguments['memberId'];
+    state.staffName = Get.arguments['staffName'];
+    state.reviews = Get.arguments['reviews'];
+    state.reviewCount = Get.arguments['reviewCount'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: true,
+        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(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            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: _buildRemarkWidget(),
+                    ),
+
+                    //底部工作历史列表
+                    SliverList(
+                        delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                        return StaffReviewsItem(index: index, item: state.datas[index]);
+                      },
+                      childCount: state.datas.length,
+                    ))
+                  ],
+                ),
+              ).expanded(),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+
+  Widget _buildRemarkWidget() {
+    return Container(
+      padding: EdgeInsets.only(bottom: 22, left: 21, right: 21, top: 18.5),
+      margin: EdgeInsets.only(left: 15, right: 15, top: 14.5, bottom: 5),
+      decoration: BoxDecoration(
+        color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(5), // 设置圆角
+      ),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            state.staffName ?? "-",
+            fontSize: 17,
+            textColor: ColorConstants.white,
+            isFontMedium: true,
+            marginBottom: 8,
+          ),
+          Row(
+            children: [
+              RatingWidget(
+                nomalImage: Assets.baseServiceRatingUnselected,
+                selectImage: Assets.baseServiceRatingSelected,
+                size: 21,
+                padding: 5,
+                selectAble: false,
+                integerOnly: false,
+                value: state.reviews ?? 0,
+                onRatingUpdate: (value) {},
+              ),
+              MyTextView(
+                "${state.reviews.toString()} (${state.reviewCount} Reviews)",
+                fontSize: 14,
+                marginLeft: 12,
+                textColor: ColorConstants.textYellowF8AE00,
+                isFontMedium: true,
+              ).expanded(),
+            ],
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 10 - 0
packages/cpt_uk/lib/modules/job/job_applied_staff_reviews/applied_staff_reviews_state.dart

@@ -0,0 +1,10 @@
+import 'package:domain/entity/response/staff_remark_history_entity.dart';
+
+class AppliedStaffReviewsState {
+  String? memberId;
+  String? staffName;
+  double? reviews;
+  String? reviewCount;
+
+  List<StaffRemarkHistoryRows> datas = [];
+}

+ 98 - 0
packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_controller.dart

@@ -0,0 +1,98 @@
+import 'package:domain/entity/response/job_list_applied_work_flow_entity.dart';
+import 'package:domain/repository/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 'applied_workflow_state.dart';
+
+/**
+ * 已申请的员工状态审核流
+ */
+class  AppliedWorkflowController extends GetxController with DioCancelableMixin{
+  final JobRepository _jobRepository = Get.find();
+  final AppliedWorkflowState state = AppliedWorkflowState();
+
+  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 _jobRepository.fetchAppliedWorkFlow(
+      state.appliedId,
+      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<JobListAppliedWorkFlowRecords>? 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();
+  }
+}

+ 228 - 0
packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_item.dart

@@ -0,0 +1,228 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/job_list_applied_work_flow_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 AppliedWorkFlowItem extends StatelessWidget {
+  final int index;
+  final JobListAppliedWorkFlowRecords item;
+
+  AppliedWorkFlowItem({
+    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: [
+          //Node
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Node:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.nodeName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ),
+
+          // assigneeType
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Type:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期时间
+              MyTextView(
+                item.assigneeTypeShow ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // Designation
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Designation:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //人数
+              MyTextView(
+                item.designationShow ?? "-",
+                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: "Approved" == item.statusShow
+                    ? ColorConstants.textGreen05DC82
+                    : "Rejected" == item.statusShow
+                    ? ColorConstants.textRedFF6262
+                    : "Recall" == item.statusShow
+                    ? ColorConstants.textYellowFFBB1B
+                    : ColorConstants.textBlue06D9FF,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // Operator
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Operator:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                item.auditName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 操作时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Audit Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.auditTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created 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),
+
+          // Remark
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Remark:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.auditMark ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+        ],
+      ),
+    );
+  }
+}

+ 102 - 0
packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_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 'applied_workflow_controller.dart';
+import 'applied_workflow_state.dart';
+import 'applied_workflow_item.dart';
+
+/*
+ * 已申请的员工-状态工作流列表
+ */
+class UKAppliedWorkflowPage extends BaseStatefulPage<AppliedWorkflowController> {
+  UKAppliedWorkflowPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? appliedId) {
+    return Get.start(RouterPath.UKJobAppliedWorkflow,arguments: {'appliedId': appliedId});
+  }
+
+  @override
+  AppliedWorkflowController createRawController() {
+    return AppliedWorkflowController();
+  }
+
+  @override
+  State<UKAppliedWorkflowPage> createState() => _AppliedWorkflowState();
+
+}
+
+class _AppliedWorkflowState extends BaseState<UKAppliedWorkflowPage, AppliedWorkflowController> {
+
+  late AppliedWorkflowState 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: true,
+          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, "Workflow".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 AppliedWorkFlowItem(index: index,item: state.datas[index]);
+                            },
+                            childCount: state.datas.length,
+                          ))
+                    ],
+                  ),
+                ).marginOnly(top: 5,bottom: 5).expanded(),
+              ],
+            ).marginOnly(top: 10),
+          ),
+        );
+    });
+  }
+}
+
+

+ 10 - 0
packages/cpt_uk/lib/modules/job/job_applied_workflow/applied_workflow_state.dart

@@ -0,0 +1,10 @@
+import 'package:domain/entity/response/job_list_applied_work_flow_entity.dart';
+
+class AppliedWorkflowState {
+
+  String? appliedId;
+
+  //页面的列表数据
+  List<JobListAppliedWorkFlowRecords> datas = [];
+
+}

+ 13 - 8
packages/cpt_uk/lib/modules/job/job_category/job_category_controller.dart

@@ -1,10 +1,17 @@
+import 'package:cpt_uk/modules/job/job_list/job_list_page.dart';
+import 'package:cpt_uk/modules/job/labour_request_list/labour_request_list_page.dart';
+import 'package:cpt_uk/modules/job/template_list/template_list_page.dart';
 import 'package:domain/entity/home_module.dart';
 import 'package:get/get.dart';
-import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:widgets/widget_export.dart';
+import '../../review/attendance_review_list/attendance_review_page.dart';
+import '../../review/labour_review_list/labour_review_page.dart';
 import 'job_category_state.dart';
 
+/*
+ * 工作相关的子模块分类列表
+ */
 class JobCategoryController extends GetxController with DioCancelableMixin {
   final JobCategoryState state = JobCategoryState();
 
@@ -23,19 +30,19 @@ class JobCategoryController extends GetxController with DioCancelableMixin {
   void gotoModulePage(HomeModule module) {
     switch (module.key) {
       case 'job_template':
-        ToastEngine.show("点击 job_template 模块");
+        UKTemplateListPage.startInstance();
         break;
       case 'labour_request':
-        ToastEngine.show("点击 labour_request 模块");
+        UKLabourRequestListPage.startInstance();
         break;
       case 'lab_review':
-        ToastEngine.show("点击 lab_review 模块");
+        UKLabourReviewPage.startInstance();
         break;
       case 'job_list':
-        ToastEngine.show("点击 job_list 模块");
+        UKJobListPage.startInstance();
         break;
       case 'attendance_review':
-        ToastEngine.show("点击 attendance_review 模块");
+        UKAttendanceReviewPage.startInstance();
         break;
     }
   }
@@ -45,6 +52,4 @@ class JobCategoryController extends GetxController with DioCancelableMixin {
     state.datas.clear();
     super.onClose();
   }
-
-
 }

+ 204 - 0
packages/cpt_uk/lib/modules/job/job_list/job_list_controller.dart

@@ -0,0 +1,204 @@
+import 'package:domain/entity/response/job_list_entity.dart';
+import 'package:domain/entity/response/job_list_index_entity.dart';
+import 'package:domain/repository/job_repository.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/dialog/dialog_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:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../job_applied/job_applied_page.dart';
+import '../job_list_detail/job_list_detail_page.dart';
+import 'job_list_filter.dart';
+import 'job_list_state.dart';
+
+class JobListController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final JobListState state = JobListState();
+
+  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;
+    fetchNotifyList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchNotifyList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchNotifyList();
+  }
+
+  /// 获取服务器数据,通知消息列表
+  Future fetchNotifyList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    // 并发执行两个请求
+    var futures = [
+      _jobRepository.fetchJobListTable(
+        state.keyword,
+        DateTimeUtils.formatDate(state.selectedStartDate, format: "yyyy-MM-dd"),
+        DateTimeUtils.formatDate(state.selectedEndDate, format: "yyyy-MM-dd"),
+        state.selectedStatusId,
+        state.selectedDepartmentId,
+        curPage: _curPage,
+        cancelToken: cancelToken,
+      ),
+      state.indexOptions == null
+          ? _jobRepository.fetchJobListIndex(
+              cancelToken: cancelToken,
+            )
+          : Future(() => HttpResult(isSuccess: true).convert(data: state.indexOptions!)),
+    ];
+
+    //拿到结果
+    var results = await Future.wait(futures);
+    var listResult = results[0] as HttpResult<JobListEntity>;
+    var optionResult = results[1] as HttpResult<JobListIndexEntity>;
+
+    //选项数据
+    if (state.indexOptions == null && optionResult.isSuccess) {
+      state.indexOptions = optionResult.data!;
+    }
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<JobListRows>? 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) {
+    state.keyword = keyword;
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  // 清空搜索条件
+  void resetFiltering() {
+    state.keyword = "";
+    state.searchController.text = "";
+
+    state.selectedStartDate = null;
+    state.selectedEndDate = null;
+    state.selectedStatusId = null;
+    state.selectedDepartmentId = null;
+
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  //展示筛选的弹窗
+  void showFilterDialog() {
+    if (state.indexOptions != null) {
+      DialogEngine.show(
+        widget: JobListFilter(
+          optionResult: state.indexOptions!,
+          selectedStartDate: state.selectedStartDate,
+          selectedEndDate: state.selectedEndDate,
+          selectedStatusId: state.selectedStatusId,
+          selectedDepartmentId: state.selectedDepartmentId,
+          onFilterAction: (startDate, endDate, statusId, departmentId) {
+            state.selectedStartDate = startDate;
+            state.selectedEndDate = endDate;
+            state.selectedStatusId = statusId;
+            state.selectedDepartmentId = departmentId;
+
+            //赋值之后刷新
+            refreshController.callRefresh();
+          },
+        ),
+        position: DialogPosition.top,
+        animType: DialogAnimation.fade,
+      );
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchNotifyList();
+  }
+
+  @override
+  void onClose() {
+    state.datas.clear();
+    super.onClose();
+  }
+
+  /// 去详情页面
+  void gotoJobDetailPage(JobListRows data) {
+    UKJobListDetailPage.startInstance(data.jobId.toString());
+  }
+
+  /// 去已申请的成员列表
+  void gotoJobAppliedPage(JobListRows data) {
+    UKJobAppliedPage.startInstance(data.jobId.toString());
+  }
+}

+ 360 - 0
packages/cpt_uk/lib/modules/job/job_list/job_list_filter.dart

@@ -0,0 +1,360 @@
+import 'dart:ui';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_index_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:shared/utils/screen_util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/my_button.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/picker/option_pick_util.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 用工请求列表的筛选
+ */
+class JobListFilter extends StatefulWidget {
+  void Function(DateTime? selectedStartDate, DateTime? selectedEndDate, String? selectedStatusId, String? selectedDepartmentId)? onFilterAction;
+  JobListIndexEntity optionResult;
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedStatusId;
+  String? selectedDepartmentId;
+
+  JobListFilter({
+    required this.optionResult,
+    required this.selectedStartDate,
+    required this.selectedEndDate,
+    required this.selectedStatusId,
+    required this.selectedDepartmentId,
+    this.onFilterAction,
+  });
+
+  @override
+  State<JobListFilter> createState() => _JobListFilterState();
+}
+
+class _JobListFilterState extends State<JobListFilter> {
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedStatusId;
+  String? selectedDepartmentId;
+
+  @override
+  void initState() {
+    super.initState();
+    this.selectedStartDate = widget.selectedStartDate;
+    this.selectedEndDate = widget.selectedEndDate;
+    this.selectedStatusId = widget.selectedStatusId;
+    this.selectedDepartmentId = widget.selectedDepartmentId;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        SizedBox(
+          height: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1,
+        ),
+        Container(
+          padding: const EdgeInsets.only(left: 15, right: 15, top: 17.5, bottom: 20),
+          width: double.infinity,
+          decoration: const BoxDecoration(
+            color: Colors.white,
+          ),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              //部门
+              MyTextView(
+                "Outlet".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择部门
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedDepartmentId == null || selectedDepartmentId == "0"
+                          ? ""
+                          : widget.optionResult.departmentList!.firstWhere((element) => element.value.toString() == selectedDepartmentId).txt!,
+                      hint: "Choose Outlet".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      fontSize: 14,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerOutlet();
+              }),
+
+              //状态
+              MyTextView(
+                "Status".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                marginTop: 11,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择状态
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStatusId == null || selectedStatusId == "0"
+                          ? ""
+                          : widget.optionResult.statusList!.firstWhere((element) => element.value.toString() == selectedStatusId).txt!,
+                      fontSize: 14,
+                      hint: "Choose Status".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStatus();
+              }),
+
+              //开始时间
+              MyTextView(
+                "Start Date".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                marginTop: 11,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择时间
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStartDate == null ? "" : DateTimeUtils.formatDate(selectedStartDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose Start Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStartDate();
+              }),
+
+              //结束日期
+              MyTextView(
+                "End Date".tr,
+                fontSize: 14,
+                marginTop: 11,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择结束日期
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedEndDate == null ? "" : DateTimeUtils.formatDate(selectedEndDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose End Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerEndDate();
+              }),
+
+              //按钮组
+              Row(
+                children: [
+                  MyButton(
+                    onPressed: () {
+                      //只是Reset当前的弹窗筛选选项
+                      widget.selectedStartDate = null;
+                      widget.selectedEndDate = null;
+                      widget.selectedStatusId = null;
+                      widget.selectedDepartmentId = null;
+
+                      setState(() {
+                        selectedStartDate = null;
+                        selectedEndDate = null;
+                        selectedStatusId = null;
+                        selectedDepartmentId = null;
+                      });
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#FFBB1B"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                  SizedBox(width: 15),
+                  MyButton(
+                    onPressed: () {
+                      onCancel();
+                      widget.onFilterAction?.call(selectedStartDate, selectedEndDate, selectedStatusId, selectedDepartmentId);
+                    },
+                    text: "Filter".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#0AC074"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                ],
+              ).marginOnly(top: 20),
+            ],
+          ),
+        ),
+        Center(child: MyAssetImage(Assets.baseServiceDialogDeleteIcon, width: 26.5, height: 26.5).marginOnly(top: 35)).onTap(() {
+          onCancel();
+        }),
+      ],
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  /// 筛选开始日期
+  void pickerStartDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedStartDate = date;
+        });
+      },
+      title: "Start Date".tr,
+    );
+  }
+
+  /// 筛选结束日期
+  void pickerEndDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedEndDate ?? selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedEndDate = date;
+        });
+      },
+      title: "End Date".tr,
+    );
+  }
+
+  /// 筛选部门
+  void pickerOutlet() {
+    int selectedDepartmentIndex;
+    if (selectedDepartmentId == null) {
+      selectedDepartmentIndex = 0;
+    } else {
+      selectedDepartmentIndex = widget.optionResult.departmentList!.indexWhere((department) => department.value.toString() == selectedDepartmentId);
+    }
+
+    if (selectedDepartmentIndex < 0) {
+      selectedDepartmentIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: widget.optionResult.departmentList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedDepartmentIndex,
+      onPickerChanged: (_, index) {
+        setState(() {
+          selectedDepartmentId = widget.optionResult.departmentList![index].value!.toString();
+        });
+      },
+    );
+  }
+
+  /// 筛选状态
+  void pickerStatus() {
+    int selectedStatusIndex;
+    if (selectedStatusId == null) {
+      selectedStatusIndex = 0;
+    } else {
+      selectedStatusIndex = widget.optionResult.statusList!.indexWhere((department) => department.value.toString() == selectedStatusId);
+    }
+
+    if (selectedStatusIndex < 0) {
+      selectedStatusIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: widget.optionResult.statusList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedStatusIndex,
+      onPickerChanged: (_, index) {
+        setState(() {
+          selectedStatusId = widget.optionResult.statusList![index].value!.toString();
+        });
+      },
+    );
+  }
+}

+ 210 - 0
packages/cpt_uk/lib/modules/job/job_list/job_list_item.dart

@@ -0,0 +1,210 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/job_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_button.dart';
+import 'package:widgets/my_text_view.dart';
+
+/**
+ * 用工请求的主页面列表Item
+ */
+class JobListItem extends StatelessWidget {
+  final int index;
+  final JobListRows item;
+  final VoidCallback? onDetailAction;
+  final VoidCallback? onAppliedAction;
+
+  JobListItem({
+    required this.index,
+    required this.item,
+    this.onDetailAction,
+    this.onAppliedAction,
+  });
+
+  @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: [
+          //工作标题
+          MyTextView(
+            item.jobTitle ?? "-",
+            isFontMedium: true,
+            textColor: ColorConstants.textYellowFFBB1B,
+            fontSize: 14,
+            textDecoration: TextDecoration.underline,
+            decorationColor: ColorConstants.textYellowFFBB1B,
+            // 可选,设置下划线的颜色
+            decorationThickness: 2.0,
+            // 可选,设置下划线的粗细
+            decorationStyle: TextDecorationStyle.solid, // 可选,设置下划线的样式
+          ),
+
+          // 部门
+          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(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 工作日期时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Datetime:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期时间
+              MyTextView(
+                item.jobTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 人数
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "No. of Staff:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //人数
+              MyTextView(
+                item.staffShow ?? "",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: ColorConstants.textYellowFFBB1B,
+                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: "Completed" == item.statusShow
+                    ? ColorConstants.textGreen05DC82
+                    : "Cancelled" == item.statusShow
+                        ? ColorConstants.textRedFF6262
+                        : "Revised" == item.statusShow || "Pending" == item.statusShow
+                            ? ColorConstants.textYellowFFBB1B
+                            : ColorConstants.textBlue06D9FF,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created 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("detail") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onDetailAction?.call();
+                    },
+                    text: "Detail".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor(
+                      "#56AAFF",
+                    ),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+              ],
+            ).marginOnly(top: 18, bottom: 2),
+          ),
+        ],
+      ),
+    ).onTap(() {
+      onAppliedAction?.call();
+    });
+  }
+}

+ 143 - 0
packages/cpt_uk/lib/modules/job/job_list/job_list_page.dart

@@ -0,0 +1,143 @@
+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: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/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'job_list_item.dart';
+import 'job_list_controller.dart';
+import 'job_list_state.dart';
+
+/*
+ * 用工请求的主页列表
+ */
+class UKJobListPage extends BaseStatefulPage<JobListController> {
+  UKJobListPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKJobList);
+  }
+
+  @override
+  JobListController createRawController() {
+    return JobListController();
+  }
+
+  @override
+  State<UKJobListPage> createState() => _JobListState();
+}
+
+class _JobListState extends BaseState<UKJobListPage, JobListController> {
+  late JobListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+          bottom: true,
+          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.searchTitleBar(
+                  context,
+                  value: state.keyword,
+                  hintText: 'Title'.tr,
+                  controller: state.searchController,
+                  onSearch: (keyword) {
+                    controller.doSearch(keyword);
+                  },
+                  actions: [
+                    //重置按钮
+                    MyButton(
+                      onPressed: () {
+                        FocusScope.of(context).unfocus();
+                        controller.resetFiltering();
+                      },
+                      text: "Reset".tr,
+                      textColor: ColorConstants.white,
+                      backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+                      radius: 17.25,
+                      minWidth: 60,
+                      minHeight: 35,
+                    ).marginOnly(right: 15),
+
+                    //筛选图标
+                    const MyAssetImage(
+                      Assets.baseServiceTitleBarFilterIcon,
+                      width: 24,
+                      height: 16.5,
+                    ).onTap(() {
+                      FocusScope.of(context).unfocus();
+                      controller.showFilterDialog();
+                    }).marginOnly(right: 15),
+                  ],
+                ),
+                //底部的列表
+                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 JobListItem(
+                            index: index,
+                            item: state.datas[index],
+                            onDetailAction: (){
+                              controller.gotoJobDetailPage(state.datas[index]);
+                            },
+                            onAppliedAction: (){
+                              controller.gotoJobAppliedPage(state.datas[index]);
+                            },
+                          );
+                        },
+                        childCount: state.datas.length,
+                      ))
+                    ],
+                  ),
+                ).marginOnly(top: 5,bottom: 5).expanded(),
+              ],
+            ),
+          ),
+        );
+    });
+  }
+}

+ 18 - 0
packages/cpt_uk/lib/modules/job/job_list/job_list_state.dart

@@ -0,0 +1,18 @@
+import 'package:domain/entity/response/job_list_entity.dart';
+import 'package:domain/entity/response/job_list_index_entity.dart';
+
+import 'package:flutter/material.dart';
+
+class JobListState {
+  //筛选条件
+  final TextEditingController searchController = TextEditingController();
+  String keyword = "";
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedStatusId;
+  String? selectedDepartmentId;
+
+  //页面的列表数据
+  List<JobListRows> datas = [];
+  JobListIndexEntity? indexOptions;
+}

+ 42 - 0
packages/cpt_uk/lib/modules/job/job_list_detail/job_list_detail_controller.dart

@@ -0,0 +1,42 @@
+import 'package:domain/repository/job_repository.dart';
+import 'package:get/get.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'job_list_detail_state.dart';
+
+class JobListDetailController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final JobListDetailState state = JobListDetailState();
+
+
+  /// 获取工作详情数据
+  void fetchJobListDetail() async {
+    var result = await _jobRepository.fetchJobListDetail(
+      state.jobId,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      state.jobListDetail = result.data;
+      state.selectedStartTime = state.jobListDetail?.startTime;
+      state.selectedEndTime = state.jobListDetail?.endTime;
+      state.noStaff = state.jobListDetail?.needNum.toString() == "0" ? "" : state.jobListDetail?.needNum.toString();
+      var needNumController = state.formData['no_of_staff']!['controller'];
+      needNumController.text = state.noStaff;
+      state.selectedJobTitle = state.jobListDetail?.jobTitle;
+      state.selectedDepartmentId = state.jobListDetail?.departmentId;
+
+      update();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchJobListDetail();
+  }
+
+}

+ 240 - 0
packages/cpt_uk/lib/modules/job/job_list_detail/job_list_detail_page.dart

@@ -0,0 +1,240 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_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: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/my_appbar.dart';
+import 'package:widgets/my_text_view.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 'job_list_detail_controller.dart';
+import 'job_list_detail_state.dart';
+
+class UKJobListDetailPage extends BaseStatefulPage<JobListDetailController> {
+  UKJobListDetailPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? jobId) {
+    return Get.start(RouterPath.UKJobListDetail, arguments: {'jobId': jobId});
+  }
+
+  @override
+  JobListDetailController createRawController() {
+    return JobListDetailController();
+  }
+
+  @override
+  State<UKJobListDetailPage> createState() => _JobListDetailState();
+}
+
+class _JobListDetailState extends BaseState<UKJobListDetailPage, JobListDetailController> {
+  late JobListDetailState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.jobId = Get.arguments['jobId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return Scaffold(
+        extendBodyBehindAppBar: true,
+        appBar: MyAppBar.appBar(context, "Job Detail".tr),
+        body: SafeArea(
+          bottom: true,
+          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: [
+                      //工作标题,选择模板
+                      FormRequireText(
+                        text: "Job Title".tr,
+                      ).marginOnly(top: 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(
+                              state.selectedJobTitle ?? "-",
+                              fontSize: 14,
+                              isFontMedium: true,
+                              textColor: ColorConstants.white,
+                            ).expanded(),
+                          ],
+                        ),
+                      ),
+
+                      //开始时间
+                      FormRequireText(
+                        text: "Start Time".tr,
+                      ).marginOnly(top: 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(
+                              state.selectedStartTime ?? "-",
+                              fontSize: 14,
+                              isFontMedium: true,
+                              textColor: ColorConstants.white,
+                            ).expanded(),
+                          ],
+                        ),
+                      ),
+
+                      //结束时间
+                      FormRequireText(
+                        text: "End Time".tr,
+                      ).marginOnly(top: 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(
+                              state.selectedEndTime ?? "-",
+                              fontSize: 14,
+                              isFontMedium: true,
+                              textColor: ColorConstants.white,
+                            ).expanded(),
+                          ],
+                        ),
+                      ),
+
+                      //工作选择部门
+                      FormRequireText(
+                        text: "Outlet".tr,
+                      ).marginOnly(top: 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(
+                              state.selectedDepartmentId == null || state.selectedDepartmentId == "0"
+                                  ? ""
+                                  : state.jobListDetail!.departmentList?.firstWhere((element) {
+                                        return element.value.toString() == state.selectedDepartmentId!;
+                                      }, orElse: () => JobListDetailDepartmentList()).txt ?? "",
+                              fontSize: 14,
+                              hint: "Choose Outlet".tr,
+                              textHintColor: ColorConstants.textGrayAECAE5,
+                              isFontMedium: true,
+                              textColor: ColorConstants.white,
+                            ).expanded(),
+                          ],
+                        ),
+                      ),
+
+                      //需要的人数
+                      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: Color(0xFF4DCFF6).withOpacity(0.5),
+                        enabled: false,
+                        inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
+                        textInputType: TextInputType.number,
+                        formData: state.formData,
+                        textInputAction: TextInputAction.done,
+                        onSubmit: (key, value) {
+                          FocusScope.of(context).unfocus();
+                        },
+                        marginTop: 10,
+                      ),
+                    ],
+                  ).paddingOnly(left: 15, right: 15),
+                ),
+              ),
+            ),
+          ),
+        ),
+      );
+    });
+  }
+}

+ 30 - 0
packages/cpt_uk/lib/modules/job/job_list_detail/job_list_detail_state.dart

@@ -0,0 +1,30 @@
+import 'package:domain/entity/response/job_list_detail_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class JobListDetailState {
+
+  String? jobId;  //编辑和详情需要用到ID
+
+  //页面对应的详情数据
+  JobListDetailEntity? jobListDetail;
+
+  //页面对应的选择的条件
+  String? selectedJobTitle;
+  String? selectedStartTime;
+  String? selectedEndTime;
+  String? selectedDepartmentId;
+  String? noStaff;  //成员数量
+
+  //表单的校验与数据
+  Map<String, Map<String, dynamic>> formData = {
+    'no_of_staff': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter No. of Staff'.tr,
+      'obsecure': false,
+    },
+  };
+
+}

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

@@ -0,0 +1,219 @@
+import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'package:domain/repository/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/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/util.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+
+import 'labour_request_add_state.dart';
+
+class LabourRequestAddController extends GetxController {
+  final LabourRepository _labourRepository = Get.find();
+  final LabourRequestAddState state = LabourRequestAddState();
+
+  /// 获取首页的数据
+  void fetchRequestDetail() async {
+    //获取到数据
+    Future<HttpResult<LabourRequestEditIndexEntity>> taskFuture;
+    if (state.pageType != 0 && Utils.isNotEmpty(state.appliedId) && state.appliedId != "0") {
+      taskFuture = _labourRepository.fetchLabourRequestEditDetail(state.appliedId);
+    } else {
+      taskFuture = _labourRepository.fetchLabourRequestAddOption();
+    }
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      state.labReqOption = result.data;
+      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();
+      var needNumController = state.formData['no_of_staff']!['controller'];
+      needNumController.text = state.noStaff;
+      var amountController = state.formData['amount']!['controller'];
+      amountController.text = state.labReqOption?.amount ?? "";
+      state.selectedTemplateId = state.labReqOption?.templateId;
+      state.selectedDepartmentId = state.labReqOption?.departmentId;
+      //时薪还是房间计费
+      state.chargeOptionId = state.labReqOption?.chargeList.firstWhere((element) => element.checked == "checked").value;
+
+      update();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    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;
+    }
+
+    Future<HttpResult> taskFuture;
+    if (state.pageType != 0 && Utils.isNotEmpty(state.appliedId) && state.appliedId != "0") {
+      taskFuture = _labourRepository.editLabourRequestSubmit(
+        state.appliedId,
+        state.selectedTemplateId,
+        DateTimeUtils.formatDate(state.selectedStartTime),
+        DateTimeUtils.formatDate(state.selectedEndTime),
+        state.selectedDepartmentId,
+        needNum,
+        state.chargeOptionId,
+        state.labReqOption?.serviceType == 1 ? amount : null,
+      );
+    } else {
+      taskFuture = _labourRepository.addLabourRequestSubmit(
+        state.selectedTemplateId,
+        DateTimeUtils.formatDate(state.selectedStartTime),
+        DateTimeUtils.formatDate(state.selectedEndTime),
+        state.selectedDepartmentId,
+        needNum,
+        state.chargeOptionId,
+        state.labReqOption?.serviceType == 1 ? amount : null,
+      );
+    }
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //根据类型刷新
+      if (state.pageType != 0 && Utils.isNotEmpty(state.appliedId) && state.appliedId != "0") {
+        //编辑就发送指定的 requestId
+        bus.emit(AppConstant.eventLabourRequestRefresh, state.appliedId);
+      } else {
+        //新增的就发送空
+        bus.emit(AppConstant.eventLabourRequestRefresh, "");
+      }
+
+      Get.back();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  // 筛选工作模板
+  void pickJobTitle() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    int selectedTemplateIndex;
+    if (state.selectedTemplateId == null) {
+      selectedTemplateIndex = 0;
+    } else {
+      selectedTemplateIndex = state.labReqOption!.templateList.indexWhere((department) => department.value.toString() == state.selectedTemplateId);
+    }
+
+    if (selectedTemplateIndex < 0) {
+      selectedTemplateIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.labReqOption!.templateList.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedTemplateIndex,
+      onPickerChanged: (_, index) {
+        state.selectedTemplateId = state.labReqOption!.templateList[index].value!.toString();
+        update();
+      },
+    );
+  }
+
+  //选择开始时间
+  void pickStartTime() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.selectedStartTime,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.selectedStartTime = date;
+        update();
+      },
+      title: "Start Time".tr,
+    );
+  }
+
+  // 选择结束时间
+  void pickEndTime() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.selectedEndTime ?? state.selectedStartTime,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.selectedEndTime = date;
+        update();
+      },
+      title: "End Time".tr,
+    );
+  }
+
+  // 筛选部门
+  void pickDepartment() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    int selectedDepartmentIndex;
+    if (state.selectedDepartmentId == null) {
+      selectedDepartmentIndex = 0;
+    } else {
+      selectedDepartmentIndex = state.labReqOption!.departmentList.indexWhere((department) => department.value.toString() == state.selectedDepartmentId);
+    }
+
+    if (selectedDepartmentIndex < 0) {
+      selectedDepartmentIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.labReqOption!.departmentList.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedDepartmentIndex,
+      onPickerChanged: (_, index) {
+        state.selectedDepartmentId = state.labReqOption!.departmentList[index].value!.toString();
+        update();
+      },
+    );
+  }
+}

+ 362 - 0
packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_page.dart

@@ -0,0 +1,362 @@
+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';
+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/date_time_utils.dart';
+import 'package:shared/utils/screen_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_radio_check.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/round_my_text_field.dart';
+
+import 'labour_request_add_controller.dart';
+import 'labour_request_add_state.dart';
+
+class UKLabourRequestAddPage extends BaseStatefulPage<LabourRequestAddController> {
+  UKLabourRequestAddPage({Key? key}) : super(key: key);
+
+  //启动当前页面,pageType 0 是新增  1是编辑  2是详情
+  static void startInstance(int pageType, String? appliedId) {
+    return Get.start(RouterPath.UKLabourAdd, arguments: {'pageType': pageType, 'appliedId': appliedId});
+  }
+
+  @override
+  LabourRequestAddController createRawController() {
+    return LabourRequestAddController();
+  }
+
+  @override
+  State<UKLabourRequestAddPage> createState() => _LabourRequestAddState();
+}
+
+class _LabourRequestAddState extends BaseState<UKLabourRequestAddPage, LabourRequestAddController> {
+  late LabourRequestAddState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.pageType = Get.arguments['pageType'];
+    state.appliedId = Get.arguments['appliedId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return Scaffold(
+        extendBodyBehindAppBar: true,
+        appBar: MyAppBar.appBar(
+            context,
+            state.pageType == 0
+                ? "Add Labour Requisition".tr
+                : state.pageType == 1
+                    ? "Edit Labour Requisition".tr
+                    : "Labour Requisition".tr),
+        body: SafeArea(
+          bottom: true,
+          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: [
+                      //工作标题,选择模板
+                      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)
+                      //     : 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),
+                      ),
+                    ],
+                  ).paddingOnly(left: 15, right: 15),
+                ),
+              ),
+            ),
+          ),
+        ),
+      );
+    });
+  }
+}

+ 40 - 0
packages/cpt_uk/lib/modules/job/labour_request_add/labour_request_add_state.dart

@@ -0,0 +1,40 @@
+import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class LabourRequestAddState {
+
+  int pageType = 0;  //页面的状态 0 是新增  1是编辑  2是详情
+  String? appliedId;  //编辑和详情需要用到ID
+
+  //页面对应的详情数据
+  LabourRequestEditIndexEntity? labReqOption;
+
+  //页面对应的选择的条件
+  DateTime? selectedStartTime;
+  DateTime? selectedEndTime;
+  String? selectedTemplateId;
+  String? selectedDepartmentId;
+  String? noStaff;  //成员数量
+
+  String? chargeOptionId;
+
+  //表单的校验与数据
+  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,
+    },
+  };
+
+}

+ 361 - 0
packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_filter.dart

@@ -0,0 +1,361 @@
+import 'dart:typed_data';
+import 'dart:ui';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/labour_request_index_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:shared/utils/screen_util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/my_button.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/picker/option_pick_util.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 用工请求列表的筛选
+ */
+class LabourRequestFilter extends StatefulWidget {
+  void Function(DateTime? selectedStartDate, DateTime? selectedEndDate, String? selectedStatusId, String? selectedDepartmentId)? onFilterAction;
+  LabourRequestIndexEntity optionResult;
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedStatusId;
+  String? selectedDepartmentId;
+
+  LabourRequestFilter({
+    required this.optionResult,
+    required this.selectedStartDate,
+    required this.selectedEndDate,
+    required this.selectedStatusId,
+    required this.selectedDepartmentId,
+    this.onFilterAction,
+  });
+
+  @override
+  State<LabourRequestFilter> createState() => _LabourRequestFilterState();
+}
+
+class _LabourRequestFilterState extends State<LabourRequestFilter> {
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedStatusId;
+  String? selectedDepartmentId;
+
+  @override
+  void initState() {
+    super.initState();
+    this.selectedStartDate = widget.selectedStartDate;
+    this.selectedEndDate = widget.selectedEndDate;
+    this.selectedStatusId = widget.selectedStatusId;
+    this.selectedDepartmentId = widget.selectedDepartmentId;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        SizedBox(
+          height: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1,
+        ),
+        Container(
+          padding: EdgeInsets.only(left: 15, right: 15, top: 17.5, bottom: 20),
+          width: double.infinity,
+          decoration: BoxDecoration(
+            color: Colors.white,
+          ),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              //部门
+              MyTextView(
+                "Outlet".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择部门
+              Container(
+                padding: EdgeInsets.only(left: 16, right: 10),
+                margin: EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: const BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedDepartmentId == null || selectedDepartmentId == "0"
+                          ? ""
+                          : widget.optionResult.departmentList!.firstWhere((element) => element.value.toString() == selectedDepartmentId).txt!,
+                      hint: "Choose Outlet".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      fontSize: 14,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerOutlet();
+              }),
+
+              //状态
+              MyTextView(
+                "Status".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                marginTop: 11,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择状态
+              Container(
+                padding: EdgeInsets.only(left: 16, right: 10),
+                margin: EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: const BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStatusId == null || selectedStatusId == "0"
+                          ? ""
+                          : widget.optionResult.statusList!.firstWhere((element) => element.value.toString() == selectedStatusId).txt!,
+                      fontSize: 14,
+                      hint: "Choose Status".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStatus();
+              }),
+
+              //开始时间
+              MyTextView(
+                "Start Date".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                marginTop: 11,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择时间
+              Container(
+                padding: EdgeInsets.only(left: 16, right: 10),
+                margin: EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: const BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStartDate == null ? "" : DateTimeUtils.formatDate(selectedStartDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose Start Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStartDate();
+              }),
+
+              //结束日期
+              MyTextView(
+                "End Date".tr,
+                fontSize: 14,
+                marginTop: 11,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择结束日期
+              Container(
+                padding: EdgeInsets.only(left: 16, right: 10),
+                margin: EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: const BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedEndDate == null ? "" : DateTimeUtils.formatDate(selectedEndDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose End Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerEndDate();
+              }),
+
+              //按钮组
+              Row(
+                children: [
+                  MyButton(
+                    onPressed: () {
+                      //只是Reset当前的弹窗筛选选项
+                      widget.selectedStartDate = null;
+                      widget.selectedEndDate = null;
+                      widget.selectedStatusId = null;
+                      widget.selectedDepartmentId = null;
+
+                      setState(() {
+                        selectedStartDate = null;
+                        selectedEndDate = null;
+                        selectedStatusId = null;
+                        selectedDepartmentId = null;
+                      });
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#FFBB1B"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                  SizedBox(width: 15),
+                  MyButton(
+                    onPressed: () {
+                      onCancel();
+                      widget.onFilterAction?.call(selectedStartDate, selectedEndDate, selectedStatusId, selectedDepartmentId);
+                    },
+                    text: "Filter".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#0AC074"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                ],
+              ).marginOnly(top: 20),
+            ],
+          ),
+        ),
+        Center(child: MyAssetImage(Assets.baseServiceDialogDeleteIcon, width: 26.5, height: 26.5).marginOnly(top: 35)).onTap(() {
+          onCancel();
+        }),
+      ],
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  /// 筛选开始日期
+  void pickerStartDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedStartDate = date;
+        });
+      },
+      title: "Start Date".tr,
+    );
+  }
+
+  /// 筛选结束日期
+  void pickerEndDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedEndDate ?? selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedEndDate = date;
+        });
+      },
+      title: "End Date".tr,
+    );
+  }
+
+  /// 筛选部门
+  void pickerOutlet() {
+    int selectedDepartmentIndex;
+    if (selectedDepartmentId == null) {
+      selectedDepartmentIndex = 0;
+    } else {
+      selectedDepartmentIndex = widget.optionResult.departmentList!.indexWhere((department) => department.value.toString() == selectedDepartmentId);
+    }
+
+    if (selectedDepartmentIndex < 0) {
+      selectedDepartmentIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: widget.optionResult.departmentList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedDepartmentIndex,
+      onPickerChanged: (_, index) {
+        setState(() {
+          selectedDepartmentId = widget.optionResult.departmentList![index].value!.toString();
+        });
+      },
+    );
+  }
+
+  /// 筛选状态
+  void pickerStatus() {
+    int selectedStatusIndex;
+    if (selectedStatusId == null) {
+      selectedStatusIndex = 0;
+    } else {
+      selectedStatusIndex = widget.optionResult.statusList!.indexWhere((department) => department.value.toString() == selectedStatusId);
+    }
+
+    if (selectedStatusIndex < 0) {
+      selectedStatusIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: widget.optionResult.statusList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedStatusIndex,
+      onPickerChanged: (_, index) {
+        setState(() {
+          selectedStatusId = widget.optionResult.statusList![index].value!.toString();
+        });
+      },
+    );
+  }
+}

+ 286 - 0
packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_item.dart

@@ -0,0 +1,286 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/labour_request_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_button.dart';
+import 'package:widgets/my_text_view.dart';
+
+/*
+ * 用工请求的主页面列表Item
+ */
+class LabourRequestItem extends StatelessWidget {
+  final int index;
+  final LabourRequestListRows item;
+  final VoidCallback? onStatusAction;
+  final VoidCallback? onRecallAction;
+  final VoidCallback? onDetailAction;
+  final VoidCallback? onEditAction;
+
+  LabourRequestItem({
+    required this.index,
+    required this.item,
+    this.onStatusAction,
+    this.onRecallAction,
+    this.onDetailAction,
+    this.onEditAction,
+  });
+
+  @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: [
+          //工作标题
+          MyTextView(
+            item.jobTitle ?? "-",
+            isFontMedium: true,
+            textColor: ColorConstants.textYellowFFBB1B,
+            fontSize: 14,
+            textDecoration: TextDecoration.underline,
+            decorationColor: ColorConstants.textYellowFFBB1B,
+            // 可选,设置下划线的颜色
+            decorationThickness: 2.0,
+            // 可选,设置下划线的粗细
+            decorationStyle: TextDecorationStyle.solid, // 可选,设置下划线的样式
+          ),
+
+          // 部门
+          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(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 工作日期时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Datetime:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期时间
+              MyTextView(
+                item.jobTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 人数
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            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(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Status:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //状态
+              MyTextView(
+                item.coStatusShow == null ? "" : item.coStatusShow!.tr,
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: "Approved" == item.coStatusShow
+                    ? ColorConstants.textGreen05DC82
+                    : "Rejected" == item.coStatusShow
+                        ? ColorConstants.textRedFF6262
+                        : "Recall" == item.coStatusShow
+                            ? ColorConstants.textYellowFFBB1B
+                            : ColorConstants.textBlue06D9FF,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).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,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created 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("detail") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onDetailAction?.call();
+                    },
+                    text: "Detail".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor(
+                      "#56AAFF",
+                    ),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+
+                //Recall按钮
+                Visibility(
+                  visible: item.actionList?.contains("recall") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onRecallAction?.call();
+                    },
+                    text: "Recall".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#FFBB1B"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+
+                //Edit按钮
+                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),
+                ),
+              ],
+            ).marginOnly(top: 18, bottom: 2),
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 295 - 0
packages/cpt_uk/lib/modules/job/labour_request_list/labour_request_list_controller.dart

@@ -0,0 +1,295 @@
+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/repository/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/util.dart';
+import 'package:widgets/dialog/app_default_dialog.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../labour_request_add/labour_request_add_page.dart';
+import 'labour_request_filter.dart';
+import 'labour_request_list_state.dart';
+
+class LabourRequestListController extends GetxController with DioCancelableMixin {
+  final LabourRepository _labourRepository = Get.find();
+  final LabourRequestListState state = LabourRequestListState();
+
+  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 = [
+      _labourRepository.fetchLabourRequestList(
+        state.keyword,
+        DateTimeUtils.formatDate(state.selectedStartDate, format: "yyyy-MM-dd"),
+        DateTimeUtils.formatDate(state.selectedEndDate, format: "yyyy-MM-dd"),
+        state.selectedStatusId,
+        state.selectedDepartmentId,
+        curPage: _curPage,
+        cancelToken: cancelToken,
+      ),
+      state.indexOptions == null
+          ? _labourRepository.fetchLabourRequestIndex(
+              cancelToken: cancelToken,
+            )
+          : Future(() => HttpResult(isSuccess: true).convert(data: state.indexOptions!)),
+    ];
+
+    //拿到结果
+    var results = await Future.wait(futures);
+    var listResult = results[0] as HttpResult<LabourRequestListEntity>;
+    var optionResult = results[1] as HttpResult<LabourRequestIndexEntity>;
+
+    //选项数据
+    if (state.indexOptions == null && optionResult.isSuccess) {
+      state.indexOptions = optionResult.data!;
+    }
+
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.rows);
+    } else {
+      errorMessage = listResult.errorMsg;
+      changeLoadingState(LoadState.State_Error);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+  // 处理数据与展示的逻辑
+  void handleList(List<LabourRequestListRows>? 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) {
+    state.keyword = keyword;
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  // 清空搜索条件
+  void resetFiltering() {
+    state.keyword = "";
+    state.searchController.text = "";
+
+    state.selectedStartDate = null;
+    state.selectedEndDate = null;
+    state.selectedStatusId = null;
+    state.selectedDepartmentId = null;
+
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  //展示筛选的弹窗
+  void showFilterDialog() {
+    if (state.indexOptions != null) {
+      DialogEngine.show(
+        widget: LabourRequestFilter(
+          optionResult: state.indexOptions!,
+          selectedStartDate: state.selectedStartDate,
+          selectedEndDate: state.selectedEndDate,
+          selectedStatusId: state.selectedStatusId,
+          selectedDepartmentId: state.selectedDepartmentId,
+          onFilterAction: (startDate, endDate, statusId, departmentId) {
+            state.selectedStartDate = startDate;
+            state.selectedEndDate = endDate;
+            state.selectedStatusId = statusId;
+            state.selectedDepartmentId = departmentId;
+
+            //赋值之后刷新
+            refreshController.callRefresh();
+          },
+        ),
+        position: DialogPosition.top,
+        animType: DialogAnimation.fade,
+      );
+    }
+  }
+
+  /// 执行Recall请求
+  void requestRecall(String requestId) async {
+    var recallResult = await _labourRepository.recallLabourRequest(
+      requestId,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (recallResult.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+      fetchItemByIdAndRefreshItem(requestId);
+    } else {
+      ToastEngine.show(recallResult.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  /// 根据ID获取Item对象,用于刷新
+  void fetchItemByIdAndRefreshItem(String requestId) async {
+    var result = await _labourRepository.fetchItemByRequestId(
+      requestId,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      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) {
+          state.datas[index] = requestItem;
+          update();
+        }
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  @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)) {
+        fetchItemByIdAndRefreshItem(requestId);
+      } else {
+        refreshController.callRefresh();
+      }
+    });
+  }
+
+  void unregisterEventBus() {
+    bus.off(AppConstant.eventLabourRequestRefresh, subscribe);
+  }
+
+  //跳转到添加页面
+  void gotoAddLabourPage() {
+    UKLabourRequestAddPage.startInstance(0, "");
+  }
+
+  //去详情页面
+  void gotoDetailPage(LabourRequestListRows data) {
+    UKLabourRequestAddPage.startInstance(2, data.requestId.toString());
+  }
+
+  //去编辑页面
+  void gotoEditPage(LabourRequestListRows data) {
+    UKLabourRequestAddPage.startInstance(1, data.requestId.toString());
+  }
+
+  //去状态工作流的页面
+  void gotoWorkflowPage(LabourRequestListRows data) {
+    UKLabourRequestWorkflowPage.startInstance(data.requestId.toString());
+  }
+
+  void doRecall(LabourRequestListRows data) {
+    DialogEngine.show(
+        widget: AppDefaultDialog(
+      title: "Message".tr,
+      message: "Are you sure you want to recall?".tr,
+      confirmAction: () {
+        requestRecall(data.requestId.toString());
+      },
+    ));
+  }
+
+
+}

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

@@ -0,0 +1,166 @@
+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: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/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'labour_request_item.dart';
+import 'labour_request_list_controller.dart';
+import 'labour_request_list_state.dart';
+
+/*
+ * 用工请求的主页列表
+ */
+class UKLabourRequestListPage extends BaseStatefulPage<LabourRequestListController> {
+  UKLabourRequestListPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKLabourList);
+  }
+
+  @override
+  LabourRequestListController createRawController() {
+    return LabourRequestListController();
+  }
+
+  @override
+  State<UKLabourRequestListPage> createState() => _LabourRequestListState();
+}
+
+class _LabourRequestListState extends BaseState<UKLabourRequestListPage, LabourRequestListController> {
+  late LabourRequestListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: true,
+        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.searchTitleBar(
+                context,
+                value: state.keyword,
+                hintText: 'Title'.tr,
+                controller: state.searchController,
+                onSearch: (keyword) {
+                  controller.doSearch(keyword);
+                },
+                actions: [
+                  //重置按钮
+                  MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      controller.resetFiltering();
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(right: 15),
+
+                  //筛选图标
+                  const MyAssetImage(
+                    Assets.baseServiceTitleBarFilterIcon,
+                    width: 24,
+                    height: 16.5,
+                  ).onTap(() {
+                    FocusScope.of(context).unfocus();
+                    controller.showFilterDialog();
+                  }).marginOnly(right: 15),
+                ],
+              ),
+              // 添加按钮
+              MyButton(
+                type: ClickType.throttle,
+                milliseconds: 500,
+                onPressed: () {
+                  FocusScope.of(context).unfocus();
+                  controller.gotoAddLabourPage();
+                },
+                text: "Create New Job Request".tr,
+                textColor: ColorConstants.white,
+                fontSize: 16,
+                radius: 20,
+                backgroundColor: hexToColor("#FFBB1B"),
+                fontWeight: FontWeight.w500,
+              ).marginSymmetric(horizontal: 15, vertical: 15),
+
+              //底部的列表
+              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 LabourRequestItem(
+                          index: index,
+                          item: state.datas[index],
+                          onDetailAction: () {
+                            controller.gotoDetailPage(state.datas[index]);
+                          },
+                          onRecallAction: () {
+                            controller.doRecall(state.datas[index]);
+                          },
+                          onEditAction: () {
+                            controller.gotoEditPage(state.datas[index]);
+                          },
+                          onStatusAction: () {
+                            controller.gotoWorkflowPage(state.datas[index]);
+                          },
+                        );
+                      },
+                      childCount: state.datas.length,
+                    ))
+                  ],
+                ),
+              ).expanded(),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}

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

@@ -0,0 +1,17 @@
+import 'package:domain/entity/response/labour_request_index_entity.dart';
+import 'package:domain/entity/response/labour_request_list_entity.dart';
+import 'package:flutter/material.dart';
+
+class LabourRequestListState {
+  //筛选条件
+  final TextEditingController searchController = TextEditingController();
+  String keyword = "";
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedStatusId;
+  String? selectedDepartmentId;
+
+  //页面的列表数据
+  List<LabourRequestListRows> datas = [];
+  LabourRequestIndexEntity? indexOptions;
+}

+ 96 - 0
packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_request_workflow_controller.dart

@@ -0,0 +1,96 @@
+import 'package:domain/entity/response/labour_request_work_flow_entity.dart';
+import 'package:domain/repository/labour_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 'labour_request_workflow_state.dart';
+
+
+class LabourRequestWorkflowController extends GetxController with DioCancelableMixin{
+  final LabourRepository _labourRepository = Get.find();
+  final LabourRequestWorkflowState state = LabourRequestWorkflowState();
+
+  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 _labourRepository.fetchLabourRequestWorkFlow(
+      state.requestId,
+      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<LabourRequestWorkFlowRecords>? 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();
+  }
+}

+ 102 - 0
packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_request_workflow_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 'labour_request_workflow_controller.dart';
+import 'labour_request_workflow_state.dart';
+import 'labour_workflow_item.dart';
+
+/*
+ * 用工请求-状态工作流列表
+ */
+class UKLabourRequestWorkflowPage extends BaseStatefulPage<LabourRequestWorkflowController> {
+  UKLabourRequestWorkflowPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? requestId) {
+    return Get.start(RouterPath.UKLabourWorlkflow,arguments: {'requestId': requestId});
+  }
+
+  @override
+  LabourRequestWorkflowController createRawController() {
+    return LabourRequestWorkflowController();
+  }
+
+  @override
+  State<UKLabourRequestWorkflowPage> createState() => _LabourRequestWorkflowState();
+
+}
+
+class _LabourRequestWorkflowState extends BaseState<UKLabourRequestWorkflowPage, LabourRequestWorkflowController> {
+
+  late LabourRequestWorkflowState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.requestId = Get.arguments['requestId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return  SafeArea(
+          bottom: true,
+          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, "Workflow".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 LabourWorkFlowItem(index: index,item: state.datas[index]);
+                            },
+                            childCount: state.datas.length,
+                          ))
+                    ],
+                  ),
+                ).expanded(),
+              ],
+            ).marginOnly(top: 10),
+          ),
+        );
+    });
+  }
+}
+
+

+ 10 - 0
packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_request_workflow_state.dart

@@ -0,0 +1,10 @@
+import 'package:domain/entity/response/labour_request_work_flow_entity.dart';
+
+class LabourRequestWorkflowState {
+
+  String? requestId;
+
+  //页面的列表数据
+  List<LabourRequestWorkFlowRecords> datas = [];
+
+}

+ 230 - 0
packages/cpt_uk/lib/modules/job/labour_request_workflow/labour_workflow_item.dart

@@ -0,0 +1,230 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/labour_request_list_entity.dart';
+import 'package:domain/entity/response/labour_request_work_flow_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';
+
+/**
+ * 用工请求的工作流列表Item
+ */
+class LabourWorkFlowItem extends StatelessWidget {
+  final int index;
+  final LabourRequestWorkFlowRecords item;
+
+  LabourWorkFlowItem({
+    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: [
+          //Node
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Node:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.nodeName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ),
+
+          // assigneeType
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Type:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期时间
+              MyTextView(
+                item.assigneeTypeShow ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // Designation
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Designation:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //人数
+              MyTextView(
+                item.designationShow ?? "-",
+                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: "Approved" == item.statusShow
+                    ? ColorConstants.textGreen05DC82
+                    : "Rejected" == item.statusShow
+                    ? ColorConstants.textRedFF6262
+                    : "Recall" == item.statusShow
+                    ? ColorConstants.textYellowFFBB1B
+                    : ColorConstants.textBlue06D9FF,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // Operator
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Operator:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                item.auditName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 操作时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Audit Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.auditTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created 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),
+
+          // Remark
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Remark:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.auditMark ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+        ],
+      ),
+    );
+  }
+}

+ 128 - 0
packages/cpt_uk/lib/modules/job/template_add/template_add_controller.dart

@@ -0,0 +1,128 @@
+import 'package:domain/entity/response/job_template_edit_index_entity.dart';
+import 'package:domain/repository/labour_repository.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/log_utils.dart';
+import 'package:shared/utils/util.dart';
+
+import 'template_add_state.dart';
+
+class TemplateAddController extends GetxController with DioCancelableMixin {
+  final LabourRepository _labourRepository = Get.find();
+  final LabourTemplateAddState state = LabourTemplateAddState();
+
+  // 获取添加或者编辑的详情
+  void _fetchAddEditIndexDetail() async {
+    //获取到数据
+    Future<HttpResult<JobTemplateEditIndexEntity>> taskFuture;
+    if (Utils.isNotEmpty(state.templateId) && state.templateId != "0") {
+      //编辑
+      taskFuture = _labourRepository.fetchJobTemplateEditIndex(state.templateId, cancelToken: cancelToken);
+    } else {
+      //新增
+      taskFuture = _labourRepository.fetchJobTemplateAddIndex(cancelToken: cancelToken);
+    }
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      state.indexEntity = result.data;
+
+      var templateNameController = state.formData['template_name']!['controller'];
+      var descController = state.formData['desc']!['controller'];
+      var noteController = state.formData['note']!['controller'];
+      templateNameController.text = state.indexEntity?.jobTitle ?? "";
+      descController.text = state.indexEntity?.description ?? "";
+      noteController.text = state.indexEntity?.note ?? "";
+
+      //默认赋值
+      state.optionLanguageList = state.indexEntity?.languageList.map((e) => e.txt!).toList() ?? [];
+      Log.d("当前语言的选项为:${state.optionLanguageList}");
+      Log.d("当前年龄的选项为:${state.indexEntity?.ageList}");
+      Log.d("当前性别的选项为:${state.indexEntity?.languageList}");
+
+      state.selectedAgeList = state.indexEntity?.ageList.where((e) => e.checked == "checked").map((e) => e.value!).toList() ?? [];
+      Log.d("当前选中的年龄:${state.selectedAgeList}");
+      state.selectedLanguageList = state.indexEntity?.languageList.where((e) => e.checked == "checked").map((e) => e.value!).toList() ?? [];
+      Log.d("当前选中的语言:${state.selectedLanguageList}");
+
+      if (state.indexEntity?.sexList != null) {
+        state.gender = state.indexEntity!.sexList.firstWhere((e) => e.checked == "checked", orElse: () => JobTemplateEditIndexSexList(),).value;
+      } else {
+        state.gender = null;
+      }
+      Log.d("当前选中的性别:${state.gender}");
+
+      //刷新
+      update();
+
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  /// 提交
+  void doSubmit() async {
+    var templateNameController = state.formData['template_name']!['controller'];
+    var descController = state.formData['desc']!['controller'];
+    var noteController = state.formData['note']!['controller'];
+
+    String templateName = templateNameController.text.toString();
+    String desc = descController.text.toString();
+    String note = noteController.text.toString();
+
+    //只校验模版的名称
+    if (Utils.isEmpty(templateName)) {
+      ToastEngine.show("Enter Job Template Name".tr);
+      return;
+    }
+
+    Future<HttpResult> taskFuture;
+    if (Utils.isNotEmpty(state.templateId) && state.templateId != "0") {
+      taskFuture = _labourRepository.editLabourTemplateSubmit(
+        state.templateId,
+        templateName,
+        desc,
+        note,
+        state.selectedAgeList.join(","),
+        state.gender,
+        state.selectedLanguageList.join(","),
+        cancelToken: cancelToken,
+      );
+    } else {
+      taskFuture = _labourRepository.addLabourTemplateSubmit(
+        templateName,
+        desc,
+        note,
+        state.selectedAgeList.join(","),
+        state.gender,
+        state.selectedLanguageList.join(","),
+        cancelToken: cancelToken,
+      );
+    }
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //根据类型刷新
+      state.cb?.call(state.templateId);
+
+      Get.back();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    _fetchAddEditIndexDetail();
+  }
+}

+ 327 - 0
packages/cpt_uk/lib/modules/job/template_add/template_add_page.dart

@@ -0,0 +1,327 @@
+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: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_text_view.dart';
+import 'package:widgets/no_shadow_scroll_behavior.dart';
+import 'package:widgets/shatter/custom_check_box.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 'template_add_controller.dart';
+
+import 'package:plugin_basic/utils/ext_get_nav.dart';
+import 'package:router/path/router_path.dart';
+
+import 'template_add_state.dart';
+
+/*
+ * 模板的添加与编辑
+ */
+class UKTemplateAddPage extends BaseStatefulPage<TemplateAddController> {
+  UKTemplateAddPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(
+    String templateId,
+    void Function(dynamic value)? cb,
+  ) {
+    return Get.start(RouterPath.UKTemplateAdd, arguments: {'templateId': templateId, 'cb': cb});
+  }
+
+  @override
+  TemplateAddController createRawController() {
+    return TemplateAddController();
+  }
+
+  @override
+  State<UKTemplateAddPage> createState() => _LabourTemplateAddState();
+}
+
+class _LabourTemplateAddState extends BaseState<UKTemplateAddPage, TemplateAddController> {
+  late LabourTemplateAddState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.templateId = Get.arguments['templateId'];
+    state.cb = Get.arguments['cb'] as void Function(dynamic)?;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(
+        id: "all",
+        builder: (controller) {
+          return Scaffold(
+            extendBodyBehindAppBar: true,
+            appBar: MyAppBar.appBar(context, Utils.isEmpty(state.templateId) ? "Create Template".tr : "Edit Template".tr),
+            body: SafeArea(
+              bottom: true,
+              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: [
+                          //模板名称
+                          FormRequireText(text: "Template Name".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,
+                          ),
+
+                          //年龄
+                          Visibility(
+                            visible: state.indexEntity?.ageList.isNotEmpty == true,
+                            child: MyTextView(
+                              "Age".tr,
+                              textColor: Colors.white,
+                              fontSize: 14,
+                              isFontRegular: true,
+                              marginLeft: 15,
+                              marginTop: 15,
+                            ),
+                          ),
+
+                          // 年龄的多选
+                          Visibility(
+                            visible: state.indexEntity?.ageList.isNotEmpty == true,
+                            child: CustomCheckBox(
+                              options: state.indexEntity?.ageList.map((e) => e.txt!).toList() ?? [],
+                              onOptionsSelected: (selected) {
+                                // 转换选中的索引为对应的 value
+                                state.selectedAgeList = selected
+                                    .map((index) {
+                                      return state.indexEntity?.ageList[index].value; // 获取对应的 value
+                                    })
+                                    .whereType<String>()
+                                    .toList();
+                              },
+                              selectedOptions: state.indexEntity?.ageList.where((e) => e.checked == "checked").map((e) => e.txt!).toList() ?? [],
+                            ).marginOnly(left: 15, right: 15, top: 10),
+                          ),
+
+                          //性别
+                          Visibility(
+                            visible: state.indexEntity?.sexList.isNotEmpty == true,
+                            child: MyTextView(
+                              "Gender".tr,
+                              textColor: Colors.white,
+                              fontSize: 14,
+                              isFontRegular: true,
+                              marginLeft: 15,
+                              marginTop: 15,
+                            ),
+                          ),
+
+                          //性别单选
+                          Visibility(
+                            visible: state.indexEntity?.sexList.isNotEmpty == true,
+                            child: CustomRadioCheck(
+                              options: state.indexEntity?.sexList.map((e) => e.txt!).toList() ?? [],
+                              onOptionSelected: (index, text) {
+                                state.gender = state.indexEntity!.sexList[index].value;
+                              },
+                              selectedPosition: state.indexEntity?.sexList.indexWhere((e) => e.checked == "checked") ?? -1,
+                            ).marginOnly(left: 15, right: 15, top: 10),
+                          ),
+
+                          //语言
+                          MyTextView(
+                            "Language".tr,
+                            textColor: Colors.white,
+                            fontSize: 14,
+                            isFontRegular: true,
+                            marginLeft: 15,
+                            marginTop: 15,
+                          ),
+
+                          // 语言的多选
+                          GetBuilder<TemplateAddController>(
+                            builder: (controller) {
+                              return CustomCheckBox(
+                                options: state.optionLanguageList,
+                                onOptionsSelected: (selected) {
+                                  // 转换选中的索引为对应的 value
+                                  state.selectedLanguageList = selected
+                                      .map((index) {
+                                        return state.indexEntity?.languageList[index].value; // 获取对应的 value
+                                      })
+                                      .whereType<String>()
+                                      .toList();
+                                },
+                                selectedOptions: state.indexEntity?.languageList.where((e) => e.checked == "checked").map((e) => e.txt!).toList() ?? [],
+                              );
+                            },
+                            id: "language",
+                            init: controller,
+                          ).marginOnly(left: 15, right: 15, top: 10),
+
+                          //备注
+                          MyTextView(
+                            "Note".tr,
+                            textColor: Colors.white,
+                            fontSize: 14,
+                            isFontRegular: true,
+                            marginLeft: 15,
+                            marginTop: 18,
+                          ),
+
+                          IgnoreKeyboardDismiss(
+                            child: Container(
+                              height: 130,
+                              margin: const EdgeInsets.only(left: 15, right: 15, top: 10),
+                              padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
+                              decoration: BoxDecoration(
+                                color: const Color(0xFF4DCFF6).withOpacity(0.2),
+                                borderRadius: const BorderRadius.all(Radius.circular(5)),
+                              ),
+                              child: TextField(
+                                cursorColor: ColorConstants.white,
+                                cursorWidth: 1.5,
+                                autofocus: false,
+                                enabled: true,
+                                focusNode: state.formData["note"]!['focusNode'],
+                                controller: state.formData["note"]!['controller'],
+                                // 装饰
+                                decoration: InputDecoration(
+                                  isDense: true,
+                                  isCollapsed: true,
+                                  border: InputBorder.none,
+                                  hintText: state.formData["note"]!['hintText'],
+                                  hintStyle: const TextStyle(
+                                    color: ColorConstants.textGrayAECAE5,
+                                    fontSize: 14.0,
+                                    fontWeight: FontWeight.w400,
+                                  ),
+                                ),
+                                style: const TextStyle(
+                                  color: ColorConstants.white,
+                                  fontSize: 14.0,
+                                  fontWeight: FontWeight.w400,
+                                ),
+                                // 键盘动作右下角图标
+                                textInputAction: TextInputAction.next,
+                                onSubmitted: (value) {
+                                  state.formData['note']!['focusNode'].unfocus();
+                                },
+                              ),
+                            ),
+                          ),
+
+                          //模板详情
+                          MyTextView(
+                            "Description".tr,
+                            textColor: Colors.white,
+                            fontSize: 14,
+                            isFontRegular: true,
+                            marginLeft: 15,
+                            marginTop: 15,
+                          ),
+
+                          IgnoreKeyboardDismiss(
+                            child: Container(
+                              height: 130,
+                              margin: const EdgeInsets.only(left: 15, right: 15, top: 10),
+                              padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
+                              decoration: BoxDecoration(
+                                color: const Color(0xFF4DCFF6).withOpacity(0.2),
+                                borderRadius: const BorderRadius.all(Radius.circular(5)),
+                              ),
+                              child: TextField(
+                                cursorColor: ColorConstants.white,
+                                cursorWidth: 1.5,
+                                autofocus: false,
+                                enabled: true,
+                                focusNode: state.formData["desc"]!['focusNode'],
+                                controller: state.formData["desc"]!['controller'],
+                                // 装饰
+                                decoration: InputDecoration(
+                                  isDense: true,
+                                  isCollapsed: true,
+                                  border: InputBorder.none,
+                                  hintText: state.formData["desc"]!['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.next,
+                                onSubmitted: (value) {
+                                  state.formData['desc']!['focusNode'].unfocus();
+                                  FocusScope.of(context).requestFocus(state.formData['note']!['focusNode']);
+                                },
+                              ),
+                            ),
+                          ),
+
+                          //提交按钮
+                          MyButton(
+                            type: ClickType.throttle,
+                            milliseconds: 500,
+                            onPressed: () {
+                              FocusScope.of(context).unfocus();
+                              controller.doSubmit();
+                            },
+                            text: "Submit".tr,
+                            textColor: ColorConstants.white,
+                            fontSize: 16,
+                            radius: 20,
+                            backgroundColor: ColorConstants.textYellowFFBB1B,
+                            fontWeight: FontWeight.w500,
+                          ).marginSymmetric(vertical: 25, horizontal: 15),
+                        ],
+                      ),
+                    ),
+                  ),
+                ),
+              ),
+            ),
+          );
+        });
+  }
+}

+ 45 - 0
packages/cpt_uk/lib/modules/job/template_add/template_add_state.dart

@@ -0,0 +1,45 @@
+import 'package:domain/entity/response/job_template_edit_index_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class LabourTemplateAddState {
+  //表单的校验与数据
+  Map<String, Map<String, dynamic>> formData = {
+    'template_name': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'desc': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+    'note': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Enter...'.tr,
+      'obsecure': false,
+    },
+  };
+
+
+  final foodHygieneCertOption = ["Yes".tr, "No".tr];
+
+  String templateId = "";
+  void Function(dynamic value)? cb;
+
+  JobTemplateEditIndexEntity? indexEntity;  //新增或者编辑的详情
+
+
+  List<String> selectedAgeList = [];   //选中的 age 的 id
+  List<String> selectedLanguageList = [];   //选中的 language 的 id
+  String? gender;
+
+  List<String> optionLanguageList =[];  // language 的选项字符串
+}

+ 7 - 0
packages/cpt_uk/lib/modules/job/template_list/add_edit_template.dart

@@ -0,0 +1,7 @@
+//编辑和新增页面返回的对象
+class AddEditTemplate{
+   bool isEdit = false;
+   String? templateId;
+
+   AddEditTemplate(this.isEdit, this.templateId);
+}

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

@@ -0,0 +1,175 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/job_template_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_text_view.dart';
+
+/*
+ * 用工请求的主页面列表Item
+ */
+class TemplateItem extends StatelessWidget {
+  final int index;
+  final JobTemplateSGRows item;
+  final VoidCallback? onDeleteAction;
+  final VoidCallback? onEditAction;
+
+  TemplateItem({
+    required this.index,
+    required this.item,
+    this.onDeleteAction,
+    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(
+                "${"Template Name".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.name ?? "-",
+                marginLeft: 5,
+                isFontMedium: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ),
+
+          // 创建人
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Created By".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.createdBy ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 14),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created At:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //状态
+              MyTextView(
+                item.createdAt ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 14),
+
+          // 更新时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Updated At".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+              MyTextView(
+                item.updatedAt ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 14),
+
+          //按钮组
+          Visibility(
+            visible: item.actionList.isNotEmpty,
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                //编辑按钮
+                Visibility(
+                  visible: item.actionList.contains("edit"),
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onEditAction?.call();
+                    },
+                    text: "Edit".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: ColorConstants.textGreen0AC074,
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+
+                //删除按钮
+                Visibility(
+                  visible: item.actionList.contains("delete"),
+                  child: MyButton(
+                    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: 12),
+                ),
+              ],
+            ).marginOnly(top: 18, bottom: 2),
+
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 215 - 0
packages/cpt_uk/lib/modules/job/template_list/template_list_controller.dart

@@ -0,0 +1,215 @@
+import 'package:domain/entity/response/job_template_s_g_entity.dart';
+import 'package:domain/repository/labour_sg_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:widgets/dialog/app_default_dialog.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../template_add/template_add_page.dart';
+import 'template_list_state.dart';
+
+class TemplateListController extends GetxController with DioCancelableMixin {
+  final LabourSGRepository _labourRepository = Get.find();
+  final TemplateListState state = TemplateListState();
+
+  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;
+    fetchNotifyList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchNotifyList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchNotifyList();
+  }
+
+  /// 获取服务器数据,通知消息列表
+  Future fetchNotifyList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    var listResult = await _labourRepository.fetchJobTemplateList(state.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<JobTemplateSGRows>? 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) {
+    state.keyword = keyword;
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  // 清空搜索条件
+  void resetFiltering() {
+    state.keyword = "";
+    state.searchController.text = "";
+
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    fetchNotifyList();
+  }
+
+  @override
+  void onClose() {
+    state.datas.clear();
+    super.onClose();
+  }
+
+  //去添加模板的页面
+  void gotoTemplateAddPage() {
+    UKTemplateAddPage.startInstance("", (result) {
+      if (result is String) {
+        refreshController.callRefresh();
+      }
+    });
+  }
+
+  //去编辑的页面
+  void gotoEditPage(String templateId) {
+    UKTemplateAddPage.startInstance(templateId, (result) {
+      if (result is String) {
+        fetchItemByIdAndRefreshItem(templateId);
+      }
+    });
+  }
+
+  //删除工作模板
+  void deleteJobTitle(int index) {
+    DialogEngine.show(
+        widget: AppDefaultDialog(
+      title: "Confirmation".tr,
+      message: "Are you sure you want to delete this job template?".tr,
+      confirmAction: () {
+        _requestDeactivate(index);
+      },
+    ));
+  }
+
+  // 请求接口删除JobTitle
+  void _requestDeactivate(int index) async {
+    final item = state.datas[index];
+    var result = await _labourRepository.deleteJobTemplateSubmit(item.id.toString(), cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      if (state.datas.length <= 1) {
+        refreshController.callRefresh();
+      } else {
+        state.datas.removeAt(index);
+        update();
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  /// 根据ID获取Item对象,用于刷新
+  void fetchItemByIdAndRefreshItem(String ids) async {
+    var result = await _labourRepository.fetchJobTemplateListByIds(
+      ids,
+      cancelToken: cancelToken,
+    );
+
+    //处理数据
+    if (result.isSuccess) {
+      var data = result.data;
+      if (data != null && data.rows.isNotEmpty) {
+        List<JobTemplateSGRows> newItem = data.rows;
+
+        // 创建一个 Map 来加速查找
+        Map<int, JobTemplateSGRows> 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);
+    }
+  }
+}

+ 153 - 0
packages/cpt_uk/lib/modules/job/template_list/template_list_page.dart

@@ -0,0 +1,153 @@
+import 'package:cs_resources/constants/color_constants.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/widget_export.dart';
+import 'item_template.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 'template_list_controller.dart';
+import 'template_list_state.dart';
+
+/// UK的模板列表页面
+class UKTemplateListPage extends BaseStatefulPage<TemplateListController> {
+  UKTemplateListPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKTemplateList);
+  }
+
+  @override
+  TemplateListController createRawController() {
+    return TemplateListController();
+  }
+
+  @override
+  State<UKTemplateListPage> createState() => _LabourTemplateListState();
+
+}
+
+class _LabourTemplateListState extends BaseState<UKTemplateListPage, TemplateListController> {
+
+  late TemplateListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: true,
+        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.searchTitleBar(
+                context,
+                value: state.keyword,
+                hintText: 'Template Name'.tr,
+                controller: state.searchController,
+                onSearch: (keyword) {
+                  controller.doSearch(keyword);
+                },
+                actions: [
+                  //重置按钮
+                  MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      controller.resetFiltering();
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(right: 15),
+                ],
+              ),
+
+              Row(
+                children: [
+                  MyButton(
+                    type: ClickType.throttle,
+                    milliseconds: 500,
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      controller.gotoTemplateAddPage();
+                    },
+                    text: "Add New".tr,
+                    textColor: ColorConstants.white,
+                    fontSize: 16,
+                    radius: 20,
+                    backgroundColor: hexToColor("#FFBB1B"),
+                    fontWeight: FontWeight.w500,
+                  ).expanded(),
+                ],
+              ).marginOnly(left: 15,right: 15,top: 15,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 TemplateItem(
+                              index: index,
+                              item: state.datas[index],
+                              onEditAction: () {
+                                controller.gotoEditPage(state.datas[index].id.toString());
+                              },
+                              onDeleteAction: () {
+                                controller.deleteJobTitle(index);
+                              },
+                            );
+                          },
+                          childCount: state.datas.length,
+                        ))
+                  ],
+                ),
+              ).expanded(),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}
+

+ 13 - 0
packages/cpt_uk/lib/modules/job/template_list/template_list_state.dart

@@ -0,0 +1,13 @@
+import 'package:domain/entity/response/job_template_s_g_entity.dart';
+import 'package:flutter/material.dart';
+
+class TemplateListState {
+
+  //筛选条件
+  final TextEditingController searchController = TextEditingController();
+  String keyword = "";
+
+  //页面的列表数据
+  List<JobTemplateSGRows> datas = [];
+
+}

+ 32 - 29
packages/cpt_uk/lib/modules/main/main_controller.dart

@@ -1,12 +1,16 @@
+import 'package:cpt_uk/modules/attendance/device_list/device_list_page.dart';
+import 'package:cpt_uk/modules/attendance/e_attendance_list/e_attendance_list_page.dart';
+import 'package:cpt_uk/modules/attendance/security_registration/security_registration_page.dart';
 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/repository/auth_repository.dart';
 import 'package:get/get.dart';
-import 'package:plugin_basic/service/app_config_service.dart';
+import 'package:plugin_basic/service/user_service.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
-import 'package:router/componentRouter/component_router_service.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
+import 'package:router/componentRouter/component_router_service.dart';
 
 import 'main_state.dart';
 
@@ -50,28 +54,25 @@ class MainController extends GetxController {
     }
 
     //获取到数据
-    // var result = await _authRepository.fetchHotelInfo();
-    //
-    // //处理数据
-    // if (result.isSuccess) {
-    //   final hotelInfo = result.data;
-    //
-    //   if (hotelInfo != null) {
-    //     UserService.to.hotelInfo.value = hotelInfo;
-    //
-    //     _handleList(hotelInfo.menus);
-    //   } else {
-    //     ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
-    //   }
-    // } else {
-    //   ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
-    // }
-
-    //todo 模拟网络请求
-    await Future.delayed(const Duration(seconds: 2));
-    state.datas.clear();
-    state.datas.addAll(state.modules);
-    changeLoadingState(LoadState.State_Success);
+    var result = await _authRepository.fetchHotelInfo();
+
+    //处理数据
+    if (result.isSuccess) {
+      final hotelInfo = result.data;
+
+      if (hotelInfo != null) {
+        UserService.to.hotelInfo.value = hotelInfo;
+
+        //展示UK全部的模块
+        state.datas.clear();
+        state.datas.addAll(state.modules);
+        changeLoadingState(LoadState.State_Success);
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
 
     //停止刷新
     refreshController.finishRefresh();
@@ -124,20 +125,22 @@ class MainController extends GetxController {
         JobCategoryPage.startInstance();
         break;
       case 'device':
-        ToastEngine.show("点击 device 模块");
+        UKDeviceListPage.startInstance();
         break;
       case 'security':
-        ToastEngine.show("点击 security 模块");
+        UKSecurityRegistrationPage.startInstance();
         break;
       case 'attendance':
-        ToastEngine.show("点击 attendance 模块");
+        UKEAttendanceListPage.startInstance();
         break;
       case 'report':
-        ToastEngine.show("点击 report 模块");
+        UKReportListPage.startInstance();
         break;
     }
   }
 
   /// 跳转到设置页面
-  void gotoSettingPage() {}
+  void gotoSettingPage() {
+    ComponentRouterServices.authService.startSettingPage();
+  }
 }

+ 0 - 0
packages/cpt_uk/lib/modules/report/report_export.dart


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

@@ -0,0 +1,79 @@
+import 'package:domain/entity/home_module.dart';
+import 'package:domain/entity/response/hotel_info_entity.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/service/app_config_service.dart';
+import 'package:plugin_basic/service/user_service.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import 'report_list_state.dart';
+
+class ReportListController extends GetxController {
+  final ReportListState state = ReportListState();
+
+  /// 获取报表的数据
+  void setupReportData() async {
+    final hotelInfo = UserService.to.getHotelInfo;
+
+    // List<HotelInfoMenusChildren>? list = hotelInfo.menus?.firstWhereOrNull((element) => element.key == "report")?.children;
+    //
+    // Log.d("list:$list");
+    //
+    // if (list != null && list.isNotEmpty) {
+    //   //有数据,判断是刷新还是加载更多的数据
+    //   state.datas.clear();
+    //
+    //   //如果是管理员登录,根据Key筛选需要展示的模块
+    //   for (var children in list) {
+    //     if (children.key != null) {
+    //       state.datas.addAll(_filterModulesByKey(children.key!));
+    //     }
+    //   }
+    // } else {
+    //   //清除
+    //   state.datas.clear();
+    // }
+
+    state.datas.clear();
+    state.datas.addAll(state.modules);
+
+    update();
+  }
+
+  List<HomeModule> _filterModulesByKey(String key) {
+    return state.modules.where((module) => module.key == key).toList();
+  }
+
+  @override
+  void onReady() async {
+    super.onReady();
+    setupReportData();
+  }
+
+  /// 跳转到指定的模块中去
+  void gotoReportPage(HomeModule module) {
+    switch (module.key) {
+      case 'labour':
+        ToastEngine.show("labour");
+        break;
+      case 'outlet':
+        ToastEngine.show("outlet");
+        break;
+      case 'finale':
+        ToastEngine.show("finale");
+        break;
+      case 'hours':
+        ToastEngine.show("hours");
+        break;
+      case 'attendance':
+        ToastEngine.show("attendance");
+        break;
+      case 'payout':
+        ToastEngine.show("payout");
+        break;
+      case 'casual':
+        ToastEngine.show("casual");
+        break;
+    }
+  }
+}

+ 55 - 0
packages/cpt_uk/lib/modules/report/report_list/report_list_item.dart

@@ -0,0 +1,55 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/home_module.dart';
+import 'package:flutter/material.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+class ReportListItem extends StatelessWidget {
+  final HomeModule item;
+  final VoidCallback onTap;
+
+  ReportListItem(this.item, this.onTap);
+
+  @override
+  Widget build(BuildContext context) {
+    return GestureDetector(
+      onTap: onTap,
+      child: Container(
+        margin: const EdgeInsets.only(top: 5, bottom: 5),
+        padding: const EdgeInsets.only(left: 15, right: 16.5, top: 8, bottom: 8),
+        decoration: BoxDecoration(
+          color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+          borderRadius: BorderRadius.circular(5), // 设置圆角
+        ),
+        child: Row(
+          children: [
+            MyAssetImage(
+              item.moduleIconPath,
+              width: item.iconWidth,
+              height: item.iconHeight,
+            ),
+
+            // 模块的名称
+            MyTextView(
+              item.moduleName,
+              textColor: ColorConstants.textGrayAECAE5,
+              isTextEllipsis: true,
+              maxLines: 2,
+              isFontMedium: true,
+              margin: 20,
+              fontSize: 14,
+            ).expanded(),
+
+            const MyAssetImage(
+              Assets.mainItemMoreIcon,
+              width: 7.5,
+              height: 13.5,
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 95 - 0
packages/cpt_uk/lib/modules/report/report_list/report_list_page.dart

@@ -0,0 +1,95 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/base/base_stateful_page.dart';
+import 'package:plugin_basic/base/base_state.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/my_appbar.dart';
+
+import 'package:widgets/widget_export.dart';
+
+import 'report_list_controller.dart';
+import 'report_list_item.dart';
+import 'report_list_state.dart';
+
+/*
+ * 报表的列表
+ */
+class UKReportListPage extends BaseStatefulPage<ReportListController> {
+  UKReportListPage({super.key});
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKReportList);
+  }
+
+  @override
+  State<UKReportListPage> createState() => _MainPageState();
+
+  @override
+  ReportListController createRawController() {
+    return ReportListController();
+  }
+}
+
+class _MainPageState extends BaseState<UKReportListPage, ReportListController> {
+  late ReportListState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    //双击退出应用
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: true,
+        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,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              MyAppBar.titleBar(context, "Report".tr),
+
+              //底部的列表
+              EasyRefresh(
+                controller: null,
+                onRefresh: null,
+                child: ListView.builder(
+                  padding: const EdgeInsets.only(top: 0),
+                  itemCount: state.datas.length,
+                  itemBuilder: (_, int index) {
+                    return ReportListItem(state.datas[index], () {
+                      controller.gotoReportPage(state.datas[index]);
+                    });
+                  },
+                ),
+              ).paddingOnly(left: 15, right: 15, top: 10, bottom: 15).expanded(),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}

+ 20 - 0
packages/cpt_uk/lib/modules/report/report_list/report_list_state.dart

@@ -0,0 +1,20 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/home_module.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class ReportListState {
+  //当前显示的模块
+  List<HomeModule> datas = [];
+
+  //全部的模块
+  final List<HomeModule> modules = [
+    HomeModule(key: 'labour', moduleName: 'Labour Request'.tr, moduleIconPath: Assets.cptReportUkReportLabour, iconWidth: 40, iconHeight: 40),
+    HomeModule(key: 'outlet', moduleName: 'Outlet Request'.tr, moduleIconPath: Assets.cptReportUkReportOutlet, iconWidth: 40, iconHeight: 40),
+    HomeModule(key: 'finale', moduleName: 'Finance Report'.tr, moduleIconPath: Assets.cptReportUkReportFinale, iconWidth: 40, iconHeight: 40),
+    HomeModule(key: 'hours', moduleName: 'Working Hours'.tr, moduleIconPath: Assets.cptReportUkReportWorkHours, iconWidth: 40, iconHeight: 40),
+    HomeModule(key: 'attendance', moduleName: 'E-Attendance'.tr, moduleIconPath: Assets.cptReportUkReportAttendance, iconWidth: 40, iconHeight: 40),
+    HomeModule(key: 'payout', moduleName: 'Casual Payout'.tr, moduleIconPath: Assets.cptReportUkReportCasualPayout, iconWidth: 40, iconHeight: 40),
+    HomeModule(key: 'casual', moduleName: 'Casual Report'.tr, moduleIconPath: Assets.cptReportUkReportCasual, iconWidth: 40, iconHeight: 40),
+  ];
+
+}

+ 249 - 0
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_controller.dart

@@ -0,0 +1,249 @@
+import 'package:domain/entity/response/attendance_review_entity.dart';
+import 'package:domain/repository/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/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 'attendance_review_reject_dialog.dart';
+import 'attendance_review_state.dart';
+
+class AttendanceReviewController extends GetxController with DioCancelableMixin {
+  final JobRepository _jobRepository = Get.find();
+  final AttendanceReviewState state = AttendanceReviewState();
+
+  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;
+    fetchAppliedStaffList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchAppliedStaffList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchAppliedStaffList();
+  }
+
+  /// 获取服务器数据,通知消息列表
+  Future fetchAppliedStaffList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading);
+    }
+
+    // 并发执行两个请求
+    final listResult = await _jobRepository.fetchAttendanceReviewList(
+      state.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<AttendanceReviewRows>? 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();
+    fetchAppliedStaffList();
+  }
+
+  @override
+  void onClose() {
+    state.datas.clear();
+    super.onClose();
+  }
+
+  /// 搜索
+  void doSearch(String keyword) {
+    state.keyword = keyword;
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  /// 清空筛选条件
+  void resetFiltering() {
+    state.keyword = "";
+    state.searchController.text = "";
+
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  /// Item选中与未选中设置
+  void doSelectedOrNot(AttendanceReviewRows data) {
+    data.isSelected = !data.isSelected;
+    Log.d("isSelected:${data.isSelected}");
+    update();
+  }
+
+  /// 执行批量同意
+  void _requestBatchApprove(String recordIds) async {
+    //执行请求
+    var result = await _jobRepository.approveAttendanceReviews(
+      recordIds,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //调用接口刷新指定的Staff的信息
+      _removeItemsByList(recordIds);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  /// 执行批量拒绝
+  void _requestBatchReject(String recordIds, String? reason) async {
+    //执行请求
+    var result = await _jobRepository.rejectLabourReviews(
+      recordIds,
+      reason,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //调用接口刷新指定的Staff的信息
+      _removeItemsByList(recordIds);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  /// 批准的操作
+  void operationApprove() async {
+    //找出已经选中的员工(只有状态为3 Approve的状态才能修改)
+    var selectedList = state.datas.where((element) => element.isSelected).toList(growable: false);
+    if (selectedList.isNotEmpty) {
+      var ids = selectedList.map((e) => e.recordId.toString()).toList(growable: false);
+      var recordIds = ids.join(',');
+
+      // Are you sure 的弹窗
+      DialogEngine.show(
+        widget: AppDefaultDialog(
+          title: "Message".tr,
+          message: "Are you sure you want to setting approved?".tr,
+          confirmAction: () {
+            _requestBatchApprove(recordIds);
+          },
+        ),
+      );
+    } else {
+      ToastEngine.show("Please select the record".tr);
+    }
+  }
+
+  /// 拒绝的操作
+  void operationReject() async {
+    //找出已经选中的员工(只有状态为3 Approve的状态才能修改)
+    var selectedList = state.datas.where((element) => element.isSelected).toList(growable: false);
+    if (selectedList.isNotEmpty) {
+      var ids = selectedList.map((e) => e.recordId.toString()).toList(growable: false);
+      var recordIds = ids.join(',');
+
+      // Are you sure 的弹窗
+      DialogEngine.show(
+        widget: AttendaceReviewRejectDialog(
+          confirmAction: (reason) {
+            //请求接口,提交评论
+            _requestBatchReject(recordIds, reason);
+          },
+        ),
+      );
+    } else {
+      ToastEngine.show("Please select the record".tr);
+    }
+  }
+
+  /// 删除对应的recordId的Item数据
+  void _removeItemsByList(String recordIds) {
+    // 将逗号分隔的字符串转换为数组
+    List<String> recordIdList = recordIds.split(',');
+
+    // 移除列表中符合条件的项
+    state.datas.removeWhere((e) => recordIdList.contains(e.recordId));
+
+    update();
+  }
+
+  /// 去用工审核流程页面
+  void gotoStatusViewPage(AttendanceReviewRows data) {
+    ToastEngine.show("去工作流页面");
+  }
+}

+ 329 - 0
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_item.dart

@@ -0,0 +1,329 @@
+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: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_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+/*
+ * 用工审核的列表Item
+ */
+class AttendanceReviewItem extends StatelessWidget {
+  final int index;
+  final AttendanceReviewRows item;
+  final VoidCallback? onStatusAction;
+  final VoidCallback? onItemAction;
+
+  AttendanceReviewItem({
+    required this.index,
+    required this.item,
+    this.onStatusAction,
+    this.onItemAction,
+  });
+
+  @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(
+                "Staff Name:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //姓名
+              MyTextView(
+                item.staffName ?? "-",
+                isFontRegular: true,
+                textColor: ColorConstants.white,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+              ).expanded(),
+
+              //是否选中
+              MyAssetImage(
+                item.isSelected ? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedIcon,
+                width: 20.5,
+                height: 20.5,
+              ),
+            ],
+          ),
+
+          // 工作标题
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Title".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.jobTitle ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 部门
+          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(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 工作时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "DateTime:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.jobTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          //考勤时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Clock Time".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                "${item.clockIn} - ${item.clockOut}",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+
+          // + - Hours
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "+/- Hours:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //小时
+              MyTextView(
+                Utils.isNotEmpty(item.adjustShow) ? item.adjustShow! : "0",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // Total Hours
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Total (Hrs/Rms)".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //小时
+              MyTextView(
+                item.totalShow.toString(),
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 状态
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Status:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                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(),
+            ],
+          ).marginOnly(top: 12),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created At:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.createdAt ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).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),
+          // ),
+        ],
+      ),
+    ).onTap(() {
+      onItemAction?.call();
+    });
+  }
+}

+ 173 - 0
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_page.dart

@@ -0,0 +1,173 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.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/widget_export.dart';
+
+import 'attendance_review_item.dart';
+import 'attendance_review_controller.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 'attendance_review_state.dart';
+
+/*
+ * 工作考勤的审核列表
+ */
+class UKAttendanceReviewPage extends BaseStatefulPage<AttendanceReviewController> {
+  UKAttendanceReviewPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKAttendanceReviewList);
+  }
+
+  @override
+  AttendanceReviewController createRawController() {
+    return AttendanceReviewController();
+  }
+
+  @override
+  State<UKAttendanceReviewPage> createState() => _LabourReviewState();
+}
+
+class _LabourReviewState extends BaseState<UKAttendanceReviewPage, AttendanceReviewController> {
+  late AttendanceReviewState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: true,
+        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.searchTitleBar(
+                context,
+                value: state.keyword,
+                hintText: 'Title'.tr,
+                controller: state.searchController,
+                onSearch: (keyword) {
+                  controller.doSearch(keyword);
+                },
+                actions: [
+                  //重置按钮
+                  MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      controller.resetFiltering();
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(right: 15),
+
+                ],
+              ),
+
+              //底部的列表
+              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 AttendanceReviewItem(
+                          index: index,
+                          item: state.datas[index],
+                          onStatusAction: () {
+
+                          },
+                          onItemAction: () {
+                            controller.doSelectedOrNot(state.datas[index]);
+                          },
+                        );
+                      },
+                      childCount: state.datas.length,
+                    ))
+                  ],
+                ),
+              ).expanded(),
+
+              Row(
+                mainAxisSize: MainAxisSize.max,
+                children: [
+                  //批量Approve
+                  MyTextView(
+                    "Batch Confirm".tr,
+                    fontSize: 17,
+                    isFontMedium: true,
+                    boxHeight: 48,
+                    onClick: () {
+                      controller.operationApprove();
+                    },
+                    alignment: Alignment.center,
+                    textAlign: TextAlign.center,
+                    textColor: Colors.white,
+                    backgroundColor: ColorConstants.textGreen0AC074,
+                  ).expanded(),
+
+                  //批量修改时间
+                  MyTextView(
+                    "Batch Reject".tr,
+                    fontSize: 17,
+                    isFontMedium: true,
+                    boxHeight: 48,
+                    onClick: () {
+                      controller.operationReject();
+                    },
+                    alignment: Alignment.center,
+                    textAlign: TextAlign.center,
+                    textColor: Colors.white,
+                    backgroundColor: ColorConstants.textRedFF6262,
+                  ).expanded(),
+                ],
+              ),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}

+ 187 - 0
packages/cpt_uk/lib/modules/review/attendance_review_list/attendance_review_reject_dialog.dart

@@ -0,0 +1,187 @@
+import 'dart:ui';
+
+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_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 拒绝的弹窗
+ */
+class AttendaceReviewRejectDialog extends StatefulWidget {
+
+  void Function(String reason)? confirmAction;
+
+  AttendaceReviewRejectDialog({this.confirmAction});
+
+  @override
+  State<AttendaceReviewRejectDialog> createState() => _AttendaceReviewRejectDialogState();
+}
+
+class _AttendaceReviewRejectDialogState extends State<AttendaceReviewRejectDialog> {
+
+  late TextEditingController _controller;
+  late FocusNode _focusNode;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = TextEditingController();
+    _focusNode = FocusNode();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        //Title (如果使用 Container 为最外层容器则默认为 match_parent 的效果,除非我们限制宽度和最大高度最小高度)
+        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(
+                  "Reason for refusal".tr,
+                  fontSize: 19,
+                  isFontMedium: true,
+                  textColor: ColorConstants.black,
+                  marginTop: 23,
+                  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: true,
+                    focusNode: _focusNode,
+                    controller: _controller,
+                    // 装饰
+                    decoration: InputDecoration(
+                      isDense: true,
+                      isCollapsed: true,
+                      border: InputBorder.none,
+                      hintText: "Enter...".tr,
+                      hintStyle: const 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,
+              ),
+
+              //按钮组
+              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),
+            ],
+          ),
+        ),
+      ],
+    ).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);
+  }
+}

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

@@ -0,0 +1,12 @@
+import 'package:domain/entity/response/attendance_review_entity.dart';
+import 'package:flutter/material.dart';
+
+class AttendanceReviewState {
+  //筛选条件
+  final TextEditingController searchController = TextEditingController();
+  String keyword = "";
+
+  //页面的列表数据
+  List<AttendanceReviewRows> datas = [];
+
+}

+ 196 - 0
packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_controller.dart

@@ -0,0 +1,196 @@
+import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'package:domain/repository/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/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/util.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+
+import 'labour_review_edit_state.dart';
+
+class LabourReviewEditController extends GetxController with DioCancelableMixin {
+  final LabourRepository _labourRepository = Get.find();
+  final LabourReviewEditState state = LabourReviewEditState();
+
+  /// 获取首页的数据
+  void fetchRequestDetail() async {
+    //获取到数据
+
+    final taskFuture = _labourRepository.fetchLabourReviewDetail(state.requestId, cancelToken: cancelToken);
+
+    var result = await taskFuture;
+
+    //处理数据
+    if (result.isSuccess) {
+      state.labReqOption = result.data;
+      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();
+      var needNumController = state.formData['no_of_staff']!['controller'];
+      needNumController.text = state.noStaff;
+      var amountController = state.formData['amount']!['controller'];
+      amountController.text = state.labReqOption?.amount ?? "";
+      state.selectedTemplateId = state.labReqOption?.templateId;
+      state.selectedDepartmentId = state.labReqOption?.departmentId;
+
+      state.chargeOptionId = state.labReqOption?.chargeList.firstWhere((element) => element.checked == "checked").value;
+
+      update();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  @override
+  void onReady() {
+    super.onReady();
+    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);
+    }
+  }
+
+  // 筛选工作模板
+  void pickJobTitle() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    int selectedTemplateIndex;
+    if (state.selectedTemplateId == null) {
+      selectedTemplateIndex = 0;
+    } else {
+      selectedTemplateIndex = state.labReqOption!.templateList.indexWhere((department) => department.value.toString() == state.selectedTemplateId);
+    }
+
+    if (selectedTemplateIndex < 0) {
+      selectedTemplateIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.labReqOption!.templateList.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedTemplateIndex,
+      onPickerChanged: (_, index) {
+        state.selectedTemplateId = state.labReqOption!.templateList[index].value!.toString();
+        update();
+      },
+    );
+  }
+
+  //选择开始时间
+  void pickStartTime() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.selectedStartTime,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.selectedStartTime = date;
+        update();
+      },
+      title: "Start Time".tr,
+    );
+  }
+
+  // 选择结束时间
+  void pickEndTime() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: state.selectedEndTime ?? state.selectedStartTime,
+      mode: CupertinoDatePickerMode.dateAndTime,
+      onDateTimeChanged: (date) {
+        state.selectedEndTime = date;
+        update();
+      },
+      title: "End Time".tr,
+    );
+  }
+
+  // 筛选部门
+  void pickDepartment() {
+    if (state.labReqOption == null || state.pageType == 2) {
+      return;
+    }
+
+    int selectedDepartmentIndex;
+    if (state.selectedDepartmentId == null) {
+      selectedDepartmentIndex = 0;
+    } else {
+      selectedDepartmentIndex = state.labReqOption!.departmentList.indexWhere((department) => department.value.toString() == state.selectedDepartmentId);
+    }
+
+    if (selectedDepartmentIndex < 0) {
+      selectedDepartmentIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.labReqOption!.departmentList.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedDepartmentIndex,
+      onPickerChanged: (_, index) {
+        state.selectedDepartmentId = state.labReqOption!.departmentList[index].value!.toString();
+        update();
+      },
+    );
+  }
+}

+ 357 - 0
packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_page.dart

@@ -0,0 +1,357 @@
+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';
+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/date_time_utils.dart';
+import 'package:shared/utils/screen_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_radio_check.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/round_my_text_field.dart';
+
+import 'labour_review_edit_controller.dart';
+import 'labour_review_edit_state.dart';
+
+class UKLabourReviewEditPage extends BaseStatefulPage<LabourReviewEditController> {
+  UKLabourReviewEditPage({Key? key}) : super(key: key);
+
+  //启动当前页面,pageType  1是编辑  2是详情
+  static void startInstance(int pageType, String? requestId,void Function(dynamic value)? cb) {
+    return Get.start(RouterPath.UKLabourReviewEdit, arguments: {'pageType': pageType, 'requestId': requestId,'cb': cb});
+  }
+
+  @override
+  LabourReviewEditController createRawController() {
+    return LabourReviewEditController();
+  }
+
+  @override
+  State<UKLabourReviewEditPage> createState() => _LabourReviewEditState();
+}
+
+class _LabourReviewEditState extends BaseState<UKLabourReviewEditPage, LabourReviewEditController> {
+  late LabourReviewEditState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.pageType = Get.arguments['pageType'];
+    state.requestId = Get.arguments['requestId'];
+    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 == 1 ? "Edit Labour Requisition".tr : "Labour Requisition".tr),
+        body: SafeArea(
+          bottom: true,
+          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: [
+                      //工作标题,选择模板
+                      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),
+                      ),
+                    ],
+                  ).paddingOnly(left: 15, right: 15),
+                ),
+              ),
+            ),
+          ),
+        ),
+      );
+    });
+  }
+}

+ 41 - 0
packages/cpt_uk/lib/modules/review/labour_review_edit/labour_review_edit_state.dart

@@ -0,0 +1,41 @@
+import 'package:domain/entity/response/labour_request_edit_index_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class LabourReviewEditState {
+
+  int pageType = 2;  //页面的状态 1是编辑  2是详情
+  String? requestId;  //编辑和详情需要用到ID
+  void Function(dynamic value)? cb;
+
+  //页面对应的详情数据
+  LabourRequestEditIndexEntity? labReqOption;
+
+  //页面对应的选择的条件
+  DateTime? selectedStartTime;
+  DateTime? selectedEndTime;
+  String? selectedTemplateId;
+  String? selectedDepartmentId;
+  String? noStaff;  //成员数量
+
+  String? chargeOptionId;
+
+  //表单的校验与数据
+  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,
+    },
+  };
+
+}

+ 345 - 0
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_controller.dart

@@ -0,0 +1,345 @@
+import 'package:domain/entity/response/labour_request_index_entity.dart';
+import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:domain/repository/labour_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: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/widget_export.dart';
+import '../labour_review_edit/labour_review_edit_page.dart';
+import '../labour_review_workflow/labour_request_workflow_page.dart';
+import 'labour_review_filter.dart';
+import 'labour_review_reject_dialog.dart';
+import 'labour_review_state.dart';
+
+class LabourReviewController extends GetxController with DioCancelableMixin {
+  final LabourRepository _labourRepository = Get.find();
+  final LabourReviewState state = LabourReviewState();
+
+  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;
+    fetchAppliedStaffList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchAppliedStaffList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchAppliedStaffList();
+  }
+
+  /// 获取服务器数据,通知消息列表
+  Future fetchAppliedStaffList() 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,
+      ),
+      state.indexOptions == null
+          ? _labourRepository.fetchLabourReviewIndex(
+              cancelToken: cancelToken,
+            )
+          : Future(() => HttpResult(isSuccess: true).convert(data: state.indexOptions!)),
+    ];
+
+    //拿到结果
+    var results = await Future.wait(futures);
+    var listResult = results[0] as HttpResult<LabourReviewListEntity>;
+    var optionResult = results[1] as HttpResult<LabourRequestIndexEntity>;
+
+    //选项数据
+    if (state.indexOptions == null && optionResult.isSuccess) {
+      state.indexOptions = optionResult.data!;
+    }
+
+    // 处理数据
+    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();
+
+        //更新展示的状态
+        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();
+    fetchAppliedStaffList();
+  }
+
+  @override
+  void onClose() {
+    state.datas.clear();
+    super.onClose();
+  }
+
+  /// 搜索
+  void doSearch(String keyword) {
+    state.keyword = keyword;
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  /// 清空筛选条件
+  void resetFiltering() {
+    state.keyword = "";
+    state.searchController.text = "";
+    state.selectedStartDate = null;
+    state.selectedEndDate = null;
+    state.selectedDepartmentId = null;
+    //赋值之后刷新
+    refreshController.callRefresh();
+  }
+
+  /// Item选中与未选中设置
+  void doSelectedOrNot(LabourReviewListRows data) {
+    data.isSelected = !data.isSelected;
+    Log.d("isSelected:${data.isSelected}");
+    update();
+  }
+
+  /// 执行批量同意
+  void _requestBatchApprove(String recordIds) async {
+    //执行请求
+    var result = await _labourRepository.approveLabourReviews(
+      recordIds,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //调用接口刷新指定的Staff的信息
+      _removeItemsByList(recordIds);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  /// 执行批量拒绝
+  void _requestBatchReject(String recordIds, String? reason) async {
+    //执行请求
+    var result = await _labourRepository.rejectLabourReviews(
+      recordIds,
+      reason,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess("Successful".tr);
+
+      //调用接口刷新指定的Staff的信息
+      _removeItemsByList(recordIds);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+      return;
+    }
+  }
+
+  /// 批准的操作
+  void operationApprove() async {
+    //找出已经选中的员工(只有状态为3 Approve的状态才能修改)
+    var selectedList = state.datas.where((element) => element.isSelected).toList(growable: false);
+    if (selectedList.isNotEmpty) {
+      var ids = selectedList.map((e) => e.recordId.toString()).toList(growable: false);
+      var recordIds = ids.join(',');
+
+      // Are you sure 的弹窗
+      DialogEngine.show(
+        widget: AppDefaultDialog(
+          title: "Message".tr,
+          message: "Are you sure you want to setting approved?".tr,
+          confirmAction: () {
+            _requestBatchApprove(recordIds);
+          },
+        ),
+      );
+    } else {
+      ToastEngine.show("Please select the record".tr);
+    }
+  }
+
+  /// 拒绝的操作
+  void operationReject() async {
+    //找出已经选中的员工(只有状态为3 Approve的状态才能修改)
+    var selectedList = state.datas.where((element) => element.isSelected).toList(growable: false);
+    if (selectedList.isNotEmpty) {
+      var ids = selectedList.map((e) => e.recordId.toString()).toList(growable: false);
+      var recordIds = ids.join(',');
+
+      // Are you sure 的弹窗
+      DialogEngine.show(
+        widget: LabourReviewRejectDialog(
+          confirmAction: (reason) {
+            //请求接口,提交评论
+            _requestBatchReject(recordIds, reason);
+          },
+        ),
+      );
+    } else {
+      ToastEngine.show("Please select the record".tr);
+    }
+  }
+
+  /// 删除对应的recordId的Item数据
+  void _removeItemsByList(String recordIds) {
+    // 将逗号分隔的字符串转换为数组
+    List<String> recordIdList = recordIds.split(',');
+
+    // 移除列表中符合条件的项
+    state.datas.removeWhere((e) => recordIdList.contains(e.recordId));
+
+    update();
+  }
+
+  /// 展示顶部的筛选
+  void showFilterDialog() {
+    if (state.indexOptions != null) {
+      DialogEngine.show(
+        widget: LabourReviewFilter(
+          optionResult: state.indexOptions!,
+          selectedStartDate: state.selectedStartDate,
+          selectedEndDate: state.selectedEndDate,
+          selectedDepartmentId: state.selectedDepartmentId,
+          onFilterAction: (startDate, endDate, departmentId) {
+            state.selectedStartDate = startDate;
+            state.selectedEndDate = endDate;
+            state.selectedDepartmentId = departmentId;
+
+            //赋值之后刷新
+            refreshController.callRefresh();
+          },
+        ),
+        position: DialogPosition.top,
+        animType: DialogAnimation.fade,
+      );
+    }
+  }
+
+  /// 去详情页面
+  void gotoDetailPage(LabourReviewListRows data) {
+    UKLabourReviewEditPage.startInstance(2, data.requestId, null);
+  }
+
+  /// 去编辑页面
+  void gotoEditPage(LabourReviewListRows data) {
+    UKLabourReviewEditPage.startInstance(1, data.requestId, (result) {
+      if (Utils.isNotEmpty(result)) {
+        fetchItemByIdAndRefreshItem(data.recordId);
+      }
+    });
+  }
+
+  /// 去用工审核流程页面
+  void gotoStatusViewPage(LabourReviewListRows data) {
+    UKLabourReviewWorkflowPage.startInstance(data.requestId);
+  }
+
+  /// 根据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);
+    }
+  }
+}

+ 318 - 0
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_filter.dart

@@ -0,0 +1,318 @@
+import 'dart:typed_data';
+import 'dart:ui';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/labour_request_index_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/date_time_utils.dart';
+import 'package:shared/utils/screen_util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:widgets/my_button.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/picker/option_pick_util.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 用工请求列表的筛选
+ */
+class LabourReviewFilter extends StatefulWidget {
+  void Function(DateTime? selectedStartDate, DateTime? selectedEndDate, String? selectedDepartmentId)? onFilterAction;
+  LabourRequestIndexEntity optionResult;
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedDepartmentId;
+
+  LabourReviewFilter({
+    required this.optionResult,
+    required this.selectedStartDate,
+    required this.selectedEndDate,
+    required this.selectedDepartmentId,
+    this.onFilterAction,
+  });
+
+  @override
+  State<LabourReviewFilter> createState() => _LabourReviewFilterState();
+}
+
+class _LabourReviewFilterState extends State<LabourReviewFilter> {
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedStatusId;
+  String? selectedDepartmentId;
+
+  @override
+  void initState() {
+    super.initState();
+    this.selectedStartDate = widget.selectedStartDate;
+    this.selectedEndDate = widget.selectedEndDate;
+    this.selectedDepartmentId = widget.selectedDepartmentId;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        SizedBox(
+          height: kToolbarHeight + ScreenUtil.getStatusBarH(context) + 1,
+        ),
+        Container(
+          padding: const EdgeInsets.only(left: 15, right: 15, top: 17.5, bottom: 20),
+          width: double.infinity,
+          decoration: const BoxDecoration(
+            color: Colors.white,
+          ),
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              //部门
+              MyTextView(
+                "Outlet".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择部门
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedDepartmentId == null || selectedDepartmentId == "0"
+                          ? ""
+                          : widget.optionResult.departmentList!.firstWhere((element) => element.value.toString() == selectedDepartmentId).txt!,
+                      hint: "Choose Outlet".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      fontSize: 14,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerOutlet();
+              }),
+
+              //开始时间
+              MyTextView(
+                "Start Date".tr,
+                fontSize: 14,
+                isFontMedium: true,
+                marginTop: 11,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择时间
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedStartDate == null ? "" : DateTimeUtils.formatDate(selectedStartDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose Start Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerStartDate();
+              }),
+
+              //结束日期
+              MyTextView(
+                "End Date".tr,
+                fontSize: 14,
+                marginTop: 11,
+                isFontMedium: true,
+                textColor: ColorConstants.black33,
+              ),
+
+              //选择结束日期
+              Container(
+                padding: const EdgeInsets.only(left: 16, right: 10),
+                margin: const EdgeInsets.only(top: 10),
+                height: 45,
+                decoration: const BoxDecoration(
+                  color: ColorConstants.grayECECEC,
+                  borderRadius: BorderRadius.all(Radius.circular(5)),
+                ),
+                child: Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      selectedEndDate == null ? "" : DateTimeUtils.formatDate(selectedEndDate, format: "yyyy-MM-dd"),
+                      fontSize: 14,
+                      hint: "Choose End Date".tr,
+                      textHintColor: ColorConstants.textBlackHint,
+                      isFontMedium: true,
+                      textColor: ColorConstants.black33,
+                    ).expanded(),
+                    const MyAssetImage(Assets.baseServiceTriangleDropDownIcon, width: 11.5, height: 6.28),
+                  ],
+                ),
+              ).onTap(() {
+                pickerEndDate();
+              }),
+
+              //按钮组
+              Row(
+                children: [
+                  MyButton(
+                    onPressed: () {
+                      //只是Reset当前的弹窗筛选选项
+                      widget.selectedStartDate = null;
+                      widget.selectedEndDate = null;
+                      widget.selectedDepartmentId = null;
+
+                      setState(() {
+                        selectedStartDate = null;
+                        selectedEndDate = null;
+                        selectedStatusId = null;
+                        selectedDepartmentId = null;
+                      });
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#FFBB1B"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                  SizedBox(width: 15),
+                  MyButton(
+                    onPressed: () {
+                      onCancel();
+                      widget.onFilterAction?.call(selectedStartDate, selectedEndDate, selectedDepartmentId);
+                    },
+                    text: "Filter".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#0AC074"),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 36,
+                  ).expanded(),
+                ],
+              ).marginOnly(top: 20),
+            ],
+          ),
+        ),
+        Center(child: const MyAssetImage(Assets.baseServiceDialogDeleteIcon, width: 26.5, height: 26.5).marginOnly(top: 35)).onTap(() {
+          onCancel();
+        }),
+      ],
+    );
+  }
+
+  //取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+
+  /// 筛选开始日期
+  void pickerStartDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedStartDate = date;
+        });
+      },
+      title: "Start Date".tr,
+    );
+  }
+
+  /// 筛选结束日期
+  void pickerEndDate() {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedEndDate ?? selectedStartDate,
+      onDateTimeChanged: (date) {
+        setState(() {
+          selectedEndDate = date;
+        });
+      },
+      title: "End Date".tr,
+    );
+  }
+
+  /// 筛选部门
+  void pickerOutlet() {
+    int selectedDepartmentIndex;
+    if (selectedDepartmentId == null) {
+      selectedDepartmentIndex = 0;
+    } else {
+      selectedDepartmentIndex = widget.optionResult.departmentList!.indexWhere((department) => department.value.toString() == selectedDepartmentId);
+    }
+
+    if (selectedDepartmentIndex < 0) {
+      selectedDepartmentIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: widget.optionResult.departmentList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedDepartmentIndex,
+      onPickerChanged: (_, index) {
+        setState(() {
+          selectedDepartmentId = widget.optionResult.departmentList![index].value!.toString();
+        });
+      },
+    );
+  }
+
+  /// 筛选状态
+  void pickerStatus() {
+    int selectedStatusIndex;
+    if (selectedStatusId == null) {
+      selectedStatusIndex = 0;
+    } else {
+      selectedStatusIndex = widget.optionResult.statusList!.indexWhere((department) => department.value.toString() == selectedStatusId);
+    }
+
+    if (selectedStatusIndex < 0) {
+      selectedStatusIndex = 0;
+    }
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: widget.optionResult.statusList!.map((e) => e.txt!).toList(growable: false),
+      initialSelectIndex: selectedStatusIndex,
+      onPickerChanged: (_, index) {
+        setState(() {
+          selectedStatusId = widget.optionResult.statusList![index].value!.toString();
+        });
+      },
+    );
+  }
+}

+ 292 - 0
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_item.dart

@@ -0,0 +1,292 @@
+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/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: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';
+
+/*
+ * 用工审核的列表Item
+ */
+class LabourReviewItem extends StatelessWidget {
+  final int index;
+  final LabourReviewListRows item;
+  final VoidCallback? onStatusAction;
+  final VoidCallback? onEditAction;
+  final VoidCallback? onDetailAction;
+  final VoidCallback? onItemAction;
+
+  LabourReviewItem({
+    required this.index,
+    required this.item,
+    this.onStatusAction,
+    this.onEditAction,
+    this.onDetailAction,
+    this.onItemAction,
+  });
+
+  @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(
+                item.jobTitle ?? "-",
+                isFontMedium: true,
+                textColor: ColorConstants.textYellowFFBB1B,
+                fontSize: 14,
+                marginLeft: 5,
+                marginRight: 5,
+                textDecoration: TextDecoration.underline,
+                decorationColor: ColorConstants.textYellowFFBB1B,
+                // 可选,设置下划线的颜色
+                decorationThickness: 2.0,
+                // 可选,设置下划线的粗细
+                decorationStyle: TextDecorationStyle.solid,
+              ).expanded(),
+
+              //是否选中
+              MyAssetImage(
+                item.isSelected ? Assets.baseServiceItemSelectedIcon : Assets.baseServiceItemUnselectedIcon,
+                width: 20.5,
+                height: 20.5,
+              ),
+            ],
+          ),
+
+          // 部门
+          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(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 工作日期时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Datetime:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期时间
+              MyTextView(
+                item.jobTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 人数
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            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(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 薪水
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "${"Salary".tr}:",
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                item.salaryShow ?? "-",
+                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: "Approved" == item.statusShow
+                    ? ColorConstants.textGreen05DC82
+                    : "Rejected" == item.statusShow
+                        ? ColorConstants.textRedFF6262
+                        : "Recall" == item.statusShow
+                            ? ColorConstants.textYellowFFBB1B
+                            : ColorConstants.textBlue06D9FF,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created 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.btnList?.isNotEmpty ?? false,
+            child: Row(
+              mainAxisSize: MainAxisSize.max,
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                //详情按钮
+                Visibility(
+                  visible: item.btnList?.contains("detail") ?? false,
+                  child: MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      onDetailAction?.call();
+                    },
+                    text: "Detail".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor(
+                      "#56AAFF",
+                    ),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(left: 12),
+                ),
+
+                //Edit按钮
+                Visibility(
+                  visible: item.btnList.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.btnList.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),
+                ),
+              ],
+            ).marginOnly(top: 18, bottom: 2),
+          ),
+        ],
+      ),
+    ).onTap(() {
+      onItemAction?.call();
+    });
+  }
+}

+ 189 - 0
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_page.dart

@@ -0,0 +1,189 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:cs_resources/generated/assets.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_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'labour_review_item.dart';
+import 'labour_review_controller.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 'labour_review_state.dart';
+
+/*
+ * 用工请求审核的列表
+ */
+class UKLabourReviewPage extends BaseStatefulPage<LabourReviewController> {
+  UKLabourReviewPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.UKLabourReviewList);
+  }
+
+  @override
+  LabourReviewController createRawController() {
+    return LabourReviewController();
+  }
+
+  @override
+  State<UKLabourReviewPage> createState() => _LabourReviewState();
+}
+
+class _LabourReviewState extends BaseState<UKLabourReviewPage, LabourReviewController> {
+  late LabourReviewState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return SafeArea(
+        bottom: true,
+        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.searchTitleBar(
+                context,
+                value: state.keyword,
+                hintText: 'Title'.tr,
+                controller: state.searchController,
+                onSearch: (keyword) {
+                  controller.doSearch(keyword);
+                },
+                actions: [
+                  //重置按钮
+                  MyButton(
+                    onPressed: () {
+                      FocusScope.of(context).unfocus();
+                      controller.resetFiltering();
+                    },
+                    text: "Reset".tr,
+                    textColor: ColorConstants.white,
+                    backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+                    radius: 17.25,
+                    minWidth: 60,
+                    minHeight: 35,
+                  ).marginOnly(right: 15),
+
+                  //筛选图标
+                  const MyAssetImage(
+                    Assets.baseServiceTitleBarFilterIcon,
+                    width: 24,
+                    height: 16.5,
+                  ).onTap(() {
+                    FocusScope.of(context).unfocus();
+                    controller.showFilterDialog();
+                  }).marginOnly(right: 15),
+                ],
+              ),
+
+              //底部的列表
+              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 LabourReviewItem(
+                          index: index,
+                          item: state.datas[index],
+                          onDetailAction: () {
+                            controller.gotoDetailPage(state.datas[index]);
+                          },
+                          onEditAction: () {
+                            controller.gotoEditPage(state.datas[index]);
+                          },
+                          onStatusAction: () {
+                            controller.gotoStatusViewPage(state.datas[index]);
+                          },
+                          onItemAction: () {
+                            controller.doSelectedOrNot(state.datas[index]);
+                          },
+                        );
+                      },
+                      childCount: state.datas.length,
+                    ))
+                  ],
+                ),
+              ).expanded(),
+
+              Row(
+                mainAxisSize: MainAxisSize.max,
+                children: [
+                  //批量Approve
+                  MyTextView(
+                    "Batch Confirm".tr,
+                    fontSize: 17,
+                    isFontMedium: true,
+                    boxHeight: 48,
+                    onClick: () {
+                      controller.operationApprove();
+                    },
+                    alignment: Alignment.center,
+                    textAlign: TextAlign.center,
+                    textColor: Colors.white,
+                    backgroundColor: ColorConstants.textGreen0AC074,
+                  ).expanded(),
+
+                  //批量修改时间
+                  MyTextView(
+                    "Batch Reject".tr,
+                    fontSize: 17,
+                    isFontMedium: true,
+                    boxHeight: 48,
+                    onClick: () {
+                      controller.operationReject();
+                    },
+                    alignment: Alignment.center,
+                    textAlign: TextAlign.center,
+                    textColor: Colors.white,
+                    backgroundColor: ColorConstants.textRedFF6262,
+                  ).expanded(),
+                ],
+              ),
+            ],
+          ),
+        ),
+      );
+    });
+  }
+}

+ 190 - 0
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_reject_dialog.dart

@@ -0,0 +1,190 @@
+import 'dart:ui';
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/job_list_remark_view_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_text_view.dart';
+import 'package:widgets/shatter/rating_widget.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 拒绝的弹窗
+ */
+class LabourReviewRejectDialog extends StatefulWidget {
+
+  void Function(String reason)? confirmAction;
+
+  LabourReviewRejectDialog({this.confirmAction});
+
+  @override
+  State<LabourReviewRejectDialog> createState() => _LabourReviewRejectDialogState();
+}
+
+class _LabourReviewRejectDialogState extends State<LabourReviewRejectDialog> {
+
+  late TextEditingController _controller;
+  late FocusNode _focusNode;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = TextEditingController();
+    _focusNode = FocusNode();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        //Title (如果使用 Container 为最外层容器则默认为 match_parent 的效果,除非我们限制宽度和最大高度最小高度)
+        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(
+                  "Reason for refusal".tr,
+                  fontSize: 19,
+                  isFontMedium: true,
+                  textColor: ColorConstants.black,
+                  marginTop: 23,
+                  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: true,
+                    focusNode: _focusNode,
+                    controller: _controller,
+                    // 装饰
+                    decoration: InputDecoration(
+                      isDense: true,
+                      isCollapsed: true,
+                      border: InputBorder.none,
+                      hintText: "Enter...".tr,
+                      hintStyle: const 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,
+              ),
+
+              //按钮组
+              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),
+            ],
+          ),
+        ),
+      ],
+    ).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);
+  }
+}

+ 16 - 0
packages/cpt_uk/lib/modules/review/labour_review_list/labour_review_state.dart

@@ -0,0 +1,16 @@
+import 'package:domain/entity/response/labour_request_index_entity.dart';
+import 'package:domain/entity/response/labour_review_list_entity.dart';
+import 'package:flutter/material.dart';
+
+class LabourReviewState {
+  //筛选条件
+  final TextEditingController searchController = TextEditingController();
+  String keyword = "";
+  DateTime? selectedStartDate;
+  DateTime? selectedEndDate;
+  String? selectedDepartmentId;
+
+  //页面的列表数据
+  List<LabourReviewListRows> datas = [];
+  LabourRequestIndexEntity? indexOptions;
+}

+ 102 - 0
packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_request_workflow_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 'labour_review_workflow_controller.dart';
+import 'labour_request_workflow_state.dart';
+import 'labour_review_workflow_item.dart';
+
+/*
+ * 用工请求审核-状态工作流列表
+ */
+class UKLabourReviewWorkflowPage extends BaseStatefulPage<LabourReviewWorkflowController> {
+  UKLabourReviewWorkflowPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance(String? requestId) {
+    return Get.start(RouterPath.UKLabourReviewWorkflow,arguments: {'requestId': requestId});
+  }
+
+  @override
+  LabourReviewWorkflowController createRawController() {
+    return LabourReviewWorkflowController();
+  }
+
+  @override
+  State<UKLabourReviewWorkflowPage> createState() => _LabourReviewWorkflowState();
+
+}
+
+class _LabourReviewWorkflowState extends BaseState<UKLabourReviewWorkflowPage, LabourReviewWorkflowController> {
+
+  late LabourReviewWorkflowState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+    state.requestId = Get.arguments['requestId'];
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return autoCtlGetBuilder(builder: (controller) {
+      return  SafeArea(
+          bottom: true,
+          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, "Workflow".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 LabourReviewWorkFlowItem(index: index,item: state.datas[index]);
+                            },
+                            childCount: state.datas.length,
+                          ))
+                    ],
+                  ),
+                ).expanded(),
+              ],
+            ).marginOnly(top: 10),
+          ),
+        );
+    });
+  }
+}
+
+

+ 10 - 0
packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_request_workflow_state.dart

@@ -0,0 +1,10 @@
+import 'package:domain/entity/response/labour_review_status_entity.dart';
+
+class LabourReviewWorkflowState {
+
+  String? requestId;
+
+  //页面的列表数据
+  List<LabourReviewStatusRecords> datas = [];
+
+}

+ 96 - 0
packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_review_workflow_controller.dart

@@ -0,0 +1,96 @@
+import 'package:domain/entity/response/labour_review_status_entity.dart';
+import 'package:domain/repository/labour_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 'labour_request_workflow_state.dart';
+
+
+class LabourReviewWorkflowController extends GetxController with DioCancelableMixin{
+  final LabourRepository _labourRepository = Get.find();
+  final LabourReviewWorkflowState state = LabourReviewWorkflowState();
+
+  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 _labourRepository.fetchLabourReviewStatusView(
+      state.requestId,
+      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<LabourReviewStatusRecords>? 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();
+  }
+}

+ 228 - 0
packages/cpt_uk/lib/modules/review/labour_review_workflow/labour_review_workflow_item.dart

@@ -0,0 +1,228 @@
+import 'package:cs_resources/constants/color_constants.dart';
+import 'package:domain/entity/response/labour_review_status_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 LabourReviewWorkFlowItem extends StatelessWidget {
+  final int index;
+  final LabourReviewStatusRecords item;
+
+  LabourReviewWorkFlowItem({
+    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: [
+          //Node
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Node:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              MyTextView(
+                item.nodeName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ),
+
+          // assigneeType
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Type:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //日期时间
+              MyTextView(
+                item.assigneeTypeShow ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // Designation
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Designation:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //人数
+              MyTextView(
+                item.designationShow ?? "-",
+                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: "Approved" == item.statusShow
+                    ? ColorConstants.textGreen05DC82
+                    : "Rejected" == item.statusShow
+                    ? ColorConstants.textRedFF6262
+                    : "Recall" == item.statusShow
+                    ? ColorConstants.textYellowFFBB1B
+                    : ColorConstants.textBlue06D9FF,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // Operator
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Operator:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //发布状态
+              MyTextView(
+                item.auditName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 操作时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Audit Time:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.auditTime ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+          // 创建时间
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Created 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),
+
+          // Remark
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Remark:".tr,
+                isFontRegular: true,
+                textColor: ColorConstants.textGrayAECAE5,
+                fontSize: 14,
+              ),
+
+              //时间
+              MyTextView(
+                item.auditMark ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Colors.white,
+                fontSize: 14,
+              ).expanded(),
+            ],
+          ).marginOnly(top: 15),
+
+        ],
+      ),
+    );
+  }
+}

+ 0 - 0
packages/cpt_uk/lib/modules/review/review_export.dart


+ 141 - 1
packages/cpt_uk/lib/router/uk_router.dart

@@ -1,12 +1,32 @@
+import 'package:cpt_uk/modules/attendance/device_list/device_list_page.dart';
+import 'package:cpt_uk/modules/attendance/e_attendance_list/e_attendance_list_page.dart';
+import 'package:cpt_uk/modules/attendance/security_registration/security_registration_page.dart';
+import 'package:cpt_uk/modules/job/job_applied_staff_detail/applied_staff_detail_page.dart';
+import 'package:cpt_uk/modules/job/job_applied_staff_reviews/applied_staff_reviews_page.dart';
+import 'package:cpt_uk/modules/job/job_applied_workflow/applied_workflow_page.dart';
 import 'package:cpt_uk/modules/job/job_category/job_category_page.dart';
+import 'package:cpt_uk/modules/job/job_list/job_list_page.dart';
+import 'package:cpt_uk/modules/job/job_list_detail/job_list_detail_page.dart';
+import 'package:cpt_uk/modules/job/labour_request_add/labour_request_add_page.dart';
+import 'package:cpt_uk/modules/job/labour_request_list/labour_request_list_page.dart';
+import 'package:cpt_uk/modules/job/labour_request_workflow/labour_request_workflow_page.dart';
+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/report_list/report_list_page.dart';
 import 'package:get/get.dart';
 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/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';
+import '../modules/review/labour_review_workflow/labour_request_workflow_page.dart';
+
 /// UK模块路由配置
 class UKPageRouter {
   static final routes = <GetPage<dynamic>>[
-
     //首页
     GetPage(
       name: RouterPath.UKMain,
@@ -19,5 +39,125 @@ class UKPageRouter {
       page: () => JobCategoryPage(),
     ),
 
+    //工作模板列表
+    GetPage(
+      name: RouterPath.UKTemplateList,
+      page: () => UKTemplateListPage(),
+    ),
+
+    //工作模板列表添加与编辑
+    GetPage(
+      name: RouterPath.UKTemplateAdd,
+      page: () => UKTemplateAddPage(),
+    ),
+
+    //工作用工请求列表
+    GetPage(
+      name: RouterPath.UKLabourList,
+      page: () => UKLabourRequestListPage(),
+    ),
+
+    //工作用工请求的添加与编辑
+    GetPage(
+      name: RouterPath.UKLabourAdd,
+      page: () => UKLabourRequestAddPage(),
+    ),
+
+    //工作用工请求的操作流
+    GetPage(
+      name: RouterPath.UKLabourWorlkflow,
+      page: () => UKLabourRequestWorkflowPage(),
+    ),
+
+    //工作列表
+    GetPage(
+      name: RouterPath.UKJobList,
+      page: () => UKJobListPage(),
+    ),
+
+    //工作列表详情
+    GetPage(
+      name: RouterPath.UKJobListDetail,
+      page: () => UKJobListDetailPage(),
+    ),
+
+    //工作列表已申请列表
+    GetPage(
+      name: RouterPath.UKJobApplied,
+      page: () => UKJobAppliedPage(),
+    ),
+
+    //工作列表已申请列表添加员工列表
+    GetPage(
+      name: RouterPath.UKJobAppliedEdit,
+      page: () => UKJobAppliedEditPage(),
+    ),
+
+    //工作列表已申请列表员工详情
+    GetPage(
+      name: RouterPath.UKJobAppliedStaffDetail,
+      page: () => UKAppliedStaffDetailPage(),
+    ),
+
+    //工作列表已申请列表员工评论列表
+    GetPage(
+      name: RouterPath.UKJobAppliedStaffReview,
+      page: () => UKAppliedStaffReviewsPage(),
+    ),
+
+    //工作列表已申请操作流
+    GetPage(
+      name: RouterPath.UKJobAppliedWorkflow,
+      page: () => UKAppliedWorkflowPage(),
+    ),
+
+    //工作列表用工请求审核
+    GetPage(
+      name: RouterPath.UKLabourReviewList,
+      page: () => UKLabourReviewPage(),
+    ),
+
+    //工作列表用工请求审核编辑
+    GetPage(
+      name: RouterPath.UKLabourReviewEdit,
+      page: () => UKLabourReviewEditPage(),
+    ),
+
+    //工作列表用工请求审核的操作流
+    GetPage(
+      name: RouterPath.UKLabourReviewWorkflow,
+      page: () => UKLabourReviewWorkflowPage(),
+    ),
+
+    //考勤的审核列表
+    GetPage(
+      name: RouterPath.UKAttendanceReviewList,
+      page: () => UKAttendanceReviewPage(),
+    ),
+
+    //设备列表
+    GetPage(
+      name: RouterPath.UKDeviceList,
+      page: () => UKDeviceListPage(),
+    ),
+
+    //电子考勤列表
+    GetPage(
+      name: RouterPath.UKAttendanceList,
+      page: () => UKEAttendanceListPage(),
+    ),
+
+    //门卫签到列表
+    GetPage(
+      name: RouterPath.UKSecurityRegistration,
+      page: () => UKSecurityRegistrationPage(),
+    ),
+
+    //报表
+    GetPage(
+      name: RouterPath.UKReportList,
+      page: () => UKReportListPage(),
+    ),
+
   ];
 }

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


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