Browse Source

布局基本完成

liukai 8 months ago
parent
commit
ba484c984b
58 changed files with 1851 additions and 389 deletions
  1. 32 59
      app/lib/main.dart
  2. 45 92
      app/lib/modules/splash/splash_controller.dart
  3. 20 6
      app/lib/modules/splash/splash_page.dart
  4. 0 9
      app/lib/router/page_router.dart
  5. 1 1
      melos.yaml
  6. 91 0
      packages/cpt_auth/lib/modules/login/login_controller.dart
  7. 242 0
      packages/cpt_auth/lib/modules/login/login_page.dart
  8. 24 0
      packages/cpt_auth/lib/modules/login/login_state.dart
  9. 0 0
      packages/cpt_auth/lib/modules/main/main_controller.dart
  10. 2 24
      app/lib/modules/main/main_page.dart
  11. 0 0
      packages/cpt_auth/lib/modules/main/main_state.dart
  12. 13 2
      packages/cpt_auth/lib/router/auth_service_impl.dart
  13. 13 3
      packages/cpt_auth/lib/router/page_router.dart
  14. 136 0
      packages/cpt_job/lib/modules/sign_in_sign_out/sign_in_sign_out_controller.dart
  15. 498 0
      packages/cpt_job/lib/modules/sign_in_sign_out/sign_in_sign_out_page.dart
  16. 17 0
      packages/cpt_job/lib/modules/sign_in_sign_out/sign_in_sign_out_state.dart
  17. 11 2
      packages/cpt_job/lib/router/job_service_impl.dart
  18. 7 0
      packages/cpt_job/lib/router/page_router.dart
  19. 10 20
      packages/cs_domain/lib/constants/api_constants.dart
  20. 68 0
      packages/cs_domain/lib/entity/response/attendance_entity.dart
  21. 25 0
      packages/cs_domain/lib/entity/response/check_success_entity.dart
  22. 0 24
      packages/cs_domain/lib/entity/response/user_login.dart
  23. 28 0
      packages/cs_domain/lib/entity/response/user_login_entity.dart
  24. 0 21
      packages/cs_domain/lib/entity/response/verify_code.dart
  25. 170 0
      packages/cs_domain/lib/generated/json/attendance_entity.g.dart
  26. 19 5
      packages/cs_domain/lib/generated/json/base/json_convert_content.dart
  27. 40 0
      packages/cs_domain/lib/generated/json/check_success_entity.g.dart
  28. 54 0
      packages/cs_domain/lib/generated/json/user_login_entity.g.dart
  29. 0 40
      packages/cs_domain/lib/generated/json/verify_code.g.dart
  30. 55 11
      packages/cs_domain/lib/repository/auth_repository.dart
  31. 95 0
      packages/cs_domain/lib/repository/job_repository.dart
  32. 3 0
      packages/cs_domain/pubspec.yaml
  33. 4 4
      packages/cs_initializer/lib/app_initializer.dart
  34. 4 0
      packages/cs_initializer/lib/global_services_injection.dart
  35. 1 0
      packages/cs_plugin_basic/lib/base/base_stateful_page.dart
  36. 0 2
      packages/cs_plugin_basic/lib/constants/app_constant.dart
  37. 1 0
      packages/cs_plugin_platform/lib/dio_export.dart
  38. 1 1
      packages/cs_plugin_platform/lib/engine/loading/loading_engine.dart
  39. 6 6
      packages/cs_plugin_platform/lib/http/dio/interceptor_network_debounce.dart
  40. 5 11
      packages/cs_plugin_platform/lib/http/http_provider.dart
  41. 0 11
      packages/cs_plugin_platform/lib/http/http_result.dart
  42. BIN
      packages/cs_resources/assets/cpt_auth/password_hide_icon.webp
  43. BIN
      packages/cs_resources/assets/cpt_auth/password_show_icon.webp
  44. BIN
      packages/cs_resources/assets/cpt_job/arraw_down_icon.webp
  45. BIN
      packages/cs_resources/assets/cpt_job/arraw_up_icon.webp
  46. BIN
      packages/cs_resources/assets/cpt_job/export_icon.webp
  47. BIN
      packages/cs_resources/assets/cpt_job/search_icon.webp
  48. BIN
      packages/cs_resources/assets/splashi_center_blue_logo.png
  49. BIN
      packages/cs_resources/assets/yy_business_top_logo.webp
  50. 7 1
      packages/cs_resources/lib/generated/assets.dart
  51. 31 1
      packages/cs_resources/lib/local/language/en_US.dart
  52. 30 1
      packages/cs_resources/lib/local/language/zh_CN.dart
  53. 2 0
      packages/cs_resources/pubspec.yaml
  54. 4 0
      packages/cs_router/lib/componentRouter/auth_service.dart
  55. 3 0
      packages/cs_router/lib/componentRouter/job_service.dart
  56. 4 14
      packages/cs_router/lib/path/router_path.dart
  57. 25 14
      packages/cs_widgets/lib/load_state_layout.dart
  58. 4 4
      packages/cs_widgets/lib/my_text_field.dart

+ 32 - 59
app/lib/main.dart

@@ -1,8 +1,8 @@
 import 'package:cpt_auth/router/auth_service_impl.dart';
 import 'package:cpt_auth/router/page_router.dart';
 import 'package:cpt_job/router/job_service_impl.dart';
+import 'package:cpt_job/router/page_router.dart';
 import 'package:cpt_labour/router/labour_service_impl.dart';
-import 'package:cpt_labour/router/page_router.dart';
 import 'package:cpt_report/router/report_service_impl.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
@@ -15,9 +15,6 @@ import 'package:router/componentRouter/auth_service.dart';
 import 'package:router/componentRouter/job_service.dart';
 import 'package:router/componentRouter/labour_service.dart';
 import 'package:router/componentRouter/report_service.dart';
-import 'package:shared/utils/log_utils.dart';
-import 'package:plugin_platform/engine/sp/sp_util.dart';
-import 'package:plugin_basic/constants/app_constant.dart';
 import 'package:cs_resources/local/theme/theme_config.dart';
 import 'package:cs_resources/local/language/translation_service.dart';
 import 'package:router/path/router_path.dart';
