Explorar o código

马来西亚的切换账号与刷新逻辑

liukai hai 3 semanas
pai
achega
3501675aa8

+ 158 - 0
packages/cpt_auth/lib/modules/setting/dialog/switch_project_dialog.dart

@@ -0,0 +1,158 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:domain/entity/response/index_option_entity.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:cs_resources/constants/color_constants.dart';
+
+import 'dart:ui';
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/widgets.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/no_shadow_scroll_behavior.dart';
+import 'package:widgets/widget_export.dart';
+
+/*
+ * 切换项目的弹窗
+ */
+class SwitchProjectDialog extends StatefulWidget {
+  final List<IndexOptionEntity> options;
+  final void Function(IndexOptionEntity) confirmAction;
+  final VoidCallback? cancelAction;
+
+  SwitchProjectDialog({
+    required this.options,
+    required this.confirmAction,
+    this.cancelAction,
+  });
+
+  @override
+  _SwitchProjectDialogState createState() => _SwitchProjectDialogState();
+}
+
+class _SwitchProjectDialogState extends State<SwitchProjectDialog> {
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Container(
+          width: double.infinity,
+          decoration: const BoxDecoration(
+            color: Colors.white,
+            borderRadius: BorderRadius.all(Radius.circular(15)),
+          ),
+          child: Column(
+            children: [
+              MyTextView(
+                "Switch Projects".tr,
+                fontSize: 19,
+                isFontMedium: true,
+                textColor: ColorConstants.black,
+                marginTop: 15,
+                marginBottom: 15,
+              ),
+              Scrollbar(
+                child: ScrollConfiguration(
+                  behavior: NoShadowScrollBehavior(),
+                  child: SingleChildScrollView(
+                    child: Column(
+                      children: widget.options.map<Widget>((IndexOptionEntity option) {
+                        return InkWell(
+                          onTap: () {
+                            // 清除其他选项的 checked 状态
+                            for (var opt in widget.options) {
+                              opt.checked = null; // 清除所有选项的 checked 状态
+                            }
+                            option.checked = 'checked'; // 选中当前选项
+                            setState(() {}); // 刷新页面
+                          },
+                          child: Row(
+                            mainAxisSize: MainAxisSize.max,
+                            children: [
+                              MyTextView(
+                                option.txt ?? "",
+                                fontSize: 15,
+                                isFontRegular: true,
+                                textColor: ColorConstants.black33,
+                              ).expanded(),
+                              option.checked == "checked"
+                                  ? const MyAssetImage(Assets.cptAuthCheckedIcon, width: 20.5, height: 20.5)
+                                  : const MyAssetImage(Assets.cptAuthUncheckedIcon, width: 20.5, height: 20.5)
+                            ],
+                          ).paddingOnly(top: 12, bottom: 12, left: 20, right: 20),
+                        );
+                      }).toList(),
+                    ),
+                  ),
+                ),
+              ).constrained(maxHeight: 210),
+              Container(
+                margin: const EdgeInsets.only(top: 25),
+                color: const Color(0XFFCECECE),
+                height: 0.5,
+              ),
+              Row(
+                children: [
+                  Expanded(
+                    flex: 1,
+                    child: InkWell(
+                      onTap: () {
+                        onCancel();
+                        widget.cancelAction?.call();
+                      },
+                      child: MyTextView(
+                        "Cancel".tr,
+                        fontSize: 17.5,
+                        isFontMedium: true,
+                        textAlign: TextAlign.center,
+                        textColor: const Color(0XFF0085C4),
+                        cornerRadius: 3,
+                        borderWidth: 1,
+                      ),
+                    ),
+                  ),
+                  Container(
+                    color: const Color(0xff09141F).withOpacity(0.13),
+                    width: 0.5,
+                  ),
+                  Expanded(
+                    flex: 1,
+                    child: InkWell(
+                      onTap: () async {
+                        onCancel();
+                        // 找到被选中的选项并触发确认操作
+                        final selectedOption = widget.options.firstWhereOrNull((opt) => opt.checked == 'checked');
+                        if (selectedOption != null) {
+                          widget.confirmAction(selectedOption);
+                        }
+                      },
+                      child: MyTextView(
+                        "Confirm".tr,
+                        marginLeft: 10,
+                        fontSize: 17.5,
+                        isFontMedium: true,
+                        textAlign: TextAlign.center,
+                        textColor: const Color(0XFF0085C4),
+                        cornerRadius: 3,
+                      ),
+                    ),
+                  ),
+                ],
+              ).constrained(height: 46),
+            ],
+          ),
+        ),
+      ],
+    ).constrained(width: 295);
+  }
+
+  // 取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+}