@@ -35,7 +32,7 @@ void main() {
   //运行App
   FlutterBugly.postCatchedException(() async {
     //交给初始化构造器去统一初始化
-    AppInitializer.initialize();
+    AppInitializer.initializeRunalone();
 
     //全局自定义单例服务的注入
     GlobalServicesInjection.init(additionalDependencies: () {
@@ -52,29 +49,33 @@ void main() {
 class MyApp extends StatelessWidget {
   MyApp({Key? key}) : super(key: key) {
     /// 全局设置 EasyRefresh 的样式
-    EasyRefresh.defaultHeaderBuilder = () =>
-        ClassicHeader(
-          dragText: '下拉刷新'.tr,
-          armedText: '释放刷新'.tr,
-          readyText: '刷新中...'.tr,
-          processingText: '刷新中...'.tr,
-          processedText: '成功'.tr,
-          noMoreText: '没有更多数据'.tr,
-          failedText: '失败'.tr,
-          messageText: '最近更新于 %T'.tr,
+    EasyRefresh.defaultHeaderBuilder = () => 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: Color(0XFFAECAE5), fontSize: 14),
+          messageStyle: const TextStyle(color: Color(0XFFAECAE5), fontSize: 12),
+          iconTheme: const IconThemeData(color: Color(0XFFAECAE5)),
+          backgroundColor: Colors.transparent,
         );
-    EasyRefresh.defaultFooterBuilder = () =>
-        ClassicFooter(
-          dragText: '上拉加载更多'.tr,
-          armedText: '释放刷新'.tr,
-          readyText: '加载中...'.tr,
-          processingText: '加载中...'.tr,
-          processedText: '成功'.tr,
-          noMoreText: '没有更多数据'.tr,
-          failedText: '成功'.tr,
+    EasyRefresh.defaultFooterBuilder = () => 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: Color(0XFFAECAE5), fontSize: 14),
+          backgroundColor: Colors.transparent,
         );
 
     /// SmartDialog 配置
@@ -99,37 +100,13 @@ class MyApp extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    int? darkModel = SPUtil.getInt(AppConstant.storagedarkmodel, defValue: 0);
-    if (GetPlatform.isAndroid) {
-      //根据SP存入的暗色模式,指定全局页面的状态栏,导航栏等设置
-      switch (darkModel) {
-        case 1:
-          Log.d("main.dart - 指定亮色模式");
-          SystemChrome.setSystemUIOverlayStyle(ThemeConfig.systemUiOverlayStyleLightThemeBlack);
-          break;
-        case 2:
-          Log.d("main.dart - 指定暗色模式");
-          SystemChrome.setSystemUIOverlayStyle(ThemeConfig.systemUiOverlayStyleDarkTheme);
-          break;
-        default:
-          Brightness currentBrightness = MediaQuery
-              .of(context)
-              .platformBrightness;
-          if (currentBrightness == Brightness.dark) {
-            Log.d("main.dart - 跟随系统模式-暗色模式");
-            SystemChrome.setSystemUIOverlayStyle(ThemeConfig.systemUiOverlayStyleDarkTheme);
-          } else {
-            Log.d("main.dart - 跟随系统模式-亮色模式");
-            SystemChrome.setSystemUIOverlayStyle(ThemeConfig.systemUiOverlayStyleLightThemeBlack);
-          }
-          break;
-      }
-    }
+    //设置全局的状态栏文本样式
+    SystemChrome.setSystemUIOverlayStyle(ThemeConfig.systemUiOverlayStyleLightThemeWhite);
 
     //路由管理,状态管理,依赖管理一切都始于GetMaterialApp
     return KeyboardVisibilityBuilder(builder: (context, isKeyboardVisible) {
       return KeyboardDismissOnTap(
-        dismissOnCapturedTaps: true,
+        dismissOnCapturedTaps: false,
         child: GetMaterialApp(
           //顶部是否展示Debug图标
           debugShowCheckedModeBanner: true,
@@ -137,22 +114,18 @@ class MyApp extends StatelessWidget {
           enableLog: true,
           //默认路由与路由表的加载
           initialRoute: RouterPath.SPLASH,
-          getPages: PageRouter.routes + BasicPageRouter.routes /*+ LabourPageRouter.routes + AuthPageRouter.routes +*/,
+          getPages: PageRouter.routes + BasicPageRouter.routes + AuthPageRouter.routes + JobPageRouter.routes,
           //对原生导航的兼容;SmartDialog路由配置生命周期处理
           navigatorObservers: [GetXRouterObserver(), FlutterSmartDialog.observer, routeObserver],
           //默认页面动画
           defaultTransition: Transition.rightToLeft,
           smartManagement: SmartManagement.keepFactory,
           //网页Title显示
-          title: 'FlutterRoom'.tr,
+          title: 'YYBusiness-ER',
           //样式相关
           theme: ThemeConfig.lightTheme,
           darkTheme: ThemeConfig.darkTheme,
-          themeMode: darkModel == 1
-              ? ThemeMode.light
-              : darkModel == 2
-              ? ThemeMode.dark
-              : ThemeMode.system,
+          themeMode: ThemeMode.light,
           //本地化相关
           locale: TranslationService.locale,
           fallbackLocale: TranslationService.fallbackLocale,
@@ -172,7 +145,7 @@ class MyApp extends StatelessWidget {
               return CustomToastWidget(msg: msg);
             },
             loadingBuilder: (String msg) {
-              return CustomLoadingWidget(msg: msg == 'loading...' ? '加载中...'.tr : msg);
+              return CustomLoadingWidget(msg: msg == 'loading...' ? 'Loading...'.tr : msg);
             },
             notifyStyle: FlutterSmartNotifyStyle(
               successBuilder: (String msg) => CustomSuccessWidget(msg: msg),

+ 45 - 92
app/lib/modules/splash/splash_controller.dart

@@ -1,117 +1,70 @@
 import 'package:flutter_bugly/flutter_bugly.dart';
-import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
 import 'package:get/get.dart';
 
 import 'package:app/jpush/jpush_receive.dart';
-import 'package:app/modules/main/main_page.dart';
 import 'package:initializer/app_initializer.dart';
 import 'package:plugin_basic/constants/app_constant.dart';
-import 'package:plugin_basic/service/config_services_injection.dart';
-import 'package:plugin_platform/engine/directory/directory_util.dart';
+import 'package:plugin_basic/service/user_service.dart';
 import 'package:plugin_platform/engine/sp/sp_util.dart';
+import 'package:router/componentRouter/component_router_service.dart';
 import 'package:shared/utils/device_utils.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
 
 class SplashController extends GetxController {
   @override
   void onReady() {
     super.onReady();
 
-    //是否是第一次进入App,需要同意协议弹窗,否则退出App
-    final isFirstOpen = SPUtil.getBool(AppConstant.storageFirstOpen) ?? false;
-    Log.d('isFirstOpen:$isFirstOpen');
-    if (!isFirstOpen) {
-      //展示协议弹窗
-      _showAgreementDialog();
-      if (DeviceUtils.isAndroid) {
-        // AppChannel.skipAndroidSplashScreen();
-      }
-    } else {
-      _gotoNextPage();
-    }
-  }
-
-  // 展示协议弹窗
-  void _showAgreementDialog() {
-    // SmartDialog.show(
-    //   usePenetrate: false,
-    //   clickMaskDismiss: false,
-    //   backDismiss: false,
-    //   keepSingle: true,
-    //   builder: (context) => PrivacyPolicyDialog(
-    //     confirmAction: () {
-    //       Log.d('同意协议了');
-    //       SPUtil.putBool(AppConstant.storageFirstOpen, true);
-    //       _gotoNextPage();
-    //     },
-    //     cancelAction: () {
-    //       //提示是否进入基础功能
-    //       _showSimpleModelDialog();
-    //     },
-    //   ),
-    // );
-
-    SPUtil.putBool(AppConstant.storageFirstOpen, true);
     _gotoNextPage();
   }
+}
 
-  // 展示基础功能弹窗
-  void _showSimpleModelDialog() {
-    // SmartDialog.show(
-    //   usePenetrate: false,
-    //   clickMaskDismiss: false,
-    //   backDismiss: false,
-    //   keepSingle: true,
-    //   builder: (context) => SimpleModelDialog(
-    //     confirmAction: () {
-    //       Log.d('同意协议了');
-    //       SpUtil.putBool(AppConstant.storageFirstOpen, true);
-    //       _gotoNextPage();
-    //     },
-    //     cancelAction: () {
-    //       //进入基础功能
-    //       Log.d('进入基础功能');
-    //     },
-    //   ),
-    // );
-  }
 
-  /// 同意了协议之后的初始化第三方与真正跳转逻辑判断
-  void _gotoNextPage() async {
+void _gotoNextPage() async {
+  await AppInitializer.delayInitialize(futureTasks: [
+    () async {
+      await FlutterBugly.init(
+        androidAppId: "12345678",
+        iOSAppId: "12345678",
+      );
+    },
+  ], normalTasks: [
+    () {
+      if (DeviceUtils.isIOS || DeviceUtils.isAndroid) {
+        jpush.init();
+      }
+    },
+  ]);
 
-    await AppInitializer.delayInitialize(futureTasks: [
-      () async {
-        await FlutterBugly.init(
-          androidAppId: "12345678",
-          iOSAppId: "12345678",
-        );
-      },
-    ], normalTasks: [
-      () {
-        if (DeviceUtils.isIOS || DeviceUtils.isAndroid) {
-          jpush.init();
-        }
-      },
-    ]);
+  // 先查询原生平台有没有保存需要跳转的子路由
+  // String routerName = await AppChannel.getNativeRouterName();
+  // Log.d('SplashController - 查询原生平台有没有保存需要跳转的子路由:$routerName');
 
-    // 先查询原生平台有没有保存需要跳转的子路由
-    // String routerName = await AppChannel.getNativeRouterName();
-    // Log.d('SplashController - 查询原生平台有没有保存需要跳转的子路由:$routerName');
+  String? token = SPUtil.getString(AppConstant.storageToken);
+  UserService.to.setToken(token);
 
-    MainPage.startWithPopAll();
+  if (UserService.to.isLogin) {
+    //去Attendance页面签到
+    Log.d("去Attendance页面签到");
+    ComponentRouterServices.jobService.startWithPopSignInSignOutPage();
+  } else {
+    //去登录页面
+    Log.d("去登录页面");
+    ComponentRouterServices.authService.startPopAllLoginPage();
+  }
 
-    // if (!Utils.isEmpty(routerName)) {
-    //   // 只跳转一次
-    //   Get.offAllNamed(routerName);
-    //   AppChannel.clearNativeRouterName();
-    // } else {
-    //   // 如果没有经历过GUIDE页面,进入GUIDE,否则进入首页
-    //     MainPage.startWithPopAll();
-    // }
+  // if (!Utils.isEmpty(routerName)) {
+  //   // 只跳转一次
+  //   Get.offAllNamed(routerName);
+  //   AppChannel.clearNativeRouterName();
+  // } else {
+  //   // 如果没有经历过GUIDE页面,进入GUIDE,否则进入首页
+  //     MainPage.startWithPopAll();
+  // }
 
-    //跳转页面之后清除 Android 的 SplashScreen 库
-    // if (Device.isAndroid) {
-    //   AppChannel.skipAndroidSplashScreen();
-    // }
-  }
+  //跳转页面之后清除 Android 的 SplashScreen 库
+  // if (Device.isAndroid) {
+  //   AppChannel.skipAndroidSplashScreen();
+  // }
 }

+ 20 - 6
app/lib/modules/splash/splash_page.dart

@@ -23,15 +23,29 @@ class SplashPage extends BaseStatelessPage<SplashController> {
   Widget buildWidget(BuildContext context) {
     SizeConfig().init(context);
 
-    return Container(
-        color: DarkThemeUtil.multiColors(ColorConstants.white, darkColor: ColorConstants.darkBlackBg),
+    return Scaffold(
+      body: Container(
+        decoration: const BoxDecoration(
+          gradient: LinearGradient(
+            colors: [
+              Color(0xFF091D44),
+              Color(0xFF245A8A),
+              Color(0xFF7F7CEC),
+            ],
+            begin: Alignment.topCenter,
+            end: Alignment.bottomCenter,
+          ),
+        ),
         child: const Center(
           child: MyAssetImage(
-            Assets.assetsSplashiCenterBlueLogo,
-            width: 144,
-            height: 144,
+            Assets.assetsYyBusinessTopLogo,
+            width: 164.5,
+            height: 101,
             fit: BoxFit.contain,
           ),
-        ));
+        ),
+      ),
+    );
   }
+
 }

+ 0 - 9
app/lib/router/page_router.dart

@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:router/path/router_path.dart';
 
-import '../modules/main/main_page.dart';
 import '../modules/splash/splash_page.dart';
 
 class PageRouter {
@@ -15,13 +14,5 @@ class PageRouter {
       page: () => SplashPage(),
     ),
 
-    //首页
-    GetPage(
-      name: RouterPath.MAIN,
-      page: () => MainPage(
-        key: const ValueKey(RouterPath.MAIN),
-      ),
-    ),
-
   ];
 }

+ 1 - 1
melos.yaml

@@ -1,4 +1,4 @@
-name: flutter_room
+name: YYHotel-Business-ER
 packages:
   - "app/**"
   - "packages/cs_domain/**"

+ 91 - 0
packages/cpt_auth/lib/modules/login/login_controller.dart

@@ -0,0 +1,91 @@
+import 'package:domain/entity/response/user_login_entity.dart';
+import 'package:domain/repository/auth_repository.dart';
+import 'package:get/get.dart';
+import 'package:plugin_basic/service/user_service.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:router/componentRouter/component_router_service.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+
+import 'login_state.dart';
+
+class LoginController extends GetxController with DioCancelableMixin {
+  final AuthRepository authRepository = Get.find();
+  final LoginState state = LoginState();
+
+  bool pwdVisibility = false; //是否明文展示密码
+  String? codeErrorText; //表单的错误信息展示
+  String? passwordErrorText;
+  String? code; //待提交的表单数据
+  String? password;
+
+  // 切换隐藏密码框
+  void switchPwdVisibility() {
+    pwdVisibility = !pwdVisibility;
+    update();
+  }
+
+  // 重置电话的错误文本
+  void resetCodeErrorText() {
+    codeErrorText = null;
+    update();
+  }
+
+  /// 执行账号密码的普通登录
+  void doInputLogin() {
+    codeErrorText = null;
+    passwordErrorText = null;
+    update();
+
+    var codeController = state.formData['code']!['controller'];
+    var passwordController = state.formData['password']!['controller'];
+
+    code = codeController.text;
+    password = passwordController.text;
+
+    Log.d('当前待提交的 code:$code password:$password');
+
+    if (Utils.isEmpty(code)) {
+      codeErrorText = "The login code cannot be empty!".tr;
+      update();
+    } else if (Utils.isEmpty(password)) {
+      passwordErrorText = "The password cannot be empty!".tr;
+      update();
+    } else {
+      //执行密码登录
+      _request2LoginPassword();
+    }
+  }
+
+  /// 请求接口执行登录
+  void _request2LoginPassword() async {
+    var result = await authRepository.userLogin(code, password, registerId: "", cancelToken: cancelToken);
+
+    //处理数据
+    if (result.isSuccess) {
+      //保存Token,去首页
+      _handleLoginSuccess(result.data!);
+    } else {
+      ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
+    }
+  }
+
+  /// 登录成功的统一处理 - 去首页
+  void _handleLoginSuccess(UserLoginEntity result) {
+    //保存Token
+    final token = result.token;
+    UserService.to.setToken(token);
+
+    //发送通知请求用户详情数据
+    // bus.emit(AppConstant.eventProfile2Refresh, true);
+
+    //使用SingleTask启动模式去首页
+    ComponentRouterServices.jobService.startWithPopSignInSignOutPage();
+  }
+
+  @override
+  void onReady() async {
+    super.onReady();
+  }
+}

+ 242 - 0
packages/cpt_auth/lib/modules/login/login_page.dart

@@ -0,0 +1,242 @@
+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_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/log_utils.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_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+import 'login_controller.dart';
+import 'login_state.dart';
+
+/*
+   App 登录页面
+ */
+class LoginPage extends BaseStatefulPage<LoginController> {
+  LoginPage({super.key});
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.AUTH_LOGIN, launchModel: LaunchModel.standard);
+  }
+
+  static void startWithPopAll() {
+    Get.offAllNamed(RouterPath.AUTH_LOGIN);
+  }
+
+  @override
+  State<LoginPage> createState() => _MainPageState();
+
+  @override
+  LoginController createRawController() {
+    return LoginController();
+  }
+}
+
+/**
+ * 页面
+ */
+class _MainPageState extends BaseState<LoginPage, LoginController> with StateLifecycle {
+  late LoginState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  void dispose() {
+    Get.delete<LoginController>();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    Log.d("LoginPage Lifecycle - build走了一遍");
+
+    return autoCtlGetBuilder(
+      builder: (controller) {
+        return Scaffold(
+          body: Container(
+            width: double.infinity,
+            height: double.infinity,
+            decoration: const BoxDecoration(
+              gradient: LinearGradient(
+                colors: [
+                  Color(0xFF091D44),
+                  Color(0xFF245A8A),
+                  Color(0xFF7F7CEC),
+                ],
+                begin: Alignment.topCenter,
+                end: Alignment.bottomCenter,
+              ),
+            ),
+            child: SingleChildScrollView(
+              scrollDirection: Axis.vertical,
+              physics: const BouncingScrollPhysics(),
+              child: Column(
+                mainAxisSize: MainAxisSize.max,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  //顶部Logo
+                  MyAssetImage(
+                    Assets.assetsYyBusinessTopLogo,
+                    width: 164.5,
+                    height: 101,
+                  ).marginOnly(top: 75),
+
+                  //中间的输入框布局
+                  Container(
+                    width: double.infinity,
+                    margin: EdgeInsets.symmetric(vertical: 45, horizontal: 15),
+                    padding: EdgeInsets.symmetric(vertical: 33, horizontal: 20),
+                    decoration: BoxDecoration(
+                      color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+                      borderRadius: BorderRadius.circular(5.0), // 设置圆角
+                    ),
+                    child: Center(
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          //登录文本
+                          MyTextView(
+                            "Login Code".tr,
+                            isFontMedium: true,
+                            fontSize: 17,
+                            textColor: ColorConstants.white,
+                          ),
+
+                          // 登录表单 - 账号
+                          _buildInputLayout(
+                            "code",
+                            textInputAction: TextInputAction.next,
+                            errorText: controller.codeErrorText,
+                            onSubmit: (formKey, value) {
+                              state.formData[formKey]!['focusNode'].unfocus();
+                              FocusScope.of(context).requestFocus(state.formData['password']!['focusNode']);
+                            },
+                          ),
+
+                          //密码文本
+                          MyTextView(
+                            "Password".tr,
+                            isFontMedium: true,
+                            fontSize: 17,
+                            textColor: ColorConstants.white,
+                            marginTop: 18,
+                          ),
+
+                          // 登录表单 - 密码
+                          _buildInputLayout(
+                            "password",
+                            obscureText: !controller.pwdVisibility,
+                            errorText: controller.passwordErrorText,
+                            showRightIcon: true,
+                            rightWidget: IconButton(
+                              highlightColor: Colors.transparent,
+                              splashColor: Colors.transparent,
+                              icon: controller.pwdVisibility
+                                  ? const MyAssetImage(
+                                      Assets.cptAuthPasswordShowIcon,
+                                      width: 21,
+                                      height: 21,
+                                      color: ColorConstants.white,
+                                    )
+                                  : const MyAssetImage(
+                                      Assets.cptAuthPasswordHideIcon,
+                                      width: 21,
+                                      height: 21,
+                                      color: ColorConstants.white,
+                                    ),
+                              onPressed: () {
+                                controller.switchPwdVisibility();
+                              },
+                            ),
+                            onSubmit: (formKey, value) {
+                              state.formData[formKey]!['focusNode'].unfocus();
+                              controller.doInputLogin();
+                            },
+                          ),
+
+                          MyButton(
+                            type: ClickType.throttle,
+                            milliseconds: 500,
+                            onPressed: () {
+                              FocusScope.of(context).unfocus();
+                              controller.doInputLogin();
+                            },
+                            text: "Log in".tr,
+                            textColor: ColorConstants.white,
+                            fontSize: 16,
+                            radius: 22.5,
+                            backgroundColor: hexToColor("#FFBB1B"),
+                            fontWeight: FontWeight.w500,
+                          ).marginOnly(top: 31)
+                        ],
+                      ),
+                    ), // 传递子部件
+                  ),
+                ],
+              ),
+            ),
+          ),
+        );
+      },
+    );
+  }
+
+  /// 输入框 账号与密码
+  _buildInputLayout(
+    String key, {
+    double marginTop = 0,
+    bool? showRightIcon = false, //是否展示右侧的布局
+    Widget? rightWidget, //右侧的布局
+    TextInputType textInputType = TextInputType.text,
+    String? errorText,
+    bool obscureText = false,
+    TextInputAction textInputAction = TextInputAction.done,
+    Function? onSubmit,
+  }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: hexToColor("#AECAE5"),
+          fontSize: 15.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        showDivider: true,
+        dividerColor: hexToColor("#7BABC8"),
+        style: TextStyle(
+          color: ColorConstants.white,
+          fontSize: 15.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        height: 35,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: ColorConstants.white,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+}

+ 24 - 0
packages/cpt_auth/lib/modules/login/login_state.dart

@@ -0,0 +1,24 @@
+
+
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class LoginState {
+  //表单的校验与数据
+  Map<String, Map<String, dynamic>> formData = {
+    'code': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Please enter your login code'.tr,
+      'obsecure': false,
+    },
+    'password': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Please enter your password'.tr,
+      'obsecure': true,
+    },
+  };
+}

app/lib/modules/main/main_controller.dart → packages/cpt_auth/lib/modules/main/main_controller.dart


+ 2 - 24
app/lib/modules/main/main_page.dart

@@ -2,18 +2,14 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
 import 'package:get/get.dart';
-import 'package:app/modules/main/main_state.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/constants/app_constant.dart';
 import 'package:plugin_basic/utils/ext_get_nav.dart';
 import 'package:plugin_platform/engine/media/image_picker_utils.dart';
-import 'package:plugin_platform/engine/sp/sp_util.dart';
 import 'package:cs_resources/constants/color_constants.dart';
 import 'package:cs_resources/local/theme/theme_config.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
-import 'package:router/componentRouter/component_router_service.dart';
 import 'package:router/path/router_path.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/double_tap_back_exit_app.dart';
@@ -21,6 +17,7 @@ import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
 import 'main_controller.dart';
+import 'main_state.dart';
 
 /*
    App首页页面
@@ -86,25 +83,6 @@ class _MainPageState extends BaseState<MainPage, MainController> with StateLifec
     Log.d("MainPage Lifecycle - onStart");
   }
 
-  //黑暗模式的切换监听
-  @override
-  void didChangePlatformBrightness() {
-    int? darkModel = SPUtil.getInt(AppConstant.storagedarkmodel, defValue: 0);
-    //当跟随系统的时候,监听系统当前的黑暗模式
-    if (darkModel == 0) {
-      //延时拿到当前的值,否则可能获取的值不对
-      Future.delayed(const Duration(milliseconds: 250), () {
-        Brightness currentBrightness = MediaQuery.of(context).platformBrightness;
-        //切换全部的Theme并刷新
-        if (currentBrightness == Brightness.dark) {
-          ThemeConfig.changeThemeDark();
-        } else {
-          ThemeConfig.changeThemeLight();
-        }
-      });
-    }
-  }
-
   @override
   Widget build(BuildContext context) {
     Log.d("MainPage Lifecycle - build走了一遍");
@@ -112,7 +90,7 @@ class _MainPageState extends BaseState<MainPage, MainController> with StateLifec
     //双击退出应用
     return DoubleTapBackExitApp(
       child: AnnotatedRegion<SystemUiOverlayStyle>(
-        value: Get.isDarkMode ? ThemeConfig.systemUiOverlayStyleDarkTheme : ThemeConfig.systemUiOverlayStyleLightThemeWhite,
+        value: ThemeConfig.systemUiOverlayStyleLightThemeWhite,
         child: autoCtlGetBuilder(builder: (controller) {
           return Scaffold(
             appBar: MyAppBar.appBar(context, "首页".tr, backCallback: () {

app/lib/modules/main/main_state.dart → packages/cpt_auth/lib/modules/main/main_state.dart


+ 13 - 2
packages/cpt_auth/lib/router/auth_service_impl.dart

@@ -1,3 +1,4 @@
+import 'package:cpt_auth/modules/login/login_page.dart';
 import 'package:plugin_basic/basic_export.dart';
 import 'package:router/componentRouter/auth_service.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -8,13 +9,23 @@ class AuthServiceImpl extends GetxService implements AuthService {
   void onInit() {
     super.onInit();
     //初始化资源
-    Log.d("ProfileServiceImpl 初始化资源");
+    Log.d("AuthServiceImpl 初始化资源");
   }
 
   @override
   void onClose() {
     super.onClose();
     //销毁资源
-    Log.d("ProfileServiceImpl 销毁资源");
+    Log.d("AuthServiceImpl 销毁资源");
+  }
+
+  @override
+  void startLoginPage() {
+    LoginPage.startInstance();
+  }
+
+  @override
+  void startPopAllLoginPage() {
+    LoginPage.startWithPopAll();
   }
 }

+ 13 - 3
packages/cpt_auth/lib/router/page_router.dart

@@ -1,12 +1,22 @@
-
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:router/path/router_path.dart';
 
-class AuthPageRouter {
+import '../modules/login/login_page.dart';
+import '../modules/main/main_page.dart';
 
+class AuthPageRouter {
   static final routes = [
+    //首页
+    GetPage(
+      name: RouterPath.MAIN,
+      page: () => MainPage(),
+    ),
 
-
+    //登录
+    GetPage(
+      name: RouterPath.AUTH_LOGIN,
+      page: () => LoginPage(),
+    ),
   ];
 }

+ 136 - 0
packages/cpt_job/lib/modules/sign_in_sign_out/sign_in_sign_out_controller.dart

@@ -0,0 +1,136 @@
+import 'package:domain/entity/response/attendance_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/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 'sign_in_sign_out_state.dart';
+
+class SignInSignOutController extends GetxController with DioCancelableMixin {
+  final JobRepository jobRepository = Get.find();
+  final SignInSignOutState state = SignInSignOutState();
+
+  var _needShowPlaceholder = true;
+
+  //页面的列表数据
+  List<AttendanceList> datas = [];
+  String? keyword;
+
+  //页面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);
+    }
+
+    final String? token = UserService.to.token;
+    //获取到数据
+    var result = await jobRepository.fetchAttendanceList(token, keyword, "2023-07-01", "2025-07-02", cancelToken: cancelToken);
+
+    //处理数据
+    if (result.isSuccess) {
+      handleList(result.data?.list);
+      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) {
+      //有数据,判断是刷新还是加载更多的数据
+      datas.clear();
+      datas.addAll(list);
+
+      //更新展示的状态
+      if (loadingState != LoadState.State_Success){
+        changeLoadingState(LoadState.State_Success);
+      }
+
+    } else {
+      //展示无数据的布局
+      datas.clear();
+      changeLoadingState(LoadState.State_Empty);
+    }
+  }
+
+  //执行搜索
+  void doSearch() {
+    var keywordController = state.formData['keyword']!['controller'];
+    keyword = keywordController.text;
+    fetchAttendanceList();
+  }
+
+  @override
+  void onReady() async {
+    super.onReady();
+    fetchAttendanceList();
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+    datas.clear();
+  }
+
+  /// 用户签到
+  void userSignIn(AttendanceList item) {
+    ToastEngine.show("用户签到");
+  }
+
+  /// 用户签出
+  void userSignOut(AttendanceList item) {
+    ToastEngine.show("用户签出");
+  }
+
+  /// 重置筛选条件
+  void resetFiltering() {
+    ToastEngine.show("重置筛选条件");
+  }
+
+  /// 筛选开始日期
+  void pickerStartDate() {
+    ToastEngine.show("筛选开始日期");
+  }
+
+  /// 筛选结束日期
+  void pickerEndDate() {
+    ToastEngine.show("筛选结束日期");
+  }
+
+}

+ 498 - 0
packages/cpt_job/lib/modules/sign_in_sign_out/sign_in_sign_out_page.dart

@@ -0,0 +1,498 @@
+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:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:router/path/router_path.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/screen_util.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.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/widget_export.dart';
+import 'sign_in_sign_out_controller.dart';
+import 'sign_in_sign_out_state.dart';
+
+/*
+   工作的签到页面
+ */
+class SignInSignOutPage extends BaseStatefulPage<SignInSignOutController> {
+  SignInSignOutPage({super.key});
+
+  //启动当前页面
+  static void startInstance() {
+    return Get.start(RouterPath.JOB_SIGN_IN_SIGN_OUT, launchModel: LaunchModel.singleTask);
+  }
+
+  static void startWithPop() {
+    Get.startWithPop(RouterPath.JOB_SIGN_IN_SIGN_OUT);
+  }
+
+  @override
+  State<SignInSignOutPage> createState() => _SignInSignOutPageState();
+
+  @override
+  SignInSignOutController createRawController() {
+    return SignInSignOutController();
+  }
+}
+
+class _SignInSignOutPageState extends BaseState<SignInSignOutPage, SignInSignOutController> with StateLifecycle {
+  late SignInSignOutState state;
+
+  @override
+  void initState() {
+    super.initState();
+    state = controller.state;
+  }
+
+  @override
+  void dispose() {
+    Get.delete<SignInSignOutController>();
+    super.dispose();
+  }
+
+  @override
+  void onResume() {
+    super.onResume();
+    Log.d("SignInSignOutPage Lifecycle - onResume");
+  }
+
+  @override
+  void onPause() {
+    super.onPause();
+    Log.d("SignInSignOutPage Lifecycle - onPause");
+  }
+
+  @override
+  void onStop() {
+    super.onStop();
+    Log.d("SignInSignOutPage Lifecycle - onStop");
+  }
+
+  @override
+  void onStart() {
+    super.onStart();
+    Log.d("SignInSignOutPage Lifecycle - onStart");
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    Log.d("SignInSignOutPage Lifecycle - build走了一遍");
+
+    return autoCtlGetBuilder(
+      builder: (controller) {
+        return Scaffold(
+          body: Container(
+            width: double.infinity,
+            height: double.infinity,
+            decoration: const BoxDecoration(
+              gradient: LinearGradient(
+                colors: [
+                  Color(0xFF091D44),
+                  Color(0xFF245A8A),
+                  Color(0xFF7F7CEC),
+                ],
+                begin: Alignment.topCenter,
+                end: Alignment.bottomCenter,
+              ),
+            ),
+            child: Column(
+              children: [
+                //顶部的搜索标题布局
+                _buildSearchTitleBar(),
+
+                Container(color: Color(0XFF415B7C), height: 0.5, margin: EdgeInsets.only(top: 12)),
+
+                _buildFilterDateWidget(),
+
+                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 _buildAttendanceItem(controller, index, () {});
+                        },
+                        childCount: controller.datas.length,
+                      ))
+                    ],
+                  ),
+                ).expanded(),
+              ],
+            ),
+          ),
+        );
+      },
+    );
+  }
+
+  /// 顶部的搜索栏布局
+  Widget _buildSearchTitleBar() {
+    return Row(
+      mainAxisSize: MainAxisSize.max,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        Container(
+          height: 35,
+          padding: EdgeInsets.only(left: 15, right: 11),
+          margin: EdgeInsets.only(left: 15, right: 10),
+          decoration: BoxDecoration(
+            color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+            borderRadius: BorderRadius.circular(17.25), // 设置圆角
+          ),
+          child: Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //输入框
+              IgnoreKeyboardDismiss(
+                child: TextField(
+                  cursorColor: ColorConstants.white,
+                  cursorWidth: 1.5,
+                  autofocus: false,
+                  maxLines: 1,
+                  minLines: 1,
+                  // 是否自动获取焦点
+                  focusNode: state.formData['keyword']!['focusNode'],
+                  // 焦点控制
+                  controller: state.formData['keyword']!['controller'],
+                  // 与输入框交互控制器
+                  //装饰
+                  decoration: InputDecoration(
+                    isDense: true,
+                    //清除垂直方向的填充
+                    isCollapsed: true,
+                    //让文字垂直居中
+                    border: InputBorder.none,
+                    hintText: state.formData['keyword']!['hintText'],
+                    hintStyle: TextStyle(
+                      color: hexToColor("#AECAE5"),
+                      fontSize: 15.0,
+                      fontWeight: FontWeight.w400,
+                    ),
+                  ),
+                  style: TextStyle(
+                    color: ColorConstants.white,
+                    fontSize: 15.0,
+                    fontWeight: FontWeight.w400,
+                  ),
+                  // 键盘动作右下角图标
+                  textInputAction: TextInputAction.search,
+                  textAlignVertical: TextAlignVertical.center,
+                  onSubmitted: (value) {
+                    controller.doSearch();
+                  }, //输入框完成触发
+                ),
+              ).expanded(),
+
+              //搜索图标
+              MyAssetImage(Assets.cptJobSearchIcon, width: 15, height: 15).marginOnly(left: 10).onTap(() {
+                controller.doSearch();
+              }),
+            ],
+          ),
+        ).expanded(),
+        MyButton(
+          onPressed: () {
+            controller.resetFiltering();
+          },
+          text: "Reset".tr,
+          textColor: ColorConstants.white,
+          backgroundColor: hexToColor("#2BA9F9", opacity: 0.5),
+          radius: 17.25,
+          minWidth: 60,
+          minHeight: 35,
+        )
+      ],
+    ).marginOnly(top: ScreenUtil.getStatusBarH(context) + 5, right: 12);
+  }
+
+  /// 时间筛选布局
+  Widget _buildFilterDateWidget() {
+    return Container(
+      width: double.infinity,
+      height: 36,
+      margin: EdgeInsets.only(left: 15, right: 15, top: 15, bottom: 10),
+      decoration: BoxDecoration(
+        color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度
+        borderRadius: BorderRadius.circular(17.25), // 设置圆角
+      ),
+      child: Row(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        children: [
+          MyTextView(
+            "2024-6-27",
+            fontSize: 16,
+            textAlign: TextAlign.center,
+            isFontRegular: true,
+            textColor: ColorConstants.white,
+            onClick: (){
+              controller.pickerStartDate();
+            },
+          ).expanded(),
+
+          Container(color: Color(0XFF52739C),width: 0.5,height: 21.5,),
+
+          MyTextView(
+            "2024-6-27",
+            fontSize: 16,
+            textAlign: TextAlign.center,
+            isFontRegular: true,
+            textColor: ColorConstants.white,
+            onClick: (){
+              controller.pickerEndDate();
+            },
+          ).expanded(),
+        ],
+      ),
+    );
+  }
+
+  /// Item列表
+  Widget _buildAttendanceItem(SignInSignOutController controller, int index, void Function() callback) {
+    final item = controller.datas[index];
+
+    return Container(
+      padding: EdgeInsets.only(left: 23, right: 12),
+      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(
+        children: [
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                "Name:".tr,
+                isFontRegular: true,
+                textColor: Color(0XFFAECAE5),
+                fontSize: 14,
+              ),
+
+              //姓名
+              MyTextView(
+                item.staffName ?? "-",
+                marginLeft: 5,
+                isFontRegular: true,
+                textColor: Color(0XFFAECAE5),
+                fontSize: 14,
+              ).expanded(),
+
+              MyAssetImage(item.isExpended ? Assets.cptJobArrawUpIcon : Assets.cptJobArrawDownIcon, width: 15, height: 7),
+            ],
+          ).paddingOnly(top: 19, bottom: 19),
+
+          //显示隐藏的布局
+          Visibility(
+            visible: item.isExpended,
+            child: Column(
+              children: [
+                //工作日期
+                Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    MyTextView(
+                      "Job Date:".tr,
+                      isFontRegular: true,
+                      textColor: Color(0XFFAECAE5),
+                      fontSize: 14,
+                    ),
+
+                    //姓名
+                    MyTextView(
+                      item.jobDate ?? "-",
+                      marginLeft: 5,
+                      isFontRegular: true,
+                      textColor: Color(0XFFAECAE5),
+                      fontSize: 14,
+                    ).expanded(),
+                  ],
+                ),
+
+                //开始时间
+                Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    MyTextView(
+                      "Start Time:",
+                      isFontRegular: true,
+                      textColor: Color(0XFFAECAE5),
+                      fontSize: 14,
+                    ),
+
+                    //姓名
+                    MyTextView(
+                      item.startTime ?? "-",
+                      marginLeft: 5,
+                      isFontRegular: true,
+                      textColor: Color(0XFFAECAE5),
+                      fontSize: 14,
+                    ).expanded(),
+                  ],
+                ).marginOnly(top: 16),
+
+                //结束时间
+                Row(
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    MyTextView(
+                      "End Time:".tr,
+                      isFontRegular: true,
+                      textColor: Color(0XFFAECAE5),
+                      fontSize: 14,
+                    ),
+
+                    //姓名
+                    MyTextView(
+                      item.endTime ?? "-",
+                      marginLeft: 5,
+                      isFontRegular: true,
+                      textColor: Color(0XFFAECAE5),
+                      fontSize: 14,
+                    ).expanded(),
+                  ],
+                ).marginOnly(top: 16),
+
+                //签到的控件
+                Row(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    //开始签到
+                    Column(
+                      mainAxisAlignment: MainAxisAlignment.start,
+                      crossAxisAlignment: CrossAxisAlignment.center,
+                      children: [
+                        Container(
+                          width: 90,
+                          height: 35,
+                          margin: EdgeInsets.only(top: 18),
+                          decoration: BoxDecoration(
+                            color: Utils.isEmpty(item.checkInImg) ? Color(0xFF56AAFF) : ColorConstants.white,
+                            borderRadius: BorderRadius.circular(17.25), // 设置圆角
+                          ),
+                          child: Stack(
+                            alignment: Alignment.center,
+                            children: [
+                              Visibility(
+                                visible: Utils.isEmpty(item.checkInImg),
+                                child: MyTextView(
+                                  "Check In".tr,
+                                  isFontMedium: true,
+                                  textColor: ColorConstants.white,
+                                  fontSize: 14,
+                                ),
+                              ),
+                              Visibility(
+                                visible: !Utils.isEmpty(item.checkInImg),
+                                child: MyLoadImage(item.checkInImg, width: 71.5, height: 25, fit: BoxFit.cover),
+                              ),
+                            ],
+                          ).onTap(() {
+                            if (Utils.isEmpty(item.checkInImg)) {
+                              controller.userSignIn(item);
+                            }
+                          }),
+                        ),
+                        Visibility(
+                          visible: !Utils.isEmpty(item.checkInTime),
+                          child: MyTextView(
+                            marginTop: 9,
+                            item.checkInTime ?? "-",
+                            textColor: ColorConstants.white,
+                            fontSize: 14,
+                            isFontRegular: true,
+                          ),
+                        ),
+                      ],
+                    ),
+
+                    //结束签到
+                    Column(
+                      mainAxisAlignment: MainAxisAlignment.start,
+                      crossAxisAlignment: CrossAxisAlignment.center,
+                      children: [
+                        Container(
+                          width: 90,
+                          height: 35,
+                          margin: EdgeInsets.only(top: 18),
+                          decoration: BoxDecoration(
+                            color: Utils.isEmpty(item.checkOutImg) ? Color(0xFF56AAFF) : ColorConstants.white,
+                            borderRadius: BorderRadius.circular(17.25), // 设置圆角
+                          ),
+                          child: Stack(
+                            alignment: Alignment.center,
+                            children: [
+                              Visibility(
+                                visible: Utils.isEmpty(item.checkOutImg),
+                                child: MyTextView(
+                                  "Check Out".tr,
+                                  isFontMedium: true,
+                                  textColor: ColorConstants.white,
+                                  fontSize: 14,
+                                ),
+                              ),
+                              Visibility(
+                                visible: !Utils.isEmpty(item.checkOutImg),
+                                child: MyLoadImage(item.checkOutImg, width: 71.5, height: 25, fit: BoxFit.cover),
+                              ),
+                            ],
+                          ).onTap(() {
+                            if (Utils.isEmpty(item.checkOutImg)) {
+                              controller.userSignOut(item);
+                            }
+                          }),
+                        ),
+                        Visibility(
+                          visible: !Utils.isEmpty(item.checkOutTime),
+                          child: MyTextView(
+                            marginTop: 9,
+                            item.checkOutTime ?? "-",
+                            textColor: ColorConstants.white,
+                            fontSize: 14,
+                            isFontRegular: true,
+                          ),
+                        ),
+                      ],
+                    ).marginOnly(left: 10),
+                  ],
+                ),
+
+                SizedBox(height: 18),
+              ],
+            ),
+          ),
+        ],
+      ),
+    ).onTap(() {
+      //切换展开收起
+      item.isExpended = !item.isExpended;
+      controller.update();
+    });
+  }
+}

+ 17 - 0
packages/cpt_job/lib/modules/sign_in_sign_out/sign_in_sign_out_state.dart

@@ -0,0 +1,17 @@
+
+
+import 'package:flutter/material.dart';
+import 'package:plugin_basic/basic_export.dart';
+
+class SignInSignOutState {
+  //表单的校验与数据
+  Map<String, Map<String, dynamic>> formData = {
+    'keyword': {
+      'value': '',
+      'controller': TextEditingController(),
+      'focusNode': FocusNode(),
+      'hintText': 'Name/Mobile'.tr,
+      'obsecure': false,
+    },
+  };
+}

+ 11 - 2
packages/cpt_job/lib/router/job_service_impl.dart

@@ -2,19 +2,28 @@ import 'package:plugin_basic/basic_export.dart';
 import 'package:router/componentRouter/job_service.dart';
 import 'package:shared/utils/log_utils.dart';
 
+import '../modules/sign_in_sign_out/sign_in_sign_out_page.dart';
+
 class JobServiceImpl extends GetxService implements JobService {
 
   @override
   void onInit() {
     super.onInit();
     //初始化资源
-    Log.d("ProfileServiceImpl 初始化资源");
+    Log.d("JobServiceImpl 初始化资源");
   }
 
   @override
   void onClose() {
     super.onClose();
     //销毁资源
-    Log.d("ProfileServiceImpl 销毁资源");
+    Log.d("JobServiceImpl 销毁资源");
   }
+
+  // 启动签到签出页面
+  @override
+  void startWithPopSignInSignOutPage() {
+    SignInSignOutPage.startWithPop();
+  }
+
 }