+ 55 - 3
packages/cpt_auth/lib/modules/setting/setting_controller.dart

@@ -1,22 +1,73 @@
 import 'package:cpt_auth/modules/login/login_page.dart';
 import 'package:cpt_auth/modules/reset_psd/reset_psd_page.dart';
+import 'package:cpt_auth/modules/setting/dialog/switch_project_dialog.dart';
+import 'package:domain/entity/response/index_option_entity.dart';
 import 'package:domain/repository/auth_repository.dart';
+import 'package:domain/repository/ms_repository.dart';
 import 'package:get/get.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
+import 'package:plugin_basic/service/app_config_service.dart';
 import 'package:plugin_basic/service/user_service.dart';
 import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
+import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/dialog/app_default_dialog.dart';
 
 import 'setting_state.dart';
 
 class SettingController extends GetxController with DioCancelableMixin {
   final AuthRepository _authRepository = Get.find();
+  final MSRepository _msRepository = Get.find();
   final SettingState state = SettingState();
 
   //切换账号
-  void switchProjects() {
-    ToastEngine.show("切换账号");
+  void switchProjects() async {
+
+    final result = await _msRepository.fetchSwitchProjectList(cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+      final projects = result.data?.cutUser;
+
+      if (projects != null && projects.isNotEmpty) {
+        _showSwitchProjectDialog(projects);
+      }
+    } else {
+      final errorMessage = result.errorMsg;
+      ToastEngine.show(errorMessage ?? "Network Load Error".tr);
+    }
+  }
+
+  void _showSwitchProjectDialog(List<IndexOptionEntity> projects) {
+    DialogEngine.show(
+        widget: SwitchProjectDialog(
+      options: projects,
+      confirmAction: (entity) {
+
+        _requestSwitchProject(entity);
+      },
+    ));
+  }
+
+  void _requestSwitchProject(IndexOptionEntity entity) async{
+    final result = await _msRepository.switchProjectSubmit(entity.value,cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+
+      NotifyEngine.showSuccess('successful'.tr);
+
+     final token =  result.data?.token;
+      UserService.to.setToken(token);
+
+      //发送通知刷新首页
+      bus.emit(AppConstant.eventMainRefresh, true);
+
+    } else {
+      final errorMessage = result.errorMsg;
+      ToastEngine.show(errorMessage ?? "Network Load Error".tr);
+    }
   }
 
   //去重置密码页面
@@ -63,7 +114,7 @@ class SettingController extends GetxController with DioCancelableMixin {
 
   /// 请求接口退出账号
   void _requestLogout() async {
-    var result = await _authRepository.userLogout(cancelToken: cancelToken);
+    var result = await _authRepository.userLogout(country: ConfigService.to.selectCountry.value, cancelToken: cancelToken);
 
     //处理数据
     if (result.isSuccess) {
@@ -74,4 +125,5 @@ class SettingController extends GetxController with DioCancelableMixin {
       ToastEngine.show(result.errorMsg ?? "Network Load Error".tr);
     }
   }
+
 }

+ 14 - 8
packages/cpt_auth/lib/modules/setting/setting_page.dart

@@ -3,6 +3,7 @@ import 'package:cs_resources/generated/assets.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_basic/base/base_stateless_page.dart';
 import 'package:plugin_basic/basic_export.dart';
+import 'package:plugin_basic/service/app_config_service.dart';
 import 'package:plugin_basic/utils/ext_get_nav.dart';
 import 'package:router/path/router_path.dart';
 import 'package:shared/utils/screen_util.dart';
@@ -56,16 +57,21 @@ class SettingPage extends BaseStatelessPage<SettingController> {
             ),
           ),
           child: Column(children: [
-            SizedBox(height: 10),
-            // SettingItemContainer(iconPath: Assets.mainSettingSwitchProject, title: "Switch Projects".tr).onTap(() {
-            //   controller.switchProjects();
-            // }),
-            SettingItemContainer(iconPath: Assets.mainSettingResetPassword, title: "Reset Password".tr).onTap(() {
+            const SizedBox(height: 10),
+
+          ConfigService.to.selectCountry.value == 3 ?
+          SettingItemContainer(iconPath: Assets.mainSettingSwitchProject, title: "Switch Projects".tr).onTap(() {
+              controller.switchProjects();
+            }) : const SizedBox(),
+
+            ConfigService.to.selectCountry.value != 3 ? SettingItemContainer(iconPath: Assets.mainSettingResetPassword, title: "Reset Password".tr).onTap(() {
               controller.gotoResetPasswordPage();
-            }),
-            SettingItemContainer(iconPath: Assets.mainSettingAccountDelectivation, title: "Account Deactivation".tr).onTap(() {
+            }): const SizedBox(),
+
+            ConfigService.to.selectCountry.value != 3 ? SettingItemContainer(iconPath: Assets.mainSettingAccountDelectivation, title: "Account Deactivation".tr).onTap(() {
               controller.doAccountDelete();
-            }),
+            }): const SizedBox(),
+
             SettingItemContainer(iconPath: Assets.mainSettingLogOut, title: "Logout".tr).onTap(() {
               controller.doLogout();
             }),

+ 22 - 0
packages/cpt_ms/lib/modules/main/main_controller.dart

@@ -9,6 +9,7 @@ import 'package:plugin_basic/service/user_service.dart';
 import 'package:plugin_platform/engine/sp/sp_util.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/componentRouter/component_router_service.dart';
+import 'package:shared/utils/event_bus.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
@@ -92,6 +93,14 @@ class MainController extends GetxController {
   void onReady() async {
     super.onReady();
     fetchHomeData();
+    registerEventBus();
+  }
+
+  @override
+  void onClose() {
+    unregisterEventBus();
+    state.datas.clear();
+    super.onClose();
   }
 
   /// 跳转到指定的模块中去
@@ -107,4 +116,17 @@ class MainController extends GetxController {
   void gotoSettingPage() {
     ComponentRouterServices.authService.startSettingPage();
   }
+
+  // EventBus 的事件接收
+  Subscription? subscribe;
+
+  void registerEventBus() {
+    subscribe = bus.on(AppConstant.eventMainRefresh, (arg) {
+      refreshController.callRefresh();
+    });
+  }
+
+  void unregisterEventBus() {
+    bus.off(AppConstant.eventMainRefresh, subscribe);
+  }
 }

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

@@ -507,4 +507,7 @@ class ApiConstants {
   //签到保存
   static const apiSignSaveMS = "/index.php/api/v1/er/sign/save";
 
+  // 用户登出系统
+  static const apiUserLogoutMS = "/index.php/api/v1/er/logout";
+
 }

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

@@ -0,0 +1,46 @@
+import 'package:domain/entity/response/index_option_entity.dart';
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/switch_project_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/switch_project_entity.g.dart';
+
+@JsonSerializable()
+class SwitchProjectEntity {
+	@JSONField(name: "cut_user")
+	List<IndexOptionEntity>? cutUser = [];
+	@JSONField(name: "user_list")
+	List<SwitchProjectUserList>? userList = [];
+
+	SwitchProjectEntity();
+
+	factory SwitchProjectEntity.fromJson(Map<String, dynamic> json) => $SwitchProjectEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $SwitchProjectEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+
+@JsonSerializable()
+class SwitchProjectUserList {
+	@JSONField(name: "admin_id")
+	String? adminId;
+	@JSONField(name: "admin_name")
+	String? adminName;
+	@JSONField(name: "employer_name")
+	String? employerName;
+
+	SwitchProjectUserList();
+
+	factory SwitchProjectUserList.fromJson(Map<String, dynamic> json) => $SwitchProjectUserListFromJson(json);
+
+	Map<String, dynamic> toJson() => $SwitchProjectUserListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

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

@@ -79,6 +79,7 @@ import 'package:domain/entity/response/staff_remark_history_entity.dart';
 import 'package:domain/entity/response/staff_report_v_n_entity.dart';
 import 'package:domain/entity/response/staff_request_report_entity.dart';
 import 'package:domain/entity/response/staff_review_history_s_g_entity.dart';
+import 'package:domain/entity/response/switch_project_entity.dart';
 import 'package:domain/entity/response/u_k_attendance_entity.dart';
 import 'package:domain/entity/response/u_k_report_attendance_entity.dart';
 import 'package:domain/entity/response/u_k_report_labour_entity.dart';
@@ -688,6 +689,12 @@ class JsonConvert {
     if (<StaffReviewHistorySGReviews>[] is M) {
       return data.map<StaffReviewHistorySGReviews>((Map<String, dynamic> e) => StaffReviewHistorySGReviews.fromJson(e)).toList() as M;
     }
+    if (<SwitchProjectEntity>[] is M) {
+      return data.map<SwitchProjectEntity>((Map<String, dynamic> e) => SwitchProjectEntity.fromJson(e)).toList() as M;
+    }
+    if (<SwitchProjectUserList>[] is M) {
+      return data.map<SwitchProjectUserList>((Map<String, dynamic> e) => SwitchProjectUserList.fromJson(e)).toList() as M;
+    }
     if (<UKAttendanceEntity>[] is M) {
       return data.map<UKAttendanceEntity>((Map<String, dynamic> e) => UKAttendanceEntity.fromJson(e)).toList() as M;
     }
@@ -921,6 +928,8 @@ class JsonConvertClassCollection {
     (StaffRequestReportEntity).toString(): StaffRequestReportEntity.fromJson,
     (StaffReviewHistorySGEntity).toString(): StaffReviewHistorySGEntity.fromJson,
     (StaffReviewHistorySGReviews).toString(): StaffReviewHistorySGReviews.fromJson,
+    (SwitchProjectEntity).toString(): SwitchProjectEntity.fromJson,
+    (SwitchProjectUserList).toString(): SwitchProjectUserList.fromJson,
     (UKAttendanceEntity).toString(): UKAttendanceEntity.fromJson,
     (UKAttendanceRows).toString(): UKAttendanceRows.fromJson,
     (UKAttendanceInOut).toString(): UKAttendanceInOut.fromJson,

+ 75 - 0
packages/cs_domain/lib/generated/json/switch_project_entity.g.dart

@@ -0,0 +1,75 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/response/switch_project_entity.dart';
+import 'package:domain/entity/response/index_option_entity.dart';
+
+
+SwitchProjectEntity $SwitchProjectEntityFromJson(Map<String, dynamic> json) {
+  final SwitchProjectEntity switchProjectEntity = SwitchProjectEntity();
+  final List<IndexOptionEntity>? cutUser = (json['cut_user'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<IndexOptionEntity>(e) as IndexOptionEntity).toList();
+  if (cutUser != null) {
+    switchProjectEntity.cutUser = cutUser;
+  }
+  final List<SwitchProjectUserList>? userList = (json['user_list'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<SwitchProjectUserList>(e) as SwitchProjectUserList).toList();
+  if (userList != null) {
+    switchProjectEntity.userList = userList;
+  }
+  return switchProjectEntity;
+}
+
+Map<String, dynamic> $SwitchProjectEntityToJson(SwitchProjectEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['cut_user'] = entity.cutUser?.map((v) => v.toJson()).toList();
+  data['user_list'] = entity.userList?.map((v) => v.toJson()).toList();
+  return data;
+}
+
+extension SwitchProjectEntityExtension on SwitchProjectEntity {
+  SwitchProjectEntity copyWith({
+    List<IndexOptionEntity>? cutUser,
+    List<SwitchProjectUserList>? userList,
+  }) {
+    return SwitchProjectEntity()
+      ..cutUser = cutUser ?? this.cutUser
+      ..userList = userList ?? this.userList;
+  }
+}
+
+SwitchProjectUserList $SwitchProjectUserListFromJson(Map<String, dynamic> json) {
+  final SwitchProjectUserList switchProjectUserList = SwitchProjectUserList();
+  final String? adminId = jsonConvert.convert<String>(json['admin_id']);
+  if (adminId != null) {
+    switchProjectUserList.adminId = adminId;
+  }
+  final String? adminName = jsonConvert.convert<String>(json['admin_name']);
+  if (adminName != null) {
+    switchProjectUserList.adminName = adminName;
+  }
+  final String? employerName = jsonConvert.convert<String>(json['employer_name']);
+  if (employerName != null) {
+    switchProjectUserList.employerName = employerName;
+  }
+  return switchProjectUserList;
+}
+
+Map<String, dynamic> $SwitchProjectUserListToJson(SwitchProjectUserList entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['admin_id'] = entity.adminId;
+  data['admin_name'] = entity.adminName;
+  data['employer_name'] = entity.employerName;
+  return data;
+}
+
+extension SwitchProjectUserListExtension on SwitchProjectUserList {
+  SwitchProjectUserList copyWith({
+    String? adminId,
+    String? adminName,
+    String? employerName,
+  }) {
+    return SwitchProjectUserList()
+      ..adminId = adminId ?? this.adminId
+      ..adminName = adminName ?? this.adminName
+      ..employerName = employerName ?? this.employerName;
+  }
+}

+ 2 - 1
packages/cs_domain/lib/repository/auth_repository.dart

@@ -50,10 +50,11 @@ class AuthRepository extends GetxService {
 
   /// 退出登录
   Future<HttpResult> userLogout({
+    required int country,
     CancelToken? cancelToken,
   }) async {
     final result = await httpProvider.requestNetResult(
-      ApiConstants.apiUserLogout,
+      country == 3 ? ApiConstants.apiUserLogoutMS : ApiConstants.apiUserLogout,
       method: HttpMethod.GET,
       networkDebounce: true,
       isShowLoadingDialog: true,

+ 47 - 0
packages/cs_domain/lib/repository/ms_repository.dart

@@ -1,4 +1,6 @@
+import 'package:domain/entity/response/hotel_info_entity.dart';
 import 'package:domain/entity/response/sign_in_sign_out_entity.dart';
+import 'package:domain/entity/response/switch_project_entity.dart';
 import 'package:get/get.dart';
 import 'package:plugin_platform/http/http_provider.dart';
 import 'package:plugin_platform/http/http_result.dart';
@@ -81,4 +83,49 @@ class MSRepository extends GetxService {
     }
     return result.convert();
   }
+
+  /// 可以切换的Project列表
+  Future<HttpResult<SwitchProjectEntity>> fetchSwitchProjectList({
+    CancelToken? cancelToken,
+  }) async {
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiAccountListMS,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = SwitchProjectEntity.fromJson(json!);
+      return result.convert<SwitchProjectEntity>(data: data);
+    }
+    return result.convert();
+  }
+
+  /// 切换项目
+  Future<HttpResult<HotelInfoEntity>> switchProjectSubmit(
+    String? adminId, {
+    CancelToken? cancelToken,
+  }) async {
+    //参数
+    Map<String, String> params = {};
+    params['admin_id'] = adminId ?? "";
+
+    final result = await httpProvider.requestNetResult(
+      ApiConstants.apiSwitchAccountMS,
+      method: HttpMethod.POST,
+      params: params,
+      networkDebounce: true,
+      isShowLoadingDialog: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = HotelInfoEntity.fromJson(json!);
+      return result.convert<HotelInfoEntity>(data: data);
+    }
+    return result.convert();
+  }
 }

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

@@ -22,5 +22,6 @@ class AppConstant {
   static const eventProfile2Refresh = 'event_profile_refresh'; //通知用户信息需要刷新
   static const eventLabourRequestRefresh = 'event_labour_request_refresh'; //用工请求的列表刷新
   static const eventAppliedListRefresh = 'event_applied_list_refresh'; //已申请的列表刷新
+  static const eventMainRefresh = 'event_main_refresh'; //首页刷新
 
 }

BIN=BIN
packages/cs_resources/assets/cpt_auth/unchecked_icon.webp


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

@@ -38,6 +38,7 @@ class Assets {
   static const String cptAuthPasswordShowIcon = 'assets/cpt_auth/password_show_icon.webp';
   static const String cptAuthSgIcon = 'assets/cpt_auth/sg_icon.webp';
   static const String cptAuthUkIcon = 'assets/cpt_auth/uk_icon.webp';
+  static const String cptAuthUncheckedIcon = 'assets/cpt_auth/unchecked_icon.webp';
   static const String cptAuthVnIcon = 'assets/cpt_auth/vn_icon.webp';
   static const String cptJobArrawDownIcon = 'assets/cpt_job/arraw_down_icon.webp';
   static const String cptJobArrawUpIcon = 'assets/cpt_job/arraw_up_icon.webp';