+ 7 - 0
packages/cpt_job/lib/router/page_router.dart

@@ -3,10 +3,17 @@ import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:router/path/router_path.dart';
 
+import '../modules/sign_in_sign_out/sign_in_sign_out_page.dart';
+
 class JobPageRouter {
 
   static final routes = [
 
+    //签到签出
+    GetPage(
+      name: RouterPath.JOB_SIGN_IN_SIGN_OUT,
+      page: () => SignInSignOutPage(),
+    ),
 
   ];
 }

+ 10 - 20
packages/cs_domain/lib/constants/api_constants.dart

@@ -2,34 +2,24 @@
 
 class ApiConstants {
   //基础域名
-  static const baseUrl = 'http://111.229.126.27:88'; //测试环境
+  static const baseUrl = 'http://vietnam-dev.casualabour.com'; //测试环境
 
   //网络请求加密 Key
   static const encrypterKey = 'xxxx'; //加密Key
 
-  //用户协议网页
-  static const userAgreementUrl = 'http://xxxxxx'; //测试环境
-
-  //隐私协议网页
-  static const privacyPolicyUrl = 'http://xxxxxx'; //测试环境
-
-  //帮助中心网页
-  static const helpCenterUrl = 'http://xxxxxx'; //测试环境
-
-  //营业执照
-  static const businessLicenseUrl = 'http://xxxxxx'; //测试环境
-
-  //人力资源许可证
-  static const humanResourcesUrl = 'http://xxxxxx'; //测试环境
+// =========================== 用户相关 ↓=========================================
 
-  //分享工作的链接
-  static const partTimeJobDetailShare = 'http://xxxxxx'; //测试环境
+  // 用户登录
+  static const apiUserLogin = "/index.php/api/v1/sign/login";
 
+  // 用户登出系统
+  static const apiUserLogout = "/index.php/api/v1/sign/logout";
 
-// =========================== 用户相关 ↓=========================================
+  // 用户签到签出列表
+  static const apiSignApplied = "/index.php/api/v1/sign/applied";
 
-  //验证码图片
-  static const apiVerifyCodeImage = "/index.php/api/v1/common/captcha";
+  // 用户签到签出
+  static const apiSignInOut = "/index.php/api/v1/sign/applied/clock";
 
   //获取用户的详情信息
   static const apiUserProfile = "/index.php/api/v1/xx/xx/xx";

+ 68 - 0
packages/cs_domain/lib/entity/response/attendance_entity.dart

@@ -0,0 +1,68 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/attendance_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/attendance_entity.g.dart';
+
+@JsonSerializable()
+class AttendanceEntity {
+	int? count = 0;
+	int? curPage = 0;
+	int? pageSize = 0;
+	int? countPage = 0;
+	List<AttendanceList>? list = [];
+
+	AttendanceEntity();
+
+	factory AttendanceEntity.fromJson(Map<String, dynamic> json) => $AttendanceEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $AttendanceEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class AttendanceList {
+	@JSONField(name: "applied_id")
+	int? appliedId = 0;
+	@JSONField(name: "staff_id")
+	int? staffId = 0;
+	@JSONField(name: "staff_name")
+	String? staffName = '';
+	@JSONField(name: "job_date")
+	String? jobDate = '';
+	@JSONField(name: "start_time")
+	String? startTime = '';
+	@JSONField(name: "end_time")
+	String? endTime = '';
+	@JSONField(name: "check_in_id")
+	int? checkInId = 0;
+	@JSONField(name: "check_in_time")
+	String? checkInTime = '';
+	@JSONField(name: "check_in_img")
+	String? checkInImg = '';
+	@JSONField(name: "check_out_id")
+	int? checkOutId = 0;
+	@JSONField(name: "check_out_time")
+	String? checkOutTime = '';
+	@JSONField(name: "check_out_img")
+	String? checkOutImg = '';
+	int? status = 0;
+	@JSONField(name: "status_show")
+	String? statusShow = '';
+
+	bool isExpended = false;  //是否展开了
+
+	AttendanceList();
+
+	factory AttendanceList.fromJson(Map<String, dynamic> json) => $AttendanceListFromJson(json);
+
+	Map<String, dynamic> toJson() => $AttendanceListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

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

@@ -0,0 +1,25 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/check_success_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/check_success_entity.g.dart';
+
+@JsonSerializable()
+class CheckSuccessEntity {
+	@JSONField(name: "applied_id")
+	int? appliedId = 0;
+	@JSONField(name: "check_img")
+	String? checkImg = '';
+	@JSONField(name: "check_time")
+	String? checkTime = '';
+
+	CheckSuccessEntity();
+
+	factory CheckSuccessEntity.fromJson(Map<String, dynamic> json) => $CheckSuccessEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $CheckSuccessEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 0 - 24
packages/cs_domain/lib/entity/response/user_login.dart

@@ -1,24 +0,0 @@
-class UserLogin {
-  int? memberId;
-  String? token;
-  String? signature;
-  String? identifier;
-
-  UserLogin({this.memberId, this.token, this.signature, this.identifier});
-
-  UserLogin.fromJson(Map<String, dynamic> json) {
-    memberId = json['member_id'];
-    token = json['token'];
-    signature = json['signature'];
-    identifier = json['identifier'];
-  }
-
-  Map<String, dynamic> toJson() {
-    final Map<String, dynamic> data = new Map<String, dynamic>();
-    data['member_id'] = this.memberId;
-    data['token'] = this.token;
-    data['signature'] = this.signature;
-    data['identifier'] = this.identifier;
-    return data;
-  }
-}

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

@@ -0,0 +1,28 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/user_login_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/user_login_entity.g.dart';
+
+@JsonSerializable()
+class UserLoginEntity {
+	@JSONField(name: "auth_id")
+	int? authId = 0;
+	@JSONField(name: "company_id")
+	int? companyId = 0;
+	@JSONField(name: "e_admin_id")
+	int? eAdminId = 0;
+	String? token = '';
+	@JSONField(name: "register_id")
+	dynamic registerId;
+
+	UserLoginEntity();
+
+	factory UserLoginEntity.fromJson(Map<String, dynamic> json) => $UserLoginEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $UserLoginEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 0 - 21
packages/cs_domain/lib/entity/response/verify_code.dart

@@ -1,21 +0,0 @@
-import 'package:domain/generated/json/base/json_field.dart';
-import 'package:domain/generated/json/verify_code.g.dart';
-import 'dart:convert';
-
-@JsonSerializable()
-class VerifyCode {
-	bool? sensitive;
-	String? key;
-	String? img;
-
-	VerifyCode();
-
-	factory VerifyCode.fromJson(Map<String, dynamic> json) => $VerifyCodeFromJson(json);
-
-	Map<String, dynamic> toJson() => $VerifyCodeToJson(this);
-
-	@override
-	String toString() {
-		return jsonEncode(this);
-	}
-}

+ 170 - 0
packages/cs_domain/lib/generated/json/attendance_entity.g.dart

@@ -0,0 +1,170 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/response/attendance_entity.dart';
+
+AttendanceEntity $AttendanceEntityFromJson(Map<String, dynamic> json) {
+  final AttendanceEntity attendanceEntity = AttendanceEntity();
+  final int? count = jsonConvert.convert<int>(json['count']);
+  if (count != null) {
+    attendanceEntity.count = count;
+  }
+  final int? curPage = jsonConvert.convert<int>(json['curPage']);
+  if (curPage != null) {
+    attendanceEntity.curPage = curPage;
+  }
+  final int? pageSize = jsonConvert.convert<int>(json['pageSize']);
+  if (pageSize != null) {
+    attendanceEntity.pageSize = pageSize;
+  }
+  final int? countPage = jsonConvert.convert<int>(json['countPage']);
+  if (countPage != null) {
+    attendanceEntity.countPage = countPage;
+  }
+  final List<AttendanceList>? list = (json['list'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<AttendanceList>(e) as AttendanceList).toList();
+  if (list != null) {
+    attendanceEntity.list = list;
+  }
+  return attendanceEntity;
+}
+
+Map<String, dynamic> $AttendanceEntityToJson(AttendanceEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['count'] = entity.count;
+  data['curPage'] = entity.curPage;
+  data['pageSize'] = entity.pageSize;
+  data['countPage'] = entity.countPage;
+  data['list'] = entity.list?.map((v) => v.toJson()).toList();
+  return data;
+}
+
+extension AttendanceEntityExtension on AttendanceEntity {
+  AttendanceEntity copyWith({
+    int? count,
+    int? curPage,
+    int? pageSize,
+    int? countPage,
+    List<AttendanceList>? list,
+  }) {
+    return AttendanceEntity()
+      ..count = count ?? this.count
+      ..curPage = curPage ?? this.curPage
+      ..pageSize = pageSize ?? this.pageSize
+      ..countPage = countPage ?? this.countPage
+      ..list = list ?? this.list;
+  }
+}
+
+AttendanceList $AttendanceListFromJson(Map<String, dynamic> json) {
+  final AttendanceList attendanceList = AttendanceList();
+  final int? appliedId = jsonConvert.convert<int>(json['applied_id']);
+  if (appliedId != null) {
+    attendanceList.appliedId = appliedId;
+  }
+  final int? staffId = jsonConvert.convert<int>(json['staff_id']);
+  if (staffId != null) {
+    attendanceList.staffId = staffId;
+  }
+  final String? staffName = jsonConvert.convert<String>(json['staff_name']);
+  if (staffName != null) {
+    attendanceList.staffName = staffName;
+  }
+  final String? jobDate = jsonConvert.convert<String>(json['job_date']);
+  if (jobDate != null) {
+    attendanceList.jobDate = jobDate;
+  }
+  final String? startTime = jsonConvert.convert<String>(json['start_time']);
+  if (startTime != null) {
+    attendanceList.startTime = startTime;
+  }
+  final String? endTime = jsonConvert.convert<String>(json['end_time']);
+  if (endTime != null) {
+    attendanceList.endTime = endTime;
+  }
+  final int? checkInId = jsonConvert.convert<int>(json['check_in_id']);
+  if (checkInId != null) {
+    attendanceList.checkInId = checkInId;
+  }
+  final String? checkInTime = jsonConvert.convert<String>(json['check_in_time']);
+  if (checkInTime != null) {
+    attendanceList.checkInTime = checkInTime;
+  }
+  final String? checkInImg = jsonConvert.convert<String>(json['check_in_img']);
+  if (checkInImg != null) {
+    attendanceList.checkInImg = checkInImg;
+  }
+  final int? checkOutId = jsonConvert.convert<int>(json['check_out_id']);
+  if (checkOutId != null) {
+    attendanceList.checkOutId = checkOutId;
+  }
+  final String? checkOutTime = jsonConvert.convert<String>(json['check_out_time']);
+  if (checkOutTime != null) {
+    attendanceList.checkOutTime = checkOutTime;
+  }
+  final String? checkOutImg = jsonConvert.convert<String>(json['check_out_img']);
+  if (checkOutImg != null) {
+    attendanceList.checkOutImg = checkOutImg;
+  }
+  final int? status = jsonConvert.convert<int>(json['status']);
+  if (status != null) {
+    attendanceList.status = status;
+  }
+  final String? statusShow = jsonConvert.convert<String>(json['status_show']);
+  if (statusShow != null) {
+    attendanceList.statusShow = statusShow;
+  }
+  return attendanceList;
+}
+
+Map<String, dynamic> $AttendanceListToJson(AttendanceList entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['applied_id'] = entity.appliedId;
+  data['staff_id'] = entity.staffId;
+  data['staff_name'] = entity.staffName;
+  data['job_date'] = entity.jobDate;
+  data['start_time'] = entity.startTime;
+  data['end_time'] = entity.endTime;
+  data['check_in_id'] = entity.checkInId;
+  data['check_in_time'] = entity.checkInTime;
+  data['check_in_img'] = entity.checkInImg;
+  data['check_out_id'] = entity.checkOutId;
+  data['check_out_time'] = entity.checkOutTime;
+  data['check_out_img'] = entity.checkOutImg;
+  data['status'] = entity.status;
+  data['status_show'] = entity.statusShow;
+  return data;
+}
+
+extension AttendanceListExtension on AttendanceList {
+  AttendanceList copyWith({
+    int? appliedId,
+    int? staffId,
+    String? staffName,
+    String? jobDate,
+    String? startTime,
+    String? endTime,
+    int? checkInId,
+    String? checkInTime,
+    String? checkInImg,
+    int? checkOutId,
+    String? checkOutTime,
+    String? checkOutImg,
+    int? status,
+    String? statusShow,
+  }) {
+    return AttendanceList()
+      ..appliedId = appliedId ?? this.appliedId
+      ..staffId = staffId ?? this.staffId
+      ..staffName = staffName ?? this.staffName
+      ..jobDate = jobDate ?? this.jobDate
+      ..startTime = startTime ?? this.startTime
+      ..endTime = endTime ?? this.endTime
+      ..checkInId = checkInId ?? this.checkInId
+      ..checkInTime = checkInTime ?? this.checkInTime
+      ..checkInImg = checkInImg ?? this.checkInImg
+      ..checkOutId = checkOutId ?? this.checkOutId
+      ..checkOutTime = checkOutTime ?? this.checkOutTime
+      ..checkOutImg = checkOutImg ?? this.checkOutImg
+      ..status = status ?? this.status
+      ..statusShow = statusShow ?? this.statusShow;
+  }
+}

+ 19 - 5
packages/cs_domain/lib/generated/json/base/json_convert_content.dart

@@ -4,9 +4,11 @@
 
 // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
 import 'package:flutter/material.dart' show debugPrint;
+import 'package:domain/entity/response/attendance_entity.dart';
+import 'package:domain/entity/response/check_success_entity.dart';
 import 'package:domain/entity/response/id_name_entity.dart';
+import 'package:domain/entity/response/user_login_entity.dart';
 import 'package:domain/entity/response/user_profile.dart';
-import 'package:domain/entity/response/verify_code.dart';
 import 'package:domain/entity/server_time.dart';
 
 JsonConvert jsonConvert = JsonConvert();
@@ -135,15 +137,24 @@ class JsonConvert {
 
   //list is returned by type
   static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
+    if (<AttendanceEntity>[] is M) {
+      return data.map<AttendanceEntity>((Map<String, dynamic> e) => AttendanceEntity.fromJson(e)).toList() as M;
+    }
+    if (<AttendanceList>[] is M) {
+      return data.map<AttendanceList>((Map<String, dynamic> e) => AttendanceList.fromJson(e)).toList() as M;
+    }
+    if (<CheckSuccessEntity>[] is M) {
+      return data.map<CheckSuccessEntity>((Map<String, dynamic> e) => CheckSuccessEntity.fromJson(e)).toList() as M;
+    }
     if (<IdNameEntity>[] is M) {
       return data.map<IdNameEntity>((Map<String, dynamic> e) => IdNameEntity.fromJson(e)).toList() as M;
     }
+    if (<UserLoginEntity>[] is M) {
+      return data.map<UserLoginEntity>((Map<String, dynamic> e) => UserLoginEntity.fromJson(e)).toList() as M;
+    }
     if (<UserProfile>[] is M) {
       return data.map<UserProfile>((Map<String, dynamic> e) => UserProfile.fromJson(e)).toList() as M;
     }
-    if (<VerifyCode>[] is M) {
-      return data.map<VerifyCode>((Map<String, dynamic> e) => VerifyCode.fromJson(e)).toList() as M;
-    }
     if (<ServerTime>[] is M) {
       return data.map<ServerTime>((Map<String, dynamic> e) => ServerTime.fromJson(e)).toList() as M;
     }
@@ -167,9 +178,12 @@ class JsonConvert {
 
 class JsonConvertClassCollection {
   Map<String, JsonConvertFunction> convertFuncMap = {
+    (AttendanceEntity).toString(): AttendanceEntity.fromJson,
+    (AttendanceList).toString(): AttendanceList.fromJson,
+    (CheckSuccessEntity).toString(): CheckSuccessEntity.fromJson,
     (IdNameEntity).toString(): IdNameEntity.fromJson,
+    (UserLoginEntity).toString(): UserLoginEntity.fromJson,
     (UserProfile).toString(): UserProfile.fromJson,
-    (VerifyCode).toString(): VerifyCode.fromJson,
     (ServerTime).toString(): ServerTime.fromJson,
   };
 

+ 40 - 0
packages/cs_domain/lib/generated/json/check_success_entity.g.dart

@@ -0,0 +1,40 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/response/check_success_entity.dart';
+
+CheckSuccessEntity $CheckSuccessEntityFromJson(Map<String, dynamic> json) {
+  final CheckSuccessEntity checkSuccessEntity = CheckSuccessEntity();
+  final int? appliedId = jsonConvert.convert<int>(json['applied_id']);
+  if (appliedId != null) {
+    checkSuccessEntity.appliedId = appliedId;
+  }
+  final String? checkImg = jsonConvert.convert<String>(json['check_img']);
+  if (checkImg != null) {
+    checkSuccessEntity.checkImg = checkImg;
+  }
+  final String? checkTime = jsonConvert.convert<String>(json['check_time']);
+  if (checkTime != null) {
+    checkSuccessEntity.checkTime = checkTime;
+  }
+  return checkSuccessEntity;
+}
+
+Map<String, dynamic> $CheckSuccessEntityToJson(CheckSuccessEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['applied_id'] = entity.appliedId;
+  data['check_img'] = entity.checkImg;
+  data['check_time'] = entity.checkTime;
+  return data;
+}
+
+extension CheckSuccessEntityExtension on CheckSuccessEntity {
+  CheckSuccessEntity copyWith({
+    int? appliedId,
+    String? checkImg,
+    String? checkTime,
+  }) {
+    return CheckSuccessEntity()
+      ..appliedId = appliedId ?? this.appliedId
+      ..checkImg = checkImg ?? this.checkImg
+      ..checkTime = checkTime ?? this.checkTime;
+  }
+}

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

@@ -0,0 +1,54 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/response/user_login_entity.dart';
+
+UserLoginEntity $UserLoginEntityFromJson(Map<String, dynamic> json) {
+  final UserLoginEntity userLoginEntity = UserLoginEntity();
+  final int? authId = jsonConvert.convert<int>(json['auth_id']);
+  if (authId != null) {
+    userLoginEntity.authId = authId;
+  }
+  final int? companyId = jsonConvert.convert<int>(json['company_id']);
+  if (companyId != null) {
+    userLoginEntity.companyId = companyId;
+  }
+  final int? eAdminId = jsonConvert.convert<int>(json['e_admin_id']);
+  if (eAdminId != null) {
+    userLoginEntity.eAdminId = eAdminId;
+  }
+  final String? token = jsonConvert.convert<String>(json['token']);
+  if (token != null) {
+    userLoginEntity.token = token;
+  }
+  final dynamic registerId = json['register_id'];
+  if (registerId != null) {
+    userLoginEntity.registerId = registerId;
+  }
+  return userLoginEntity;
+}
+
+Map<String, dynamic> $UserLoginEntityToJson(UserLoginEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['auth_id'] = entity.authId;
+  data['company_id'] = entity.companyId;
+  data['e_admin_id'] = entity.eAdminId;
+  data['token'] = entity.token;
+  data['register_id'] = entity.registerId;
+  return data;
+}
+
+extension UserLoginEntityExtension on UserLoginEntity {
+  UserLoginEntity copyWith({
+    int? authId,
+    int? companyId,
+    int? eAdminId,
+    String? token,
+    dynamic registerId,
+  }) {
+    return UserLoginEntity()
+      ..authId = authId ?? this.authId
+      ..companyId = companyId ?? this.companyId
+      ..eAdminId = eAdminId ?? this.eAdminId
+      ..token = token ?? this.token
+      ..registerId = registerId ?? this.registerId;
+  }
+}

+ 0 - 40
packages/cs_domain/lib/generated/json/verify_code.g.dart

@@ -1,40 +0,0 @@
-import 'package:domain/generated/json/base/json_convert_content.dart';
-import 'package:domain/entity/response/verify_code.dart';
-
-VerifyCode $VerifyCodeFromJson(Map<String, dynamic> json) {
-  final VerifyCode verifyCode = VerifyCode();
-  final bool? sensitive = jsonConvert.convert<bool>(json['sensitive']);
-  if (sensitive != null) {
-    verifyCode.sensitive = sensitive;
-  }
-  final String? key = jsonConvert.convert<String>(json['key']);
-  if (key != null) {
-    verifyCode.key = key;
-  }
-  final String? img = jsonConvert.convert<String>(json['img']);
-  if (img != null) {
-    verifyCode.img = img;
-  }
-  return verifyCode;
-}
-
-Map<String, dynamic> $VerifyCodeToJson(VerifyCode entity) {
-  final Map<String, dynamic> data = <String, dynamic>{};
-  data['sensitive'] = entity.sensitive;
-  data['key'] = entity.key;
-  data['img'] = entity.img;
-  return data;
-}
-
-extension VerifyCodeExtension on VerifyCode {
-  VerifyCode copyWith({
-    bool? sensitive,
-    String? key,
-    String? img,
-  }) {
-    return VerifyCode()
-      ..sensitive = sensitive ?? this.sensitive
-      ..key = key ?? this.key
-      ..img = img ?? this.img;
-  }
-}

+ 55 - 11
packages/cs_domain/lib/repository/auth_repository.dart

@@ -1,12 +1,11 @@
-
 import 'package:get/get.dart';
+import 'package:plugin_platform/dio_export.dart';
 import 'package:plugin_platform/http/http_provider.dart';
 import 'package:plugin_platform/http/http_result.dart';
 
 import '../constants/api_constants.dart';
+import '../entity/response/user_login_entity.dart';
 import '../entity/response/user_profile.dart';
-import '../entity/response/verify_code.dart';
-
 
 /// 用户相关
 class AuthRepository extends GetxService {
@@ -14,21 +13,66 @@ class AuthRepository extends GetxService {
 
   AuthRepository({required this.httpProvider});
 
-  /// 获取发送验证码的图片,用于发送短信
-  Future<HttpResult<VerifyCode>> getVerifyCodeImage() async {
-    //Get请求
-    final result = await httpProvider.requestNetResult(ApiConstants.apiVerifyCodeImage);
+  /// 用户登录
+  Future<HttpResult<UserLoginEntity>> userLogin(
+    String? code,
+    String? password, {
+    String? registerId,
+    CancelToken? cancelToken,
+  }) async {
+    //Post请求
+    Map<String, String> params = {};
+    params['code'] = code ?? "";
+    params['password'] = password ?? "";
+
+    if (registerId != null && registerId.isNotEmpty) {
+      params['register_id'] = registerId;
+    }
+
+    final result = await httpProvider.requestNetResult(
+      method: HttpMethod.POST,
+      ApiConstants.apiUserLogin,
+      params: params,
+      networkDebounce: true,
+      isShowLoadingDialog: true,
+      cancelToken: cancelToken,
+    );
 
     //根据返回的结果,封装原始数据为Bean/Entity对象
     if (result.isSuccess) {
       final json = result.getDataJson();
-      var data = VerifyCode.fromJson(json!);
-      //重新赋值data或list
-      return result.convert<VerifyCode>(data: data);
+      var data = UserLoginEntity.fromJson(json!);
+      //重新赋值data
+      return result.convert<UserLoginEntity>(data: data);
     }
-    return result.convert<VerifyCode>();
+    return result.convert<UserLoginEntity>();
   }
 
+  /// 退出登录
+  Future<HttpResult> userLogout(
+    String? token, {
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['token'] = token ?? "";
+
+    //POST请求
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiUserLogout,
+      method: HttpMethod.POST,
+      params: params,
+      networkDebounce: true,
+      isShowLoadingDialog: true,
+      cancelToken: cancelToken,
+    );
+
+    //根据返回的结果,封装原始数据为Bean/Entity对象
+    if (result.isSuccess) {
+      //重新赋值data或list
+      return result.convert();
+    }
+    return result.convert();
+  }
 
   /// 获取用户详情数据
   Future<HttpResult<UserProfile>> fetchUserProfile() async {

+ 95 - 0
packages/cs_domain/lib/repository/job_repository.dart

@@ -0,0 +1,95 @@
+import 'package:get/get.dart';
+import 'package:plugin_platform/dio_export.dart';
+import 'package:plugin_platform/http/http_provider.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:shared/utils/util.dart';
+
+import '../constants/api_constants.dart';
+import '../entity/response/attendance_entity.dart';
+import '../entity/response/check_success_entity.dart';
+
+/// 工作相关
+class JobRepository extends GetxService {
+  HttpProvider httpProvider;
+
+  JobRepository({required this.httpProvider});
+
+  /// 获取当前酒店的考勤成员列表
+  Future<HttpResult<AttendanceEntity>> fetchAttendanceList(
+    String? token,
+    String? keyword,
+    String? startDate,
+    String? endDate, {
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params["token"] = token ?? "";
+    params["cur_page"] = "1";
+    params["page_size"] = "9999";
+
+    if (!Utils.isEmpty(keyword)) {
+      params["keyword"] = keyword!;
+    }
+    if (!Utils.isEmpty(startDate)) {
+      params["start_date"] = startDate!;
+    }
+    if (!Utils.isEmpty(endDate)) {
+      params["end_date"] = endDate!;
+    }
+
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiSignApplied,
+      params: params,
+    );
+
+    //根据返回的结果,封装原始数据为Bean/Entity对象
+    if (result.isSuccess) {
+      //重新赋值data或list
+      final json = result.getDataJson();
+      var data = AttendanceEntity.fromJson(json!);
+      //重新赋值data或list
+      return result.convert<AttendanceEntity>(data: data);
+    }
+    return result.convert();
+  }
+
+  /// 用户上传考勤
+  Future<HttpResult<CheckSuccessEntity>> submitCheckInOut(
+    String? token,
+    String? appliedId,
+    String? path, {
+    bool isCheckIn = false,
+    CancelToken? cancelToken,
+  }) async {
+    //Post请求
+    Map<String, String> params = {};
+    params['token'] = token ?? "";
+    params['applied_id'] = appliedId ?? "";
+    params['check_type'] = isCheckIn ? "1" : "2";
+
+    Map<String, String> paths = {};
+    if (!Utils.isEmpty(path)) {
+      paths["capture"] = path!;
+    }
+
+    final result = await httpProvider.requestNetResult(
+      method: HttpMethod.POST,
+      ApiConstants.apiSignInOut,
+      params: params,
+      paths: paths,
+      networkDebounce: true,
+      isShowLoadingDialog: true,
+      cancelToken: cancelToken,
+    );
+
+    //根据返回的结果,封装原始数据为Bean/Entity对象
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = CheckSuccessEntity.fromJson(json!);
+      //重新赋值data
+      return result.convert<CheckSuccessEntity>(data: data);
+    }
+    return result.convert<CheckSuccessEntity>();
+  }
+
+}

+ 3 - 0
packages/cs_domain/pubspec.yaml

@@ -20,6 +20,9 @@ dependencies:
   # json 序列化和反序列化
   json_annotation: ^4.8.0
 
+  shared:
+    path: ../cs_shared
+
   plugin_platform:
     path: ../cs_plugin_platform
 

+ 4 - 4
packages/cs_initializer/lib/app_initializer.dart

@@ -31,8 +31,8 @@ class AppInitializer {
     //指定页面的展示方向为哪一种,常用的三种屏幕方向,支持横屏
     SystemChrome.setPreferredOrientations([
       DeviceOrientation.portraitUp,
-      DeviceOrientation.landscapeLeft,
-      DeviceOrientation.landscapeRight,
+      // DeviceOrientation.landscapeLeft,
+      // DeviceOrientation.landscapeRight,
     ]);
 
     //处理显示区域
@@ -103,8 +103,8 @@ class AppInitializer {
     //指定页面的展示方向为哪一种,常用的三种屏幕方向
     SystemChrome.setPreferredOrientations([
       DeviceOrientation.portraitUp,
-      DeviceOrientation.landscapeLeft,
-      DeviceOrientation.landscapeRight,
+      // DeviceOrientation.landscapeLeft,
+      // DeviceOrientation.landscapeRight,
     ]);
 
     //处理显示区域

+ 4 - 0
packages/cs_initializer/lib/global_services_injection.dart

@@ -1,5 +1,6 @@
 import 'package:domain/constants/api_constants.dart';
 import 'package:domain/repository/auth_repository.dart';
+import 'package:domain/repository/job_repository.dart';
 import 'package:plugin_basic/basic_export.dart';
 import 'package:plugin_basic/service/user_service.dart';
 import 'package:plugin_platform/http/http_provider.dart';
@@ -25,6 +26,9 @@ class GlobalServicesInjection {
     //全局单例的用户数据仓库
     Get.put(AuthRepository(httpProvider: Get.find()));
 
+    //其他的数据仓库注入
+    Get.lazyPut(() => JobRepository(httpProvider: Get.find()));
+
     // 用户信息服务(用户信息相关业务类)
     Get.put(UserService(Get.find()));
 

+ 1 - 0
packages/cs_plugin_basic/lib/base/base_stateful_page.dart

@@ -22,6 +22,7 @@ abstract class BaseStatefulPage<C extends GetxController> extends StatefulWidget
     try {
       _controller = GetInstance().put<C>(createRawController(), tag: key?.toString());
     } catch (e) {
+      e.printError();
       _controller = null;
     }
   }

+ 0 - 2
packages/cs_plugin_basic/lib/constants/app_constant.dart

@@ -11,11 +11,9 @@ class AppConstant {
   static const String locale = 'locale';
 
   // 本地SP存储key
-  static const storageFirstOpen = 'first_open'; //第一次打开-需要协议弹窗
   static const storageGuideFirst = 'guide_first'; //是否经历过Guide
   static const storageToken = 'token'; //用户的Token
   static const searchJobHistoryRecord = 'search_job_history_record'; //兼职工作搜索记录
-  static const storagedarkmodel = 'storage_dark_model'; //应用设置的暗黑模式
   static const storageNotificationEnable = 'storage_notification_enable'; //应用设置的推送是否开启
   static const storageDeviceUUID = 'storage_device_uuid'; //设备的UUID
 

+ 1 - 0
packages/cs_plugin_platform/lib/dio_export.dart

@@ -0,0 +1 @@
+export 'package:dio/dio.dart';

+ 1 - 1
packages/cs_plugin_platform/lib/engine/loading/loading_engine.dart

@@ -5,7 +5,7 @@ class LoadingEngine {
 
   //展示加载中弹窗
   static void show({String? message}) {
-    SmartDialog.showLoading(msg: message ?? "加载中...".tr);
+    SmartDialog.showLoading(msg: message ?? "Loading...".tr);
   }
 
   // 隐藏

+ 6 - 6
packages/cs_plugin_platform/lib/http/dio/interceptor_network_debounce.dart

@@ -1,10 +1,10 @@
 import 'package:dio/dio.dart';
-import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+
+import 'package:plugin_platform/engine/loading/loading_engine.dart';
 import 'package:shared/utils/log_utils.dart';
 
 import '../../core/platform_config.dart';
 
-
 /*
  * Dio 网络请求去重的拦截器
  */
@@ -27,7 +27,7 @@ class NetworkDebounceInterceptor extends Interceptor {
       _handleNetworkDebounce(url, method, parameters, cancelToken, options, handler, isShowLoadingDialog);
     } else {
       if (isShowLoadingDialog) {
-        SmartDialog.showLoading();
+        LoadingEngine.show();
       }
       // 处理去重
       super.onRequest(options, handler);
@@ -96,7 +96,7 @@ class NetworkDebounceInterceptor extends Interceptor {
     if (params == null) {
       //无需处理去重
       if (isShowLoadingDialog) {
-        SmartDialog.showLoading();
+        LoadingEngine.show();
       }
       handler.next(options);
     } else {
@@ -114,7 +114,7 @@ class NetworkDebounceInterceptor extends Interceptor {
         _urlParamsMap[urlkey] = curSerializedParams;
         //正常请求
         if (isShowLoadingDialog) {
-          SmartDialog.showLoading();
+          LoadingEngine.show();
         }
         handler.next(options);
       } else {
@@ -193,7 +193,7 @@ class NetworkDebounceInterceptor extends Interceptor {
     }
 
     if (isShowLoadingDialog) {
-      SmartDialog.dismiss(status: SmartStatus.loading);
+      LoadingEngine.dismiss();
     }
   }
 

+ 5 - 11
packages/cs_plugin_platform/lib/http/http_provider.dart

@@ -129,8 +129,8 @@ class HttpProvider {
         if (jsonMap.containsKey('code')) {
           int code = jsonMap['code'];
 
-          // 如果有 code,并且 code = 0 说明成功
-          if (code == 0) {
+          // 如果有 code,并且 code = 200 说明成功
+          if (code == 200) {
             if (jsonMap['data'] is List<dynamic>) {
               //成功->返回数组
               return HttpResult(
@@ -149,12 +149,9 @@ class HttpProvider {
               );
             }
 
-            //如果code !=0 ,下面是错误的情况判断
+            //如果code != 200 ,下面是错误的情况判断
           } else {
-            if (jsonMap.containsKey('errors')) {
-              //拿到错误信息对象
-              return HttpResult(isSuccess: false, code: code, errorObj: jsonMap['errors'], errorMsg: jsonMap['message']);
-            } else if (jsonMap.containsKey('msg')) {
+            if (jsonMap.containsKey('msg')) {
               //如果有msg字符串优先返回msg字符串
               return HttpResult(isSuccess: false, code: code, errorMsg: jsonMap['msg']);
             } else {
@@ -164,10 +161,7 @@ class HttpProvider {
           }
         } else {
           //没有code,说明有错误信息,判断错误信息
-          if (jsonMap.containsKey('errors')) {
-            //拿到错误信息对象
-            return HttpResult(isSuccess: false, errorObj: jsonMap['errors'], errorMsg: jsonMap['message']);
-          } else if (jsonMap.containsKey('msg')) {
+          if (jsonMap.containsKey('msg')) {
             //如果有msg字符串优先返回msg字符串
             return HttpResult(isSuccess: false, errorMsg: jsonMap['msg']);
           } else {

+ 0 - 11
packages/cs_plugin_platform/lib/http/http_result.dart

@@ -3,7 +3,6 @@ class HttpResult<T> {
       {required this.isSuccess,
       dynamic dataJson,
       List<dynamic>? listJson,
-      this.errorObj,
       this.code = -1,
       this.msg,
       this.errorMsg}) {
@@ -27,8 +26,6 @@ class HttpResult<T> {
   //成功之后的消息
   String? msg;
 
-  //失败的数据,失败对象
-  dynamic errorObj;
   //失败的数据,失败字符串
   String? errorMsg;
 
@@ -40,13 +37,6 @@ class HttpResult<T> {
     return null;
   }
 
-  /// 以Json对象的方式获取Error对象
-  Map<String, dynamic>? getErrorJson() {
-    if (errorObj is Map<String, dynamic>) {
-      return errorObj as Map<String, dynamic>;
-    }
-    return null;
-  }
 
   /// 以原始对象的方式获取,可以获取到String,Int,bool等基本类型
   dynamic getDataDynamic() {
@@ -76,7 +66,6 @@ class HttpResult<T> {
         listJson: this._listJson,
         code: this.code,
         msg: this.msg,
-        errorObj: this.errorObj,
         errorMsg: this.errorMsg);
 
     result.data = data;

BIN
packages/cs_resources/assets/cpt_auth/password_hide_icon.webp


BIN
packages/cs_resources/assets/cpt_auth/password_show_icon.webp


BIN
packages/cs_resources/assets/cpt_job/arraw_down_icon.webp


BIN
packages/cs_resources/assets/cpt_job/arraw_up_icon.webp


BIN
packages/cs_resources/assets/cpt_job/export_icon.webp


BIN
packages/cs_resources/assets/cpt_job/search_icon.webp


BIN
packages/cs_resources/assets/splashi_center_blue_logo.png


BIN
packages/cs_resources/assets/yy_business_top_logo.webp


+ 7 - 1
packages/cs_resources/lib/generated/assets.dart

@@ -2,7 +2,7 @@
 class Assets {
   Assets._();
 
-  static const String assetsSplashiCenterBlueLogo = 'assets/splashi_center_blue_logo.png';
+  static const String assetsYyBusinessTopLogo = 'assets/yy_business_top_logo.webp';
   static const String baseLibBlackBack = 'assets/base_lib/black_back.webp';
   static const String baseLibDialogBlueDeleteIcon = 'assets/base_lib/dialog_blue_delete_icon.webp';
   static const String baseLibDialogDeleteIcon = 'assets/base_lib/dialog_delete_icon.webp';
@@ -10,5 +10,11 @@ class Assets {
   static const String baseLibWhiteBack = 'assets/base_lib/white_back.webp';
   static const String baseServicePageLoadError = 'assets/base_service/page_load_error.webp';
   static const String baseServicePageNoData = 'assets/base_service/page_no_data.webp';
+  static const String cptAuthPasswordHideIcon = 'assets/cpt_auth/password_hide_icon.webp';
+  static const String cptAuthPasswordShowIcon = 'assets/cpt_auth/password_show_icon.webp';
+  static const String cptJobArrawDownIcon = 'assets/cpt_job/arraw_down_icon.webp';
+  static const String cptJobArrawUpIcon = 'assets/cpt_job/arraw_up_icon.webp';
+  static const String cptJobExportIcon = 'assets/cpt_job/export_icon.webp';
+  static const String cptJobSearchIcon = 'assets/cpt_job/search_icon.webp';
 
 }

+ 31 - 1
packages/cs_resources/lib/local/language/en_US.dart

@@ -1,4 +1,34 @@
 const Map<String, String> en_US = {
-  'app_name': 'Flutter Room',
+  'app_name': 'YYBusiness',
+  'Please enter your login code': 'Please enter your login code',
+  'Please enter your password': 'Please enter your password',
+  'The login code cannot be empty!': 'The login code cannot be empty!',
+  'The password cannot be empty!': 'The password cannot be empty!',
+  'Log in': 'Log in',
+  'Login Code': 'Login Code',
+  'Password': 'Password',
+  'Name/Mobile': 'Name/Mobile',
+  'Check In': 'Check In',
+  'Check Out': 'Check Out',
+  'Job Date:': 'Job Date:',
+  'Start Time:': 'Start Time:',
+  'End Time:': 'End Time:',
+  'Name:': 'Name:',
+  'Reset': 'Reset',
+
+
+  'Pull to refresh': 'Pull to refresh',
+  'Release ready': 'Release ready',
+  'Refreshing...': 'Refreshing...',
+  'Succeeded': 'Succeeded',
+  'No more': 'No more',
+  'Failed': 'Failed',
+  'Last updated at %T': 'Last updated at %T',
+  'Pull to load': 'Pull to load',
+
+  'Network Load Error': 'Network Load Error',
+  'Loading...': 'Loading...',
+  'Data loading failed! Please refresh and try again': 'Data loading failed! Please refresh and try again',
+  'There is currently no content available': 'There is currently no content available',
 
 };

+ 30 - 1
packages/cs_resources/lib/local/language/zh_CN.dart

@@ -1,4 +1,33 @@
 const Map<String, String> zh_CN = {
-  'app_name': 'Flutter Room',
+  'app_name': 'YYBusiness',
+  'Please enter your login code': '请输入您的登录账号',
+  'Please enter your password': '请输入您的密码',
+  'The login code cannot be empty!': '登录账号不能为空',
+  'The password cannot be empty!': '密码不能为空',
+  'Log in': '登录',
+  'Login Code': '登录账号',
+  'Password': '密码',
+  'Name/Mobile': '请输入姓名或电话',
+  'Check In': '签到',
+  'Check Out': '签出',
+  'Job Date:': '工作日期:',
+  'Start Time:': '开始时间:',
+  'End Time:': '结束时间:',
+  'Name:': '姓名:',
+  'Reset': '重置',
 
+
+  'Pull to refresh': '下拉刷新',
+  'Release ready': '释放刷新',
+  'Refreshing...': '刷新中...',
+  'Succeeded': '成功',
+  'No more': '没有更多了',
+  'Failed': '失败',
+  'Last updated at %T': '最近更新于 %T',
+  'Pull to load': '上拉加载',
+
+  'Network Load Error': '网络加载错误',
+  'Loading...': '加载中...',
+  'Data loading failed! Please refresh and try again': '数据加载失败!请刷新并重试',
+  'There is currently no content available': '当前没有可用数据',
 };

+ 2 - 0
packages/cs_resources/pubspec.yaml

@@ -24,3 +24,5 @@ flutter:
     - assets/
     - assets/base_lib/
     - assets/base_service/
+    - assets/cpt_auth/
+    - assets/cpt_job/

+ 4 - 0
packages/cs_router/lib/componentRouter/auth_service.dart

@@ -3,4 +3,8 @@
  */
 abstract class AuthService {
 
+  void startLoginPage();
+
+  void startPopAllLoginPage();
+
 }

+ 3 - 0
packages/cs_router/lib/componentRouter/job_service.dart

@@ -1,6 +1,9 @@
+
 /**
  * Job组件对应的路由抽象接口
  */
 abstract class JobService {
 
+  void startWithPopSignInSignOutPage();
+
 }

+ 4 - 14
packages/cs_router/lib/path/router_path.dart

@@ -5,29 +5,19 @@ class RouterPath {
 
   static const GUIDE = '/guide'; //指引页面
 
-  //用户登录注册
-  static const AUTH_LOGIN = '/auth/login';
-  static const AUTH_BIND = '/auth/bind'; //绑定手机号
-  static const AUTH_FORGET = '/auth/forget'; //忘记密码
-  static const AUTH_SIGNUP = '/auth/signup'; //手动注册
+  static const AUTH_LOGIN = '/auth/login';  //用户登录注册
+  static const AUTH_SIGNUP = '/auth/signup'; //注册
 
   //首页
   static const MAIN = '/main';
 
-  static const FORMFILED = '/form_filed'; //表单提交
 
-  static const SETTING = '/setting'; // 设置界面
-  static const RESETPASSWORD = '/reset/password'; // 重置密码
-  static const CHANGEMOBILE = '/change/mobile'; // 修改手机号
-  static const DARK_MODEL = '/dark/model'; // 黑暗模式
-  static const NOTIFICATION_ENABLE = '/notification/enable'; // 通知推送设置
-
-  static const MallMain = '/mall/main'; // 商城
+  //工作-签到签出
+  static const JOB_SIGN_IN_SIGN_OUT = '/job/sign_in_sign_out';
 
   static const PREVIEW_IMAGE = '/preview/image'; //预览图片
   static const GLOBAL_WEB = '/global/web'; //全局公用的Web页面
 
-
   //Runalone
   static const RunaloneMain = '/runalone/main'; //独立运行的入口页面
 }

+ 25 - 14
packages/cs_widgets/lib/load_state_layout.dart

@@ -1,3 +1,4 @@
+import 'package:cs_resources/generated/assets.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:cs_resources/constants/color_constants.dart';
@@ -112,16 +113,16 @@ class _LoadStateLayoutState extends State<LoadStateLayout> {
         mainAxisAlignment: MainAxisAlignment.center,
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
-          Get.isDarkMode
-              ? const CircularProgressIndicator(
-                  strokeWidth: 3,
-                  valueColor: AlwaysStoppedAnimation(Colors.white),
-                )
-              : CircularProgressIndicator(
-                  strokeWidth: 3,
-                  valueColor: AlwaysStoppedAnimation(ColorConstants.appBlue),
-                ),
-          MyTextView('加载中...'.tr, marginTop: 15, fontSize: 15.5)
+          CircularProgressIndicator(
+            strokeWidth: 3,
+            valueColor: AlwaysStoppedAnimation(Color(0XFFD6E9F1)),
+          ),
+          MyTextView(
+            'Loading...'.tr,
+            marginTop: 15,
+            fontSize: 14,
+            textColor: Color(0XFFD6E9F1),
+          )
         ],
       ),
     );
@@ -141,8 +142,13 @@ class _LoadStateLayoutState extends State<LoadStateLayout> {
               crossAxisAlignment: CrossAxisAlignment.center,
               mainAxisAlignment: MainAxisAlignment.center,
               children: <Widget>[
-                const MyAssetImage('page_load_error.png', width: 180, height: 180, fit: BoxFit.contain),
-                MyTextView(widget.errorMessage ?? '加载数据错误,请重试'.tr, marginTop: 10, fontSize: 15.5),
+                const MyAssetImage(Assets.baseServicePageLoadError, width: 141, height: 117.5, fit: BoxFit.contain),
+                MyTextView(
+                  widget.errorMessage ?? 'Data loading failed! Please refresh and try again'.tr,
+                  marginTop: 18,
+                  fontSize: 14,
+                  textColor: Color(0XFFD6E9F1),
+                ),
               ],
             )));
   }
@@ -159,8 +165,13 @@ class _LoadStateLayoutState extends State<LoadStateLayout> {
         crossAxisAlignment: CrossAxisAlignment.center,
         mainAxisAlignment: MainAxisAlignment.center,
         children: <Widget>[
-          const MyAssetImage('page_no_data.png', width: 180, height: 180, fit: BoxFit.contain),
-          MyTextView('暂无数据'.tr, marginTop: 10, fontSize: 15.5),
+          const MyAssetImage(Assets.baseServicePageNoData, width: 123.5, height: 115.5, fit: BoxFit.contain),
+          MyTextView(
+            'There is currently no content available'.tr,
+            marginTop: 18,
+            fontSize: 14,
+            textColor: Color(0XFFD6E9F1),
+          ),
         ],
       ),
     );

+ 4 - 4
packages/cs_widgets/lib/my_text_field.dart

@@ -137,9 +137,9 @@ class MyTextField extends StatelessWidget {
                     suffixIcon: showRightIcon == true ? rightWidget : null,
                     labelText: labelText,
                     errorText: errorText,
-                    errorStyle: const TextStyle(color: Colors.red, fontSize: 11.5),
-                    errorBorder: const OutlineInputBorder(
-                      borderSide: BorderSide(color: Colors.red),
+                    errorStyle: TextStyle(color: hexToColor("#7BABC8"), fontSize: 11.5),
+                    errorBorder: OutlineInputBorder(
+                      borderSide: BorderSide(color: hexToColor("#7BABC8")),
                     ),
                   ),
               onChanged: changeActionType == ClickType.debounce
@@ -156,7 +156,7 @@ class MyTextField extends StatelessWidget {
             ),
             showDivider == true
                 ? Divider(
-                    height: 0.5,
+                    height: 0.3,
                     color: dividerColor!,
                   ).marginOnly(top: errorText == null ? 0 : 10)
                 : const SizedBox.shrink(),