Browse Source

添加搜索房产
选择房产单元与校验
选择角色之后的文件选择上传与国际化处理类型区分
登录页面与房产页面的添加之后的跳转路由处理
我的房产页面处理
我的家庭成员列表处理
Me页面添加刷新用户信息处理

liukai 3 months ago
parent
commit
8c94a8ef06
56 changed files with 1300 additions and 545 deletions
  1. 0 1
      packages/cpt_auth/lib/modules/auth_login/auth_login_view_model.dart
  2. 117 0
      packages/cpt_auth/lib/modules/estate_upload_success/estate_upload_success_page.dart
  3. 22 0
      packages/cpt_auth/lib/modules/estate_upload_success/estate_upload_success_view_model.dart
  4. 27 0
      packages/cpt_auth/lib/modules/estate_upload_success/estate_upload_success_view_model.g.dart
  5. 1 1
      packages/cpt_auth/lib/modules/forgot_input/forgot_input_view_model.g.dart
  6. 1 1
      packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_view_model.g.dart
  7. 61 0
      packages/cpt_auth/lib/modules/select_estate/attach_input_widget.dart
  8. 74 0
      packages/cpt_auth/lib/modules/select_estate/dialog/attach_search_dialog.dart
  9. 128 114
      packages/cpt_auth/lib/modules/select_estate/select_estate_page.dart
  10. 29 3
      packages/cpt_auth/lib/modules/select_estate/select_estate_state.dart
  11. 74 4
      packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.dart
  12. 1 1
      packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.g.dart
  13. 7 0
      packages/cpt_auth/lib/modules/select_role/select_role_view_model.dart
  14. 1 1
      packages/cpt_auth/lib/modules/select_role/select_role_view_model.g.dart
  15. 9 5
      packages/cpt_auth/lib/modules/select_unit/select_unit_page.dart
  16. 0 12
      packages/cpt_auth/lib/modules/select_unit/select_unit_state.dart
  17. 60 5
      packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.dart
  18. 1 1
      packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.g.dart
  19. 0 2
      packages/cpt_auth/lib/modules/sign_up/sign_up_view_model.dart
  20. 7 6
      packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_page.dart
  21. 0 1
      packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_view_model.dart
  22. 1 15
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_page.dart
  23. 4 6
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_state.dart
  24. 48 7
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.dart
  25. 1 1
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.g.dart
  26. 3 0
      packages/cpt_auth/lib/router/page/auth_page_router.dart
  27. 25 22
      packages/cpt_auth/lib/router/page/auth_page_router.gr.dart
  28. 72 61
      packages/cpt_main/lib/modules/me/me_page.dart
  29. 27 2
      packages/cpt_main/lib/modules/me/me_view_model.dart
  30. 0 6
      packages/cpt_profile/lib/modules/my_estate/estate_group_data.dart
  31. 12 10
      packages/cpt_profile/lib/modules/my_estate/item_estate.dart
  32. 10 7
      packages/cpt_profile/lib/modules/my_estate/my_estate_page.dart
  33. 3 3
      packages/cpt_profile/lib/modules/my_estate/my_estate_state.dart
  34. 103 97
      packages/cpt_profile/lib/modules/my_estate/my_estate_view_model.dart
  35. 10 10
      packages/cpt_profile/lib/modules/my_household/item_household.dart
  36. 3 3
      packages/cpt_profile/lib/modules/my_household/my_household_page.dart
  37. 3 2
      packages/cpt_profile/lib/modules/my_household/my_household_state.dart
  38. 30 78
      packages/cpt_profile/lib/modules/my_household/my_household_view_model.dart
  39. 15 0
      packages/cs_domain/lib/constants/api_constants.dart
  40. 21 0
      packages/cs_domain/lib/entity/id_name_entity.dart
  41. 1 1
      packages/cs_domain/lib/entity/user_me_entity.dart
  42. 5 0
      packages/cs_domain/lib/generated/json/base/json_convert_content.dart
  43. 33 0
      packages/cs_domain/lib/generated/json/id_name_entity.g.dart
  44. 2 2
      packages/cs_domain/lib/generated/json/user_me_entity.g.dart
  45. 143 0
      packages/cs_domain/lib/repository/profile_repository.dart
  46. 1 0
      packages/cs_plugin_basic/lib/basic_export.dart
  47. 1 0
      packages/cs_plugin_basic/lib/constants/app_constant.dart
  48. 1 1
      packages/cs_plugin_basic/lib/provider/user_config/user_config_service.dart
  49. 3 0
      packages/cs_plugin_basic/pubspec.yaml
  50. 5 0
      packages/cs_plugin_platform/lib/engine/dialog/dialog_engine.dart
  51. 13 8
      packages/cs_resources/lib/generated/intl/messages_en.dart
  52. 48 18
      packages/cs_resources/lib/generated/l10n.dart
  53. 6 3
      packages/cs_resources/lib/l10n/intl_en.arb
  54. 6 3
      packages/cs_resources/lib/l10n/intl_zh_CN.arb
  55. 6 3
      packages/cs_resources/lib/l10n/intl_zh_HK.arb
  56. 15 18
      packages/cs_router/lib/path/router_path.dart

+ 0 - 1
packages/cpt_auth/lib/modules/auth_login/auth_login_view_model.dart

@@ -22,7 +22,6 @@ class AuthLoginViewModel extends _$AuthLoginViewModel {
   @override
   LoginState build() {
     authRepository = ref.read(authRepositoryProvider);
-
     final state = LoginState();
     initListener(state);
     ref.onDispose(() {

+ 117 - 0
packages/cpt_auth/lib/modules/estate_upload_success/estate_upload_success_page.dart

@@ -0,0 +1,117 @@
+import 'package:cpt_auth/modules/sing_up_success/sign_up_success_view_model.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import '../../router/page/auth_page_router.dart';
+import 'estate_upload_success_view_model.dart';
+
+@RoutePage()
+class EstateUploadSuccessPage extends HookConsumerWidget {
+  const EstateUploadSuccessPage({Key? key}) : super(key: key);
+
+  //登录页面进入
+  static void startPop2Login() {
+    appRouter.pushAndPopUntil(
+      const EstateUploadSuccessPageRoute(),
+      predicate: (route) {
+        return route.settings.name == "AuthLoginPageRoute";
+      },
+    );
+  }
+
+  //Me页面进入
+  static void startPop2Estate() {
+    appRouter.pushAndPopUntil(
+      const EstateUploadSuccessPageRoute(),
+      predicate: (route) {
+        return route.settings.name == "MyEstatePageRoute";
+      },
+    );
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(estateUploadSuccessViewModelProvider.notifier);
+    final userConfig = UserConfigService.getState(ref: ref);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, ""),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: Container(
+        padding: const EdgeInsets.symmetric(horizontal: 18),
+        width: double.infinity,
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            SingleChildScrollView(
+                scrollDirection: Axis.vertical,
+                physics: const BouncingScrollPhysics(),
+                child: Column(
+                  children: [
+                    //顶部图片
+                    const MyAssetImage(
+                      Assets.authYyHomeSuccess,
+                      width: 264,
+                      height: 180,
+                    ).alignCenter().marginOnly(top: 12),
+
+                    MyTextView(
+                      S.current.thank_you_name(userConfig.userName ?? ""),
+                      fontSize: 23,
+                      marginTop: 30,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+
+                    MyTextView(
+                      S.current.estate_upload_success_desc,
+                      fontSize: 15,
+                      marginTop: 25,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                  ],
+                )).expanded(),
+            Row(
+              children: [
+                MyButton(
+                  onPressed: viewModel.callEmail,
+                  text: S.current.send_email,
+                  textColor: Colors.white,
+                  backgroundColor: context.appColors.btnBgDefault,
+                  fontWeight: FontWeight.w500,
+                  type: ClickType.throttle,
+                  fontSize: 16,
+                  minHeight: 50,
+                  radius: 5,
+                ).expanded(),
+                MyButton(
+                  onPressed: viewModel.callPhone,
+                  text: S.current.call_phone,
+                  textColor: Colors.white,
+                  backgroundColor: context.appColors.btnBgDefault,
+                  fontWeight: FontWeight.w500,
+                  type: ClickType.throttle,
+                  fontSize: 16,
+                  minHeight: 50,
+                  radius: 5,
+                ).marginOnly(left: 10).expanded(),
+              ],
+            ).marginOnly(top: 50, bottom: 50, left: 18, right: 18),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 22 - 0
packages/cpt_auth/lib/modules/estate_upload_success/estate_upload_success_view_model.dart

@@ -0,0 +1,22 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+import '../select_estate/select_estate_page.dart';
+
+part 'estate_upload_success_view_model.g.dart';
+
+@riverpod
+class EstateUploadSuccessViewModel extends _$EstateUploadSuccessViewModel {
+  @override
+  void build() {}
+
+  //拨打电话
+  void callPhone() {
+
+  }
+
+  //发送邮件
+  void callEmail() {
+
+  }
+
+}

+ 27 - 0
packages/cpt_auth/lib/modules/estate_upload_success/estate_upload_success_view_model.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'estate_upload_success_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$estateUploadSuccessViewModelHash() =>
+    r'b59a8d4df107b2a6b269bf899884ac09dd9e3122';
+
+/// See also [EstateUploadSuccessViewModel].
+@ProviderFor(EstateUploadSuccessViewModel)
+final estateUploadSuccessViewModelProvider =
+    AutoDisposeNotifierProvider<EstateUploadSuccessViewModel, void>.internal(
+  EstateUploadSuccessViewModel.new,
+  name: r'estateUploadSuccessViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$estateUploadSuccessViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$EstateUploadSuccessViewModel = AutoDisposeNotifier<void>;
+// ignore_for_file: type=lint
+// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 1 - 1
packages/cpt_auth/lib/modules/forgot_input/forgot_input_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'forgot_input_view_model.dart';
 // **************************************************************************
 
 String _$forgotInputViewModelHash() =>
-    r'5998f4831003ebb7e6ebe822bc002580f13b1962';
+    r'd3f941cb656ba085b920cfb68cc80c597e5b97f1';
 
 /// See also [ForgotInputViewModel].
 @ProviderFor(ForgotInputViewModel)

+ 1 - 1
packages/cpt_auth/lib/modules/forgot_verify/forgot_verify_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'forgot_verify_view_model.dart';
 // **************************************************************************
 
 String _$forgotVerifyViewModelHash() =>
-    r'9ca96e6da48e893d90ed8b0dc939ebae4c1fb940';
+    r'8b8ca850496d1176fa0eb77104d3fedf026e3bc3';
 
 /// See also [ForgotVerifyViewModel].
 @ProviderFor(ForgotVerifyViewModel)

+ 61 - 0
packages/cpt_auth/lib/modules/select_estate/attach_input_widget.dart

@@ -0,0 +1,61 @@
+import 'package:cpt_auth/modules/select_estate/select_estate_view_model.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/widget_export.dart';
+
+//输入框的布局,单独抽取为了做Attach弹窗
+class AttachInputWidget extends HookConsumerWidget {
+  final void Function(BuildContext context, String value) onChanged;
+
+  AttachInputWidget({
+    required this.onChanged,
+  });
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final state = ref.watch(selectEstateViewModelProvider);
+
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        "estate",
+        key: key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        "",
+        hintText: state.formData['estate']!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData['estate']!['controller'],
+        focusNode: state.formData['estate']!['focusNode'],
+        margin: const EdgeInsets.only(top: 0),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        height: 44,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: TextInputType.text,
+        textInputAction: TextInputAction.done,
+        onChanged: (k, v) {
+          onChanged.call(context, v);
+        },
+        changeActionType: ClickType.debounce,
+        changeActionMilliseconds: 500,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: false,
+        errorText: null,
+        showLeftIcon: true,
+        showRightIcon: false,
+        rightWidget: null,
+      ),
+    );
+  }
+}

+ 74 - 0
packages/cpt_auth/lib/modules/select_estate/dialog/attach_search_dialog.dart

@@ -0,0 +1,74 @@
+import 'package:cpt_auth/modules/auth_login/auth_login_page.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/id_name_entity.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/src/widgets/framework.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../select_estate_view_model.dart';
+
+//输入文本框
+class AttachSearchDialog extends HookConsumerWidget {
+  final ValueChanged<IdNameEntity?> onSelected;
+
+  AttachSearchDialog({
+    required this.onSelected,
+  });
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final state = ref.watch(selectEstateViewModelProvider);
+
+    return Container(
+      margin: const EdgeInsets.symmetric(horizontal: 38),
+      padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
+      decoration: BoxDecoration(
+        color: context.appColors.whiteBG,
+        borderRadius: BorderRadius.circular(5.0), // 5个圆角
+        boxShadow: [
+          BoxShadow(
+            color: const Color(0xFF656565).withOpacity(0.1), // 阴影颜色,并且设置透明度
+            offset: const Offset(0, 1.5), // 阴影的偏移量
+            blurRadius: 2.5, // 模糊半径
+            spreadRadius: 1.5, // 扩散半径
+          ),
+        ],
+      ),
+      constraints: const BoxConstraints(
+        maxHeight: 200, // 设置最大高度
+      ),
+      child: ListView.builder(
+        padding: EdgeInsets.zero,
+        shrinkWrap: true,
+        physics: const AlwaysScrollableScrollPhysics(),
+        itemCount: state.estateList?.length ?? 0,
+        itemBuilder: (context, index) {
+          final item = state.estateList?[index];
+          return MyTextView(
+            item?.name ?? "",
+            fontSize: 15,
+            paddingTop: 10,
+            paddingBottom: 10,
+            isFontRegular: true,
+            onClick: () {
+              onSelected(item); // 选中回调
+              onCancel();
+            },
+            textColor: context.appColors.textBlack,
+          );
+        },
+      ),
+    );
+  }
+}
+
+//取消弹框
+void onCancel() async {
+  SmartDialog.dismiss();
+}

+ 128 - 114
packages/cpt_auth/lib/modules/select_estate/select_estate_page.dart

@@ -1,24 +1,31 @@
-import 'package:cpt_auth/modules/select_estate/select_estate_state.dart';
+import 'dart:async';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_load_image.dart';
-import 'package:widgets/my_text_field.dart';
 import 'package:widgets/my_text_view.dart';
-import 'package:widgets/widget_export.dart';
-
+import 'package:plugin_basic/basic_export.dart';
 import '../../router/page/auth_page_router.dart';
+import 'attach_input_widget.dart';
 import 'select_estate_view_model.dart';
 
 @RoutePage()
-class SelectEstatePage extends HookConsumerWidget {
+class SelectEstatePage extends HookConsumerWidget with WidgetsBindingObserver {
+  SelectEstateViewModel? viewModel;
+  bool _isKeyboardVisible = false; //软件是否展示
+  double _previousBottom = 0; // 用于保存上一个 Insets
+  Function()? throttledShowDropDownDialog; // 定义防抖函数
+  bool isVisible = true; //页面是否可见
+
   SelectEstatePage({Key? key}) : super(key: key);
 
   //启动当前页面
@@ -32,127 +39,134 @@ class SelectEstatePage extends HookConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final viewModel = ref.watch(selectEstateViewModelProvider.notifier);
+    viewModel = ref.watch(selectEstateViewModelProvider.notifier);
     final state = ref.watch(selectEstateViewModelProvider);
 
+    // 初始化防抖函数
+    throttledShowDropDownDialog ??= throttle(() {
+      viewModel?.showDropDownDialog(needReLocation: true);
+    }) as Function()?;
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      WidgetsBinding.instance.addObserver(this);
+      return () {
+        // 组件卸载时执行
+        WidgetsBinding.instance.removeObserver(this);
+      };
+    }, []);
+
     return Scaffold(
       appBar: MyAppBar.appBar(context, S.current.yy_home_accounts),
       backgroundColor: context.appColors.backgroundDefault,
       body: Container(
         padding: const EdgeInsets.symmetric(horizontal: 38),
         width: double.infinity,
-        child: Column(
-          mainAxisSize: MainAxisSize.max,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            SingleChildScrollView(
-                scrollDirection: Axis.vertical,
-                physics: const BouncingScrollPhysics(),
-                child: Column(
-                  crossAxisAlignment: CrossAxisAlignment.center,
-                  children: [
-                    //顶部图片
-                    const MyAssetImage(
-                      Assets.authChooseEstateBuilding,
-                      width: 267,
-                      height: 158,
-                    ).marginOnly(top: 28, bottom: 38),
-
-                    MyTextView(
-                      S.current.estate_or_building_name,
-                      fontSize: 23,
-                      marginBottom: 20,
-                      textAlign: TextAlign.center,
-                      isFontMedium: true,
-                      textColor: context.appColors.textBlack,
-                    ),
-
-                    //输入资产的名称
-                    _buildInputLayout(
-                      context,
-                      state,
-                      "estate",
-                      textInputAction: TextInputAction.done,
-                      onSubmit: (formKey, value) {
-                        state.formData[formKey]!['focusNode'].unfocus();
-                      },
-                    ),
-
-                    MyTextView(
-                      S.current.estate_name_desc,
-                      fontSize: 15,
-                      marginTop: 19,
-                      isFontMedium: true,
-                      textColor: context.appColors.textBlack,
-                    ),
-                  ],
-                )).expanded(),
-
-            MyButton(
-              onPressed: viewModel.submitEstate,
-              text: S.current.next,
-              textColor: Colors.white,
-              backgroundColor: context.appColors.btnBgDefault,
-              fontWeight: FontWeight.w500,
-              type: ClickType.throttle,
-              fontSize: 16,
-              minHeight: 50,
-              radius: 5,
-            ).marginOnly(top: 50, bottom: 50),
-          ],
+        child: VisibilityDetector(
+          key: Key('select-estate-page'),
+          onVisibilityChanged: (VisibilityInfo info) {
+            // 检测页面是否可见
+            isVisible = info.visibleFraction > 0;
+            Log.d("检测页面是否可见:$isVisible");
+          },
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              SingleChildScrollView(
+                  scrollDirection: Axis.vertical,
+                  physics: const BouncingScrollPhysics(),
+                  child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      //顶部图片
+                      const MyAssetImage(
+                        Assets.authChooseEstateBuilding,
+                        width: 267,
+                        height: 158,
+                      ).marginOnly(top: 28, bottom: 38),
+
+                      MyTextView(
+                        S.current.estate_or_building_name,
+                        fontSize: 23,
+                        marginBottom: 20,
+                        textAlign: TextAlign.center,
+                        isFontMedium: true,
+                        textColor: context.appColors.textBlack,
+                      ),
+
+                      //输入资产的名称
+                      AttachInputWidget(
+                        onChanged: (context, value) {
+                          viewModel?.searchEstate(context, value);
+                        },
+                      ),
+
+                      MyTextView(
+                        S.current.estate_name_desc,
+                        fontSize: 15,
+                        marginTop: 19,
+                        isFontMedium: true,
+                        textColor: context.appColors.textBlack,
+                      ),
+                    ],
+                  )).expanded(),
+              MyButton(
+                onPressed: (){
+                  isVisible = false;
+                  viewModel?.submitEstate();
+                },
+                text: S.current.next,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                fontWeight: FontWeight.w500,
+                type: ClickType.throttle,
+                fontSize: 16,
+                minHeight: 50,
+                radius: 5,
+              ).marginOnly(top: 50, bottom: 50),
+            ],
+          ),
         ),
       ),
     );
   }
 
-  /// 输入框
-  Widget _buildInputLayout(
-    BuildContext context,
-    SelectEstateState state,
-    String formKey, {
-    Key? 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(
-        formKey,
-        key: key,
-        fillBackgroundColor: context.appColors.authFiledBG,
-        state.formData[formKey]!['value'],
-        hintText: state.formData[formKey]!['hintText'],
-        hintStyle: TextStyle(
-          color: context.appColors.authFiledHint,
-          fontSize: 16.0,
-          fontWeight: FontWeight.w500,
-        ),
-        controller: state.formData[formKey]!['controller'],
-        focusNode: state.formData[formKey]!['focusNode'],
-        margin: EdgeInsets.only(top: marginTop),
-        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
-        showDivider: false,
-        height: 44,
-        style: TextStyle(
-          color: context.appColors.authFiledText,
-          fontSize: 16.0,
-          fontWeight: FontWeight.w500,
-        ),
-        inputType: textInputType,
-        textInputAction: textInputAction,
-        onSubmit: onSubmit,
-        cursorColor: context.appColors.authFiledText,
-        obscureText: obscureText,
-        errorText: errorText,
-        showLeftIcon: true,
-        showRightIcon: showRightIcon,
-        rightWidget: rightWidget,
-      ),
-    );
+  @override
+  void didChangeMetrics() {
+    //页面不可见时不走逻辑
+    if (!isVisible) return;
+
+    // 当键盘弹出或收起时,这里会被调用
+    final currentInsets = WidgetsBinding.instance.window.viewInsets;
+
+    if (currentInsets.bottom > 0 && _previousBottom == 0) {
+      //键盘已弹出
+      _isKeyboardVisible = true;
+    } else if (currentInsets.bottom == 0 && _previousBottom > 0) {
+      //键盘已收起
+      _isKeyboardVisible = false;
+
+      //软键盘收起的时候,重新布局Attach下拉选弹窗
+      throttledShowDropDownDialog?.call();
+    }
+
+    // 更新上一个 Insets
+    _previousBottom = currentInsets.bottom;
+  }
+
+  //防抖 throttle 函数
+  Function throttle(void Function() callback, [int milliseconds = 500]) {
+    bool _isAllowed = true;
+    Timer? _throttleTimer;
+    return () {
+      if (!_isAllowed) return;
+      _isAllowed = false;
+      callback();
+      _throttleTimer?.cancel();
+      _throttleTimer = Timer(Duration(milliseconds: milliseconds), () {
+        _isAllowed = true;
+      });
+    };
   }
 }

+ 29 - 3
packages/cpt_auth/lib/modules/select_estate/select_estate_state.dart

@@ -1,16 +1,30 @@
 import 'package:cs_resources/generated/l10n.dart';
+import 'package:domain/entity/id_name_entity.dart';
 import 'package:flutter/material.dart';
 
 class SelectEstateState {
   //表单的校验与数据
   final Map<String, Map<String, dynamic>> formData;
 
-  double remainingSpace;
+  List<IdNameEntity>? estateList;  //第一步的下拉选房产数据源
+
+  IdNameEntity? selectedEstate; //第一步数据:已经选中的房产
+
+  String? block; //第二步数据:已经选中的Block
+  String? unit; //第二步数据:已经选中的单元
+  String? room; //第二步数据:已经选中的单元-房间
+
+  String? type; //第三步数据:已经选中的类型
 
   // ===================================  Begin  ↓  ===================================
 
   SelectEstateState({
-    this.remainingSpace = 0,
+    this.estateList,
+    this.selectedEstate,
+    this.block,
+    this.unit,
+    this.room,
+    this.type,
     Map<String, Map<String, dynamic>>? formData,
   }) : formData = formData ??
             {
@@ -25,9 +39,21 @@ class SelectEstateState {
 
   SelectEstateState copyWith({
     double? remainingSpace,
+    List<IdNameEntity>? estateList,
+    IdNameEntity? selectedEstate,
+    String? block,
+    String? unit,
+    String? room,
+    String? type,
   }) {
     return SelectEstateState(
-      remainingSpace: remainingSpace ?? this.remainingSpace,
+      estateList: estateList ?? this.estateList,
+      selectedEstate: selectedEstate ?? this.selectedEstate,
+      block: block ?? this.block,
+      unit: unit ?? this.unit,
+      room: room ?? this.room,
+      type: type ?? this.type,
+      formData: this.formData,
     );
   }
 }

+ 74 - 4
packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.dart

@@ -1,21 +1,91 @@
-
 import 'package:cpt_auth/modules/select_estate/select_estate_state.dart';
 import 'package:cpt_auth/modules/select_unit/select_unit_page.dart';
+import 'package:domain/entity/id_name_entity.dart';
+import 'package:domain/repository/profile_repository.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import 'dialog/attach_search_dialog.dart';
 
 part 'select_estate_view_model.g.dart';
 
 @riverpod
-class SelectEstateViewModel extends _$SelectEstateViewModel {
+class SelectEstateViewModel extends _$SelectEstateViewModel with DioCancelableMixin {
+  late final ProfileRepository _profileRepository;
+  BuildContext? _targetContext;
 
   @override
-  SelectEstateState build(){
-    return SelectEstateState();
+  SelectEstateState build() {
+    _profileRepository = ref.read(profileRepositoryProvider);
+    final state = SelectEstateState();
+    registerCancellation();
+    return state;
   }
 
   /// 提交并进入下一步
   void submitEstate() {
+    if (state.selectedEstate == null) {
+      ToastEngine.show("Select Estate First");
+      return;
+    }
+
     SelectUnitPage.startInstance();
   }
 
+  /// 关键字搜索房产
+  void searchEstate(BuildContext targetContext, String? keyword) async {
+    _targetContext = targetContext;
+    final result = await _profileRepository.searchEstate(keyword: keyword, cancelToken: cancelToken);
+
+    if (result.isSuccess) {
+      final list = result.list;
+
+      if (list != null && list.isNotEmpty) {
+        state = state.copyWith(estateList: list);
+        //尝试展示下拉选选项
+        showDropDownDialog();
+      }
+    } else {
+      Log.e(result.errorMsg ?? "UnKnow Error");
+    }
+  }
+
+  //Attach下拉选
+  void showDropDownDialog({bool needReLocation = false}) {
+    if (_targetContext == null) return;
+    if (state.estateList == null || state.estateList!.isEmpty) return;
+
+    if (needReLocation) {
+      Log.d("需要重新定位弹出");
+      DialogEngine.dismiss(tag: 'estate');
+    }
+    if (!DialogEngine.checkIsExist(tag: 'estate') || needReLocation) {
+      DialogEngine.showAttach(
+        tag: 'estate',
+        targetContext: _targetContext!,
+        position: DialogPosition.bottom,
+        widget: AttachSearchDialog(
+          onSelected: (item) {
+            state = state.copyWith(selectedEstate: item);
+            final TextEditingController controller = state.formData['estate']!['controller'];
+            controller.text = item?.name ?? "";
+          },
+        ),
+      );
+    }
+  }
+
+  /// 保存第二步的单元等信息
+  void saveUnit({required String block, required String unit, required String room}) {
+    state = state.copyWith(block: block, unit: unit, room: room);
+  }
+
+  /// 保存第三步的角色信息
+  void saveRoleType({required String type}) {
+    state = state.copyWith(type: type);
+  }
 }

+ 1 - 1
packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'select_estate_view_model.dart';
 // **************************************************************************
 
 String _$selectEstateViewModelHash() =>
-    r'5f5009ecf893acd0a8814a57432abeab66b05325';
+    r'aba0d6d52228a8b0cdfb7fb1e4fb1009fb33df94';
 
 /// See also [SelectEstateViewModel].
 @ProviderFor(SelectEstateViewModel)

+ 7 - 0
packages/cpt_auth/lib/modules/select_role/select_role_view_model.dart

@@ -2,17 +2,24 @@ import 'package:cpt_auth/modules/select_role/select_role_state.dart';
 import 'package:cpt_auth/modules/tenant_doc/tenant_doc_page.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 
+import '../select_estate/select_estate_state.dart';
+import '../select_estate/select_estate_view_model.dart';
+
 part 'select_role_view_model.g.dart';
 
 @riverpod
 class SelectRoleViewModel extends _$SelectRoleViewModel {
+  late final SelectEstateViewModel _selectEstateViewModel;
+
   @override
   SelectRoleState build() {
+    _selectEstateViewModel = ref.watch(selectEstateViewModelProvider.notifier);
     return SelectRoleState();
   }
 
   //进入下一步
   void submitRole() {
+    _selectEstateViewModel.saveRoleType(type: "${state.selectedIndex + 1}");
     TenantDocPage.startInstance();
   }
 

+ 1 - 1
packages/cpt_auth/lib/modules/select_role/select_role_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'select_role_view_model.dart';
 // **************************************************************************
 
 String _$selectRoleViewModelHash() =>
-    r'a42d4ba4dd03754e74e58b1a320793449326bef4';
+    r'dcf0c9060d9661a5428df0fa2136cc138dc6050d';
 
 /// See also [SelectRoleViewModel].
 @ProviderFor(SelectRoleViewModel)

+ 9 - 5
packages/cpt_auth/lib/modules/select_unit/select_unit_page.dart

@@ -1,6 +1,7 @@
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/id_name_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
@@ -21,14 +22,15 @@ import 'select_unit_view_model.dart';
 
 @RoutePage()
 class SelectUnitPage extends HookConsumerWidget {
-  SelectUnitPage({Key? key}) : super(key: key);
+
+  const SelectUnitPage({Key? key,}) : super(key: key);
 
   //启动当前页面
   static void startInstance({BuildContext? context}) {
     if (context != null) {
-      context.router.push(SelectUnitPageRoute());
+      context.router.push(const SelectUnitPageRoute());
     } else {
-      appRouter.push(SelectUnitPageRoute());
+      appRouter.push(const SelectUnitPageRoute());
     }
   }
 
@@ -80,6 +82,7 @@ class SelectUnitPage extends HookConsumerWidget {
                               context,
                               state,
                               "block",
+                              textInputType: TextInputType.text,
                               textInputAction: TextInputAction.next,
                               onSubmit: (formKey, value) {
                                 state.formData[formKey]!['focusNode'].unfocus();
@@ -177,9 +180,10 @@ class SelectUnitPage extends HookConsumerWidget {
                     ),
                   ],
                 )).expanded(),
-
             MyButton(
-              onPressed: viewModel.submitUnit,
+              onPressed: (){
+                viewModel.submitUnit();
+              },
               text: S.current.next,
               textColor: Colors.white,
               backgroundColor: context.appColors.btnBgDefault,

+ 0 - 12
packages/cpt_auth/lib/modules/select_unit/select_unit_state.dart

@@ -4,12 +4,9 @@ class SelectUnitState {
   //表单的校验与数据
   final Map<String, Map<String, dynamic>> formData;
 
-  double remainingSpace;
-
   // ===================================  Begin  ↓  ===================================
 
   SelectUnitState({
-    this.remainingSpace = 0,
     Map<String, Map<String, dynamic>>? formData,
   }) : formData = formData ??
             {
@@ -35,13 +32,4 @@ class SelectUnitState {
                 'obsecure': false,
               },
             };
-
-  SelectUnitState copyWith({
-    double? remainingSpace,
-  }) {
-    return SelectUnitState(
-      remainingSpace: remainingSpace ?? this.remainingSpace,
-    );
-  }
-
 }

+ 60 - 5
packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.dart

@@ -1,20 +1,75 @@
+import 'package:cpt_auth/modules/select_estate/select_estate_view_model.dart';
 import 'package:cpt_auth/modules/select_role/select_role_page.dart';
 import 'package:cpt_auth/modules/select_unit/select_unit_state.dart';
+import 'package:domain/repository/profile_repository.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/util.dart';
+
+import '../select_estate/select_estate_state.dart';
 
 part 'select_unit_view_model.g.dart';
 
 @riverpod
-class SelectUnitViewModel extends _$SelectUnitViewModel {
+class SelectUnitViewModel extends _$SelectUnitViewModel with DioCancelableMixin {
+  late final ProfileRepository _profileRepository;
+  late final SelectEstateViewModel _selectEstateViewModel;
+  late final SelectEstateState _selectEstateState;
 
   @override
   SelectUnitState build() {
-    return SelectUnitState();
+    _profileRepository = ref.read(profileRepositoryProvider);
+    _selectEstateViewModel = ref.watch(selectEstateViewModelProvider.notifier);
+    _selectEstateState = ref.watch(selectEstateViewModelProvider);
+
+    final state = SelectUnitState();
+    registerCancellation();
+    return state;
   }
 
   /// 提交选择的街道与单元
-  void submitUnit() {
-    SelectRolePage.startInstance();
-  }
+  void submitUnit() async {
+    final FocusNode blockFocusNode = state.formData['block']!['focusNode'];
+    final FocusNode unitFocusNode = state.formData['unit']!['focusNode'];
+    final FocusNode roomFocusNode = state.formData['room']!['focusNode'];
+
+    blockFocusNode.unfocus();
+    unitFocusNode.unfocus();
+    roomFocusNode.unfocus();
+
+    final TextEditingController blockController = state.formData['block']!['controller'];
+    final TextEditingController unitController = state.formData['unit']!['controller'];
+    final TextEditingController roomController = state.formData['room']!['controller'];
+
+    final block = blockController.text;
+    final unit = unitController.text;
+    final room = roomController.text;
 
+    if (Utils.isEmpty(block)) {
+      ToastEngine.show("Block cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(unit)) {
+      ToastEngine.show("Unit Number cannot be empty!");
+      return;
+    }
+
+    if (Utils.isEmpty(room)) {
+      ToastEngine.show("Unit Number cannot be empty!");
+      return;
+    }
+
+    final result = await _profileRepository.estateJoinCheck(estateId: _selectEstateState.selectedEstate?.id, block: block, unit: "$unit-$room");
+
+    if (result.isSuccess) {
+      //存入内存数据
+      _selectEstateViewModel.saveUnit(block: block, unit: unit, room: room);
+      SelectRolePage.startInstance();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "UnKnow Error");
+    }
+  }
 }

+ 1 - 1
packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'select_unit_view_model.dart';
 // **************************************************************************
 
 String _$selectUnitViewModelHash() =>
-    r'f4f8001a0fa6e406b06fe7a8ecaba8e6309e21c5';
+    r'04669c8553c295069d6cc1fb0f7e771cbbc72672';
 
 /// See also [SelectUnitViewModel].
 @ProviderFor(SelectUnitViewModel)

+ 0 - 2
packages/cpt_auth/lib/modules/sign_up/sign_up_view_model.dart

@@ -120,10 +120,8 @@ class SignUpViewModel extends _$SignUpViewModel {
       ),
     );
 
-
   }
 
-
   //切换隐藏显示密码
   void switchPwdVisibility() {
     state = state.copyWith(pwdVisibility: !state.pwdVisibility);

+ 7 - 6
packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_page.dart

@@ -19,12 +19,13 @@ class SignUpSuccessPage extends HookConsumerWidget {
   const SignUpSuccessPage({Key? key}) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context}) {
-    if (context != null) {
-      context.router.popAndPush(const SignUpSuccessPageRoute());
-    } else {
-      appRouter.popAndPush(const SignUpSuccessPageRoute());
-    }
+  static void startInstance() {
+    appRouter.pushAndPopUntil(
+      const SignUpSuccessPageRoute(),
+      predicate: (route) {
+        return route.settings.name == AuthLoginPageRoute.name;
+      },
+    );
   }
 
   @override

+ 0 - 1
packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_view_model.dart

@@ -1,4 +1,3 @@
-import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 
 import '../select_estate/select_estate_page.dart';

+ 1 - 15
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_page.dart

@@ -60,22 +60,8 @@ class TenantDocPage extends HookConsumerWidget {
                       textColor: context.appColors.textBlack,
                     ),
                     MyTextView(
-                      S.current.upload_doc_desc,
+                      state.type == "1" ? S.current.upload_doc_owner_desc : S.current.upload_doc_tenant_desc,
                       fontSize: 15,
-                      isFontMedium: true,
-                      textColor: context.appColors.textBlack,
-                    ),
-                    MyTextView(
-                      S.current.upload_doc_desc1,
-                      fontSize: 15,
-                      marginTop: 22,
-                      isFontMedium: true,
-                      textColor: context.appColors.textBlack,
-                    ),
-                    MyTextView(
-                      S.current.upload_doc_desc2,
-                      fontSize: 15,
-                      marginTop: 22,
                       marginBottom: 24,
                       isFontMedium: true,
                       textColor: context.appColors.textBlack,

+ 4 - 6
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_state.dart

@@ -1,22 +1,20 @@
 class TenantDocState {
-
   final List<String> docList;
 
-  final double remainingSpace;
+  final String type;
 
   const TenantDocState({
     required this.docList,
-    this.remainingSpace = 0,
+    required this.type,
   });
 
   TenantDocState copyWith({
     List<String>? docList,
-    double? remainingSpace,
+    String? type,
   }) {
     return TenantDocState(
       docList: docList ?? this.docList,
-      remainingSpace: remainingSpace ?? this.remainingSpace,
+      type: type ?? this.type,
     );
   }
-
 }

+ 48 - 7
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.dart

@@ -1,28 +1,69 @@
-
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:domain/repository/profile_repository.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:router/componentRouter/component_service_manager.dart';
+import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
 
+import '../estate_upload_success/estate_upload_success_page.dart';
+import '../select_estate/select_estate_state.dart';
+import '../select_estate/select_estate_view_model.dart';
 import 'tenant_doc_state.dart';
 
 part 'tenant_doc_view_model.g.dart';
 
 @riverpod
 class TenantDocViewModel extends _$TenantDocViewModel {
+  late final ProfileRepository _profileRepository;
+  late final SelectEstateState _selectEstateState;
 
   @override
-  TenantDocState build(){
-    return const TenantDocState(docList: []);
+  TenantDocState build() {
+    _profileRepository = ref.read(profileRepositoryProvider);
+    _selectEstateState = ref.watch(selectEstateViewModelProvider);
+
+    return TenantDocState(docList: [], type: _selectEstateState.type ?? "1");
   }
 
   //设置已选中的文件数组
-  void setDocList(List<String> list){
+  void setDocList(List<String> list) {
     state = state.copyWith(docList: list);
   }
 
   //提交文件
-  void submitDoc() {
-    ToastEngine.show("请求接口上传文件:${state.docList}");
-  }
+  void submitDoc() async {
+    if (state.docList.isEmpty) {
+      ToastEngine.show("Select Documents First");
+      return;
+    }
 
+    final result = await _profileRepository.joinEstateUnit(
+      estateId: _selectEstateState.selectedEstate?.id,
+      block: _selectEstateState.block,
+      unit: "${_selectEstateState.unit}-${_selectEstateState.room}",
+      type: _selectEstateState.type,
+      paths: state.docList,
+    );
 
+    if (result.isSuccess) {
+      //如果有用户信息,说明是在Me页面添加的
+      if (UserConfigService.getState().user != null) {
+        //刷新Estate页面
+        bus.emit(AppConstant.eventEstateRefresh, true);
+        //去成功页面
+        Log.d("Estate页面");
+        EstateUploadSuccessPage.startPop2Estate();
+      } else {
+        Log.d("登录页面");
+        //如果没有用户信息,说明是在登录页面添加的。
+        EstateUploadSuccessPage.startPop2Login();
+      }
+    } else {
+      ToastEngine.show(result.errorMsg ?? "UnKnow Error");
+    }
+  }
 }

+ 1 - 1
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'tenant_doc_view_model.dart';
 // **************************************************************************
 
 String _$tenantDocViewModelHash() =>
-    r'8283e1970743d66a871e1145e15ffd3177d3a42b';
+    r'92e8fc2e3d5b1e9f7a709ca06a17adb6a28c76ff';
 
 /// See also [TenantDocViewModel].
 @ProviderFor(TenantDocViewModel)

+ 3 - 0
packages/cpt_auth/lib/router/page/auth_page_router.dart

@@ -1,4 +1,5 @@
 import 'package:auto_route/auto_route.dart';
+import 'package:domain/entity/id_name_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:router/path/router_path.dart';
@@ -13,6 +14,7 @@ import '../../modules/select_estate/select_estate_page.dart';
 import '../../modules/select_unit/select_unit_page.dart';
 import '../../modules/select_role/select_role_page.dart';
 import '../../modules/tenant_doc/tenant_doc_page.dart';
+import '../../modules/estate_upload_success/estate_upload_success_page.dart';
 
 
 
@@ -35,5 +37,6 @@ class AuthPageRouter extends _$AuthPageRouter {
     CustomRoute(page: SelectUnitPageRoute.page, path: RouterPath.authSelectUnit, transitionsBuilder: applySlideTransition),
     CustomRoute(page: SelectRolePageRoute.page, path: RouterPath.authSelectRole, transitionsBuilder: applySlideTransition),
     CustomRoute(page: TenantDocPageRoute.page, path: RouterPath.authTenantDoc, transitionsBuilder: applySlideTransition),
+    CustomRoute(page: EstateUploadSuccessPageRoute.page, path: RouterPath.authEstateUploadSuccess, transitionsBuilder: applySlideTransition),
   ];
 }

+ 25 - 22
packages/cpt_auth/lib/router/page/auth_page_router.gr.dart

@@ -21,6 +21,12 @@ abstract class _$AuthPageRouter extends RootStackRouter {
         child: const AuthLoginPage(),
       );
     },
+    EstateUploadSuccessPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const EstateUploadSuccessPage(),
+      );
+    },
     ForgotInputPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
@@ -52,11 +58,9 @@ abstract class _$AuthPageRouter extends RootStackRouter {
       );
     },
     SelectUnitPageRoute.name: (routeData) {
-      final args = routeData.argsAs<SelectUnitPageRouteArgs>(
-          orElse: () => const SelectUnitPageRouteArgs());
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: SelectUnitPage(key: args.key),
+        child: const SelectUnitPage(),
       );
     },
     SignUpPageRoute.name: (routeData) {
@@ -114,6 +118,20 @@ class AuthLoginPageRoute extends PageRouteInfo<void> {
 }
 
 /// generated route for
+/// [EstateUploadSuccessPage]
+class EstateUploadSuccessPageRoute extends PageRouteInfo<void> {
+  const EstateUploadSuccessPageRoute({List<PageRouteInfo>? children})
+      : super(
+          EstateUploadSuccessPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'EstateUploadSuccessPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
 /// [ForgotInputPage]
 class ForgotInputPageRoute extends PageRouteInfo<void> {
   const ForgotInputPageRoute({List<PageRouteInfo>? children})
@@ -210,31 +228,16 @@ class SelectRolePageRoute extends PageRouteInfo<void> {
 
 /// generated route for
 /// [SelectUnitPage]
-class SelectUnitPageRoute extends PageRouteInfo<SelectUnitPageRouteArgs> {
-  SelectUnitPageRoute({
-    Key? key,
-    List<PageRouteInfo>? children,
-  }) : super(
+class SelectUnitPageRoute extends PageRouteInfo<void> {
+  const SelectUnitPageRoute({List<PageRouteInfo>? children})
+      : super(
           SelectUnitPageRoute.name,
-          args: SelectUnitPageRouteArgs(key: key),
           initialChildren: children,
         );
 
   static const String name = 'SelectUnitPageRoute';
 
-  static const PageInfo<SelectUnitPageRouteArgs> page =
-      PageInfo<SelectUnitPageRouteArgs>(name);
-}
-
-class SelectUnitPageRouteArgs {
-  const SelectUnitPageRouteArgs({this.key});
-
-  final Key? key;
-
-  @override
-  String toString() {
-    return 'SelectUnitPageRouteArgs{key: $key}';
-  }
+  static const PageInfo<void> page = PageInfo<void>(name);
 }
 
 /// generated route for

+ 72 - 61
packages/cpt_main/lib/modules/me/me_page.dart

@@ -11,6 +11,7 @@ import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 import 'package:widgets/shatter/setting_item_container.dart';
+import 'package:widgets/widget_export.dart';
 
 import 'me_view_model.dart';
 
@@ -23,6 +24,10 @@ class MePage extends HookConsumerWidget {
     final viewModel = ref.watch(meViewModelProvider.notifier);
     final userConfig = UserConfigService.getState(ref: ref);
 
+    String totalAccountsCount = userConfig.user?.estates?.fold(0, (sum, estate) {
+      return sum + (estate.accounts?.length ?? 0);
+    }).toString() ?? "0";
+
     return Scaffold(
       appBar: MyAppBar.appBar(
         context,
@@ -34,67 +39,73 @@ class MePage extends HookConsumerWidget {
             : ThemeConfig.systemUiOverlayStyleLightThemeWhite,
       ),
       backgroundColor: context.appColors.backgroundDark,
-      body: SingleChildScrollView(
-        scrollDirection: Axis.vertical,
-        physics: const BouncingScrollPhysics(),
-        child: SizedBox(
-          width: double.infinity,
-          child: Column(
-            mainAxisSize: MainAxisSize.max,
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              //顶部信息
-              _buildTopProfile(context, ref),
-
-              //关注与粉丝
-              _buildFollower(context, ref),
-
-              //我的发布
-              SettingItemContainer(
-                title: S.current.my_post,
-                iconPath: Assets.mainMeMyPostIcon,
-                isShowMoreIcon: true,
-                rightWidget: MyTextView(
-                  userConfig.user?.postsCount ?? "0",
-                  textColor: context.appColors.textPrimary,
-                  fontSize: 20,
-                  isFontMedium: true,
-                ),
-              ).onTap(viewModel.gotoMyPostPage).marginOnly(top: 10),
-
-              //家庭
-              SettingItemContainer(
-                title: S.current.household,
-                iconPath: Assets.mainMeHouseholdIcon,
-                isShowMoreIcon: true,
-                rightWidget: MyTextView(
-                  userConfig.user?.households?.length.toString() ?? "0",
-                  textColor: context.appColors.textPrimary,
-                  fontSize: 20,
-                  isFontMedium: true,
-                ),
-              ).onTap(viewModel.gotoMyHouseholdPage),
-
-              //房产
-              SettingItemContainer(
-                title: S.current.estate,
-                iconPath: Assets.mainMeEstateIcon,
-                isShowMoreIcon: true,
-                rightWidget: MyTextView(
-                  userConfig.user?.estates?.length.toString() ?? "0",
-                  textColor: context.appColors.textPrimary,
-                  fontSize: 20,
-                  isFontMedium: true,
-                ),
-              ).onTap(viewModel.gotoMyEstatePage),
-
-              //设置
-              SettingItemContainer(
-                title: S.current.settings,
-                iconPath: Assets.mainMeSettingIcon,
-                isShowMoreIcon: true,
-              ).onTap(viewModel.gotoSettingPage),
-            ],
+      body: EasyRefresh(
+        controller: viewModel.refreshController,
+        header: const MaterialHeader(),
+        onRefresh: viewModel.onRefresh,
+        child: SingleChildScrollView(
+          scrollDirection: Axis.vertical,
+          child: SizedBox(
+            width: double.infinity,
+            child: Column(
+              mainAxisSize: MainAxisSize.max,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                //顶部信息
+                _buildTopProfile(context, ref),
+
+                //关注与粉丝
+                _buildFollower(context, ref),
+
+                //我的发布
+                SettingItemContainer(
+                  title: S.current.my_post,
+                  iconPath: Assets.mainMeMyPostIcon,
+                  isShowMoreIcon: true,
+                  rightWidget: MyTextView(
+                    userConfig.user?.postsCount ?? "0",
+                    textColor: context.appColors.textPrimary,
+                    fontSize: 20,
+                    isFontMedium: true,
+                  ),
+                ).onTap(viewModel.gotoMyPostPage).marginOnly(top: 10),
+
+                //家庭
+                SettingItemContainer(
+                  title: S.current.household,
+                  iconPath: Assets.mainMeHouseholdIcon,
+                  isShowMoreIcon: true,
+                  rightWidget: MyTextView(
+                    userConfig.user?.households?.length.toString() ?? "0",
+                    textColor: context.appColors.textPrimary,
+                    fontSize: 20,
+                    isFontMedium: true,
+                  ),
+                ).onTap(viewModel.gotoMyHouseholdPage),
+
+                //房产
+                SettingItemContainer(
+                  title: S.current.estate,
+                  iconPath: Assets.mainMeEstateIcon,
+                  isShowMoreIcon: true,
+                  rightWidget: MyTextView(
+                    userConfig.user?.estates?.fold(0, (sum, estate) {
+                      return sum + (estate.accounts?.length ?? 0);
+                    }).toString() ?? "0",
+                    textColor: context.appColors.textPrimary,
+                    fontSize: 20,
+                    isFontMedium: true,
+                  ),
+                ).onTap(viewModel.gotoMyEstatePage),
+
+                //设置
+                SettingItemContainer(
+                  title: S.current.settings,
+                  iconPath: Assets.mainMeSettingIcon,
+                  isShowMoreIcon: true,
+                ).onTap(viewModel.gotoSettingPage),
+              ],
+            ),
           ),
         ),
       ),

+ 27 - 2
packages/cpt_main/lib/modules/me/me_view_model.dart

@@ -1,13 +1,38 @@
+import 'package:domain/repository/profile_repository.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:router/componentRouter/component_service_manager.dart';
-
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/widget_export.dart';
 
 part 'me_view_model.g.dart';
 
 @riverpod
 class MeViewModel extends _$MeViewModel {
+  late final ProfileRepository _profileRepository;
+
   @override
-  void build() {}
+  void build() {
+    _profileRepository = ref.read(profileRepositoryProvider);
+  }
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: false, //允许加载
+  );
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    final result = await _profileRepository.fetchUserInfo();
+    if (result.isSuccess) {
+      UserConfigService.getInstance().setUserInfo(result.data);
+    } else {
+      Log.e(result.errorMsg ?? "UnKnow Error");
+    }
+
+    refreshController.finishRefresh();
+  }
 
   //去我的房产页面
   void gotoMyEstatePage() {

+ 0 - 6
packages/cpt_profile/lib/modules/my_estate/estate_group_data.dart

@@ -1,6 +0,0 @@
-
-//对应分组的数据,需要在ViewModel中处理每一个组的数据
-class EstateGroupData{
-  String? groupId;
-  List<String>? groupDatas=[];
-}

+ 12 - 10
packages/cpt_profile/lib/modules/my_estate/item_estate.dart

@@ -1,6 +1,7 @@
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/user_me_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_load_image.dart';
@@ -8,13 +9,15 @@ import 'package:widgets/my_text_view.dart';
 
 class EstateItem extends StatelessWidget {
   final int childIndex; //组内的索引
-  final String item;
+  final UserMeEstatesAccounts item;
   final VoidCallback deleteAction;
+  final VoidCallback itemAction;
 
   const EstateItem({
     required this.childIndex,
     required this.item,
     required this.deleteAction,
+    required this.itemAction,
   });
 
   @override
@@ -31,7 +34,7 @@ class EstateItem extends StatelessWidget {
               Row(
                 children: [
                   MyLoadImage(
-                    "https://img1.baidu.com/it/u=1656098746,3560654086&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=800",
+                    item.avatar,
                     width: 65,
                     height: 65,
                     isCircle: true,
@@ -45,7 +48,7 @@ class EstateItem extends StatelessWidget {
                       const SizedBox(height: 22.5),
                       //姓名
                       MyTextView(
-                        "Wu Bing Bing",
+                        item.name ?? "-",
                         fontSize: 16,
                         isFontBold: true,
                         textColor: context.appColors.textBlack,
@@ -53,14 +56,14 @@ class EstateItem extends StatelessWidget {
                       ),
 
                       MyTextView(
-                        "Owner",
+                        item.type == "1" ? S.current.owner : S.current.tenant,
                         fontSize: 15,
                         isFontRegular: true,
                         textColor: context.appColors.textBlack,
                       ),
 
                       MyTextView(
-                        "Block 35 #08-29",
+                        item.unit?.address ?? "-",
                         fontSize: 15,
                         isFontRegular: true,
                         textColor: context.appColors.textBlack,
@@ -80,23 +83,22 @@ class EstateItem extends StatelessWidget {
                   paddingTop: 16,
                   paddingBottom: 16,
                   fontSize: 16,
+                  onClick: deleteAction,
                   isFontMedium: true,
                   textColor: context.appColors.textPrimary,
                 ),
               )
             ],
           ),
-        ),
-
+        ).onTap(itemAction),
         Visibility(
-          visible: true,
-          child: MyAssetImage(
+          visible: item.isDefault == 1,
+          child: const MyAssetImage(
             Assets.profileMyEstateDefault,
             width: 76,
             height: 44,
           ),
         ).marginOnly(top: childIndex == 0 ? 0 : 10).alignRight(),
-
         MyTextView(
           S.current.approved,
           fontSize: 16,

+ 10 - 7
packages/cpt_profile/lib/modules/my_estate/my_estate_page.dart

@@ -1,6 +1,7 @@
 import 'package:cpt_profile/modules/change_mobile/change_mobile_page.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/user_me_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
@@ -24,9 +25,9 @@ class MyEstatePage extends HookConsumerWidget {
   //启动当前页面
   static void startInstance({BuildContext? context}) {
     if (context != null) {
-      context.router.push(const MyEstatePageRoute());
+      context.router.navigate(const MyEstatePageRoute());
     } else {
-      appRouter.push(const MyEstatePageRoute());
+      appRouter.navigate(const MyEstatePageRoute());
     }
   }
 
@@ -56,7 +57,6 @@ class MyEstatePage extends HookConsumerWidget {
           EasyRefresh(
             controller: viewModel.refreshController,
             onRefresh: viewModel.onRefresh,
-            onLoad: viewModel.loadMore,
             child: LoadStateLayout(
               state: state.loadingState,
               errorMessage: state.errorMessage,
@@ -68,9 +68,9 @@ class MyEstatePage extends HookConsumerWidget {
                     delegate: SliverChildBuilderDelegate(
                   (context, index) {
                     return StickyHeader(
-                      header: EstateItemHeader(state.datas[index].groupId),
+                      header: EstateItemHeader(state.datas[index].name),
                       content: Column(
-                        children: _buildGroup(state.datas[index].groupDatas!, index,viewModel),
+                        children: _buildGroup(state.datas[index].accounts!, index,viewModel),
                       ),
                     );
                   },
@@ -98,7 +98,7 @@ class MyEstatePage extends HookConsumerWidget {
   }
 
   //当前组内的子数据
-  List<Widget> _buildGroup(List<String> list, int index, MyEstateViewModel viewModel) {
+  List<Widget> _buildGroup(List<UserMeEstatesAccounts> list, int index, MyEstateViewModel viewModel) {
     return list
         .asMap()
         .map((childIndex, item) {
@@ -107,8 +107,11 @@ class MyEstatePage extends HookConsumerWidget {
               EstateItem(
                 item: item,
                 childIndex: childIndex,
+                itemAction: (){
+                  viewModel.setEstateUnitDefault(item);
+                },
                 deleteAction: () {
-                  viewModel.showRemoveEstateDialog();
+                  viewModel.showRemoveEstateDialog(item.unit?.id);
                 },
               ));
         })

+ 3 - 3
packages/cpt_profile/lib/modules/my_estate/my_estate_state.dart

@@ -1,5 +1,5 @@
+import 'package:domain/entity/user_me_entity.dart';
 import 'package:widgets/load_state_layout.dart';
-import 'estate_group_data.dart';
 
 class MyEstateState{
 
@@ -7,7 +7,7 @@ class MyEstateState{
   LoadState loadingState;
   String? errorMessage;
 
-  List<EstateGroupData> datas; //页面列表数据
+  List<UserMeEstates> datas; //页面列表数据
 
   // ===================================  Begin  ↓  ===================================
 
@@ -21,7 +21,7 @@ class MyEstateState{
     LoadState? loadingState,
     String? errorMessage,
     bool? needShowPlaceholder,
-    List<EstateGroupData>? datas,
+    List<UserMeEstates>? datas,
   }) {
     return MyEstateState(
       errorMessage: errorMessage ?? this.errorMessage,

+ 103 - 97
packages/cpt_profile/lib/modules/my_estate/my_estate_view_model.dart

@@ -1,8 +1,16 @@
 import 'package:cpt_profile/modules/my_estate/dialog/remove_account_dialog.dart';
-import 'package:cpt_profile/modules/my_estate/estate_group_data.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:domain/entity/user_me_entity.dart';
+import 'package:domain/repository/profile_repository.dart';
+import 'package:plugin_basic/constants/app_constant.dart';
+import 'package:plugin_basic/provider/user_config/user_config_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:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/event_bus.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
@@ -11,19 +19,27 @@ import 'my_estate_state.dart';
 part 'my_estate_view_model.g.dart';
 
 @riverpod
-class MyEstateViewModel extends _$MyEstateViewModel {
+class MyEstateViewModel extends _$MyEstateViewModel with DioCancelableMixin {
+  late final ProfileRepository _profileRepository;
+
   @override
   MyEstateState build() {
-    return MyEstateState(datas: []);
+    _profileRepository = ref.read(profileRepositoryProvider);
+    final state = MyEstateState(datas: []);
+
+    onInit();
+    registerCancellation(callback: () {
+      unregisterEventBus();
+    });
+    return state;
   }
 
-  var _curPage = 1; //请求参数当前的页面
   var _needShowPlaceholder = true; //是否展示LoadingView
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
     controlFinishRefresh: true, //允许刷新
-    controlFinishLoad: true, //允许加载
+    controlFinishLoad: false, //允许加载
   );
 
   //刷新页面状态
@@ -33,19 +49,11 @@ class MyEstateViewModel extends _$MyEstateViewModel {
 
   // Refresh 刷新事件
   Future onRefresh() async {
-    _curPage = 1;
-    fetchList();
-  }
-
-  // Refresh 加载事件
-  Future loadMore() async {
-    _curPage++;
     fetchList();
   }
 
   // 重试请求
   Future retryRequest() async {
-    _curPage = 1;
     _needShowPlaceholder = true;
     fetchList();
   }
@@ -57,106 +65,104 @@ class MyEstateViewModel extends _$MyEstateViewModel {
     }
 
     // 获取 Applied 列表
-    // var listResult = await _jobRepository.fetchJobAppliedList(
-    //   state.jobId,
-    //   state.selectedStatusId,
-    //   state.keyword,
-    //   curPage: _curPage,
-    //   cancelToken: cancelToken,
-    // );
-    //
-    // // 处理数据
-    // if (listResult.isSuccess) {
-    //   handleList(listResult.data?.rows);
-    // } else {
-    //   errorMessage = listResult.errorMsg;
-    //   changeLoadingState(LoadState.State_Error);
-    // }
-
-    await Future.delayed(const Duration(milliseconds: 1500));
-
-    List<EstateGroupData> list = [];
-    if (_curPage > 1) {
-
-      //这里只加载一页吧
+    var result = await _profileRepository.fetchUserInfo(
+      cancelToken: cancelToken,
+    );
+
+    // 处理数据
+    if (result.isSuccess) {
+      handleList(result.data?.estates);
     } else {
+      changeLoadingState(LoadState.State_Error, result.errorMsg);
+    }
 
-      list.add(EstateGroupData()
-        ..groupId = "Parc Life"
-        ..groupDatas = ["1", "2",]);
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
 
-      list.add(EstateGroupData()
-        ..groupId = "Little India"
-        ..groupDatas = ["1", "2",]);
+  // 处理数据与展示的逻辑
+  void handleList(List<UserMeEstates>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据
+      state = state.copyWith(datas: list, loadingState: LoadState.State_Success);
+    } else {
+      //展示无数据的布局
+      state = state.copyWith(datas: [], loadingState: LoadState.State_Empty, errorMessage: null);
+    }
 
-      list.add(EstateGroupData()
-        ..groupId = "Marina Bay Sands"
-        ..groupDatas = ["1"]);
+    refreshController.finishRefresh();
+  }
 
+  /// 展示移除账号的提示弹窗
+  void showRemoveEstateDialog(String? unitId) {
+    DialogEngine.show(widget: RemoveAccountDialog(
+      confirmAction: () {
+        _doDeleteEstateUnit(unitId);
+      },
+    ));
+  }
+
+  // 删除指定的单元
+  void _doDeleteEstateUnit(String? unitId) async {
+    final result = await _profileRepository.deleteEstateUnit(unitId: unitId, cancelToken: cancelToken);
+    if (result.isSuccess) {
+      refreshController.callRefresh();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "UnKnow Error");
     }
+  }
 
+  /// 设置默认的房产单元
+  void setEstateUnitDefault(UserMeEstatesAccounts? account) async {
+    if (account == null || account.isDefault == 1) {
+      //已经是默认的不需要操作了
+      return;
+    }
 
-    if (_curPage == 1) {
-      //刷新的方式
-      state = state.copyWith(datas: list);
-      refreshController.finishRefresh();
+    final unitId = account.unit?.id;
 
-      //更新展示的状态
-      changeLoadingState(LoadState.State_Success, null);
-    } else {
-      //加载更多
-      final allList = state.datas;
-      allList.addAll(list);
-      state.datas.addAll(list);
+    final result = await _profileRepository.setUnitAsDefault(unitId: unitId, cancelToken: cancelToken);
 
-      // refreshController.finishLoad();
-      refreshController.finishLoad(IndicatorResult.noMore);
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess(S.current.successful);
 
-      state = state.copyWith(datas: allList);
+      // 创建一个新的数据列表并更新 isDefault 状态
+      List<UserMeEstates> newDatas = state.datas.map((estate) {
+        var newEstate = estate.copyWith(
+          accounts: estate.accounts?.map((account) {
+            return account.copyWith(
+              isDefault: account.unit?.id == unitId ? 1 : 0,
+            );
+          }).toList(),
+        );
+        return newEstate;
+      }).toList();
+
+      //这里需要传入一个新对象啊,而不是上面的state.datas对象
+      state = state.copyWith(datas: newDatas);
+
+      //刷新用户的信息
+      UserConfigService.getInstance().refreshUserInfo();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "UnKnow Error");
     }
+  }
 
-    // 最后赋值
-    _needShowPlaceholder = false;
+  //初始化
+  void onInit() {
+    registerEventBus();
   }
 
-// 处理数据与展示的逻辑
-// void handleList(List<JobAppliedListSGRows>? list) {
-//   if (list != null && list.isNotEmpty) {
-//     //有数据,判断是刷新还是加载更多的数据
-//     if (_curPage == 1) {
-//       //刷新的方式
-//       state.datas.clear();
-//       state.datas.addAll(list);
-//       refreshController.finishRefresh();
-//
-//       //更新展示的状态
-//       changeLoadingState(LoadState.State_Success);
-//     } else {
-//       //加载更多
-//       state.datas.addAll(list);
-//       refreshController.finishLoad();
-//       update();
-//     }
-//   } else {
-//     if (_curPage == 1) {
-//       //展示无数据的布局
-//       state.datas.clear();
-//       changeLoadingState(LoadState.State_Empty);
-//       refreshController.finishRefresh();
-//     } else {
-//       //展示加载完成,没有更多数据了
-//       refreshController.finishLoad(IndicatorResult.noMore);
-//     }
-//   }
-// }
+  Subscription? subscribe;
 
-  /// 展示移除账号的提示弹窗
-  void showRemoveEstateDialog() {
-    DialogEngine.show(widget: RemoveAccountDialog(
-      confirmAction: () {
-        ToastEngine.show("确定去删除");
-      },
-    ));
+  void registerEventBus() {
+    subscribe = bus.on(AppConstant.eventEstateRefresh, (arg) {
+      Log.d("收到信息-需要刷新My Estate的列表");
+      refreshController.callRefresh();
+    });
   }
 
+  void unregisterEventBus() {
+    bus.off(AppConstant.eventEstateRefresh, subscribe);
+  }
 }

+ 10 - 10
packages/cpt_profile/lib/modules/my_household/item_household.dart

@@ -1,5 +1,6 @@
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/user_me_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_load_image.dart';
@@ -7,7 +8,7 @@ import 'package:widgets/my_text_view.dart';
 
 class HouseholdItem extends StatelessWidget {
   final int index;
-  final String item;
+  final UserMeHouseholds item;
 
   const HouseholdItem({
     required this.index,
@@ -25,19 +26,18 @@ class HouseholdItem extends StatelessWidget {
         mainAxisSize: MainAxisSize.max,
         children: [
           MyLoadImage(
-            "https://img1.baidu.com/it/u=1656098746,3560654086&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=800",
+            item.avatar,
             width: 65,
             height: 65,
             isCircle: true,
           ).marginOnly(right: 17),
-
-        MyTextView(
-          "Wu Bing Bing",
-          fontSize: 17,
-          isFontBold: true,
-          textColor: context.appColors.textBlack,
-          maxLines: 2,
-        ).expanded(),
+          MyTextView(
+            item.name ?? "-",
+            fontSize: 17,
+            isFontBold: true,
+            textColor: context.appColors.textBlack,
+            maxLines: 2,
+          ).expanded(),
         ],
       ),
     );

+ 3 - 3
packages/cpt_profile/lib/modules/my_household/my_household_page.dart

@@ -4,8 +4,8 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
 import 'package:router/ext/auto_router_extensions.dart';
-import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_text_view.dart';
@@ -53,7 +53,6 @@ class MyHouseholdPage extends HookConsumerWidget {
         child: EasyRefresh(
           controller: viewModel.refreshController,
           onRefresh: viewModel.onRefresh,
-          onLoad: viewModel.loadMore,
           child: LoadStateLayout(
             state: state.loadingState,
             errorMessage: state.errorMessage,
@@ -81,9 +80,10 @@ class MyHouseholdPage extends HookConsumerWidget {
 
   //顶部的房产布局
   Widget _buildEstateWidget(BuildContext context) {
+    ;
     return SliverToBoxAdapter(
       child: MyTextView(
-        "Owner 35 #08-29",
+        UserConfigService.getState().user?.defaultUnit?.address ?? "",
         fontSize: 20,
         paddingLeft: 15,
         paddingRight: 15,

+ 3 - 2
packages/cpt_profile/lib/modules/my_household/my_household_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/user_me_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class MyHouseholdState{
@@ -6,7 +7,7 @@ class MyHouseholdState{
   LoadState loadingState;
   String? errorMessage;
 
-  List<String> datas; //页面列表数据
+  List<UserMeHouseholds> datas; //页面列表数据
 
   // ===================================  Begin  ↓  ===================================
 
@@ -20,7 +21,7 @@ class MyHouseholdState{
     LoadState? loadingState,
     String? errorMessage,
     bool? needShowPlaceholder,
-    List<String>? datas,
+    List<UserMeHouseholds>? datas,
   }) {
     return MyHouseholdState(
       errorMessage: errorMessage ?? this.errorMessage,

+ 30 - 78
packages/cpt_profile/lib/modules/my_household/my_household_view_model.dart

@@ -1,3 +1,6 @@
+import 'package:domain/entity/user_me_entity.dart';
+import 'package:domain/repository/profile_repository.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
@@ -7,19 +10,23 @@ import 'my_household_state.dart';
 part 'my_household_view_model.g.dart';
 
 @riverpod
-class MyHouseholdViewModel extends _$MyHouseholdViewModel {
+class MyHouseholdViewModel extends _$MyHouseholdViewModel with DioCancelableMixin {
+  late final ProfileRepository _profileRepository;
+
   @override
   MyHouseholdState build() {
-    return MyHouseholdState(datas: []);
+    _profileRepository = ref.read(profileRepositoryProvider);
+    final state = MyHouseholdState(datas: []);
+    registerCancellation();
+    return state;
   }
 
-  var _curPage = 1; //请求参数当前的页面
   var _needShowPlaceholder = true; //是否展示LoadingView
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: false, //允许加载
   );
 
   //刷新页面状态
@@ -29,19 +36,11 @@ class MyHouseholdViewModel extends _$MyHouseholdViewModel {
 
   // Refresh 刷新事件
   Future onRefresh() async {
-    _curPage = 1;
-    fetchList();
-  }
-
-  // Refresh 加载事件
-  Future loadMore() async {
-    _curPage++;
     fetchList();
   }
 
   // 重试请求
   Future retryRequest() async {
-    _curPage = 1;
     _needShowPlaceholder = true;
     fetchList();
   }
@@ -53,78 +52,31 @@ class MyHouseholdViewModel extends _$MyHouseholdViewModel {
     }
 
     // 获取 Applied 列表
-    // var listResult = await _jobRepository.fetchJobAppliedList(
-    //   state.jobId,
-    //   state.selectedStatusId,
-    //   state.keyword,
-    //   curPage: _curPage,
-    //   cancelToken: cancelToken,
-    // );
-    //
-    // // 处理数据
-    // if (listResult.isSuccess) {
-    //   handleList(listResult.data?.rows);
-    // } else {
-    //   errorMessage = listResult.errorMsg;
-    //   changeLoadingState(LoadState.State_Error);
-    // }
-
-
-    await Future.delayed(const Duration(milliseconds: 1500));
-
-    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+    var result = await _profileRepository.fetchUserInfo(
+      cancelToken: cancelToken,
+    );
 
-    if (_curPage == 1) {
-      //刷新的方式
-      state = state.copyWith(datas: list);
-      refreshController.finishRefresh();
-
-      //更新展示的状态
-      changeLoadingState(LoadState.State_Success, null);
+    // 处理数据
+    if (result.isSuccess) {
+      handleList(result.data?.households);
     } else {
-      //加载更多
-      final allList = state.datas;
-      allList.addAll(list);
-      state.datas.addAll(list);
-
-      refreshController.finishLoad();
-
-      state = state.copyWith(datas: allList);
+      changeLoadingState(LoadState.State_Error, result.errorMsg);
     }
 
     // 最后赋值
     _needShowPlaceholder = false;
   }
 
-// 处理数据与展示的逻辑
-// void handleList(List<JobAppliedListSGRows>? list) {
-//   if (list != null && list.isNotEmpty) {
-//     //有数据,判断是刷新还是加载更多的数据
-//     if (_curPage == 1) {
-//       //刷新的方式
-//       state.datas.clear();
-//       state.datas.addAll(list);
-//       refreshController.finishRefresh();
-//
-//       //更新展示的状态
-//       changeLoadingState(LoadState.State_Success);
-//     } else {
-//       //加载更多
-//       state.datas.addAll(list);
-//       refreshController.finishLoad();
-//       update();
-//     }
-//   } else {
-//     if (_curPage == 1) {
-//       //展示无数据的布局
-//       state.datas.clear();
-//       changeLoadingState(LoadState.State_Empty);
-//       refreshController.finishRefresh();
-//     } else {
-//       //展示加载完成,没有更多数据了
-//       refreshController.finishLoad(IndicatorResult.noMore);
-//     }
-//   }
-// }
+  // 处理数据与展示的逻辑
+  void handleList(List<UserMeHouseholds>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据
+      state = state.copyWith(datas: list, loadingState: LoadState.State_Success);
+    } else {
+      //展示无数据的布局
+      state = state.copyWith(datas: [], loadingState: LoadState.State_Empty, errorMessage: null);
+    }
 
+    refreshController.finishRefresh();
+  }
 }

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

@@ -49,6 +49,21 @@ class ApiConstants {
   //修改手机号码
   static const apiChangeMobile = "/api/v1/user/me/setting/change-phone";
 
+  //设置房产单元为默认
+  static const apiSetEstateDefault = "/api/v1/user/estate/unit-user/set-default";
+
+  //删除指定的房产单元
+  static const apiDeleteEstateUnit = "/api/v1/user/estate/unit-user/delete";
+
+  //搜索房产
+  static const apiEstateSearch = "/api/v1/user/estate/estate/index";
+
+  //加入房产的单元校验
+  static const apiEstateUnitCheck = "/api/v1/user/estate/unit-user/join-check";
+
+  //加入房产单元
+  static const apiEstateUnitJoin = "/api/v1/user/estate/unit-user/join";
+
   // =========================== 其他 ↓=========================================
 
   //服务器时间

+ 21 - 0
packages/cs_domain/lib/entity/id_name_entity.dart

@@ -0,0 +1,21 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/id_name_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/id_name_entity.g.dart';
+
+@JsonSerializable()
+class IdNameEntity {
+	String? id;
+	String? name;
+
+	IdNameEntity();
+
+	factory IdNameEntity.fromJson(Map<String, dynamic> json) => $IdNameEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $IdNameEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 1 - 1
packages/cs_domain/lib/entity/user_me_entity.dart

@@ -78,7 +78,7 @@ class UserMeEstatesAccounts {
 	String? type;
 	@JSONField(name: "default")
 	int isDefault = 0;
-	dynamic status;
+	String? status;
 	UserMeEstatesAccountsUnit? unit;
 
 	UserMeEstatesAccounts();

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

@@ -6,6 +6,7 @@
 import 'package:flutter/material.dart' show debugPrint;
 import 'package:domain/entity/auth_login_entity.dart';
 import 'package:domain/entity/captcha_img_entity.dart';
+import 'package:domain/entity/id_name_entity.dart';
 import 'package:domain/entity/server_time.dart';
 import 'package:domain/entity/user_me_entity.dart';
 
@@ -146,6 +147,9 @@ class JsonConvert {
     if (<CaptchaImgEntity>[] is M) {
       return data.map<CaptchaImgEntity>((Map<String, dynamic> e) => CaptchaImgEntity.fromJson(e)).toList() as M;
     }
+    if (<IdNameEntity>[] is M) {
+      return data.map<IdNameEntity>((Map<String, dynamic> e) => IdNameEntity.fromJson(e)).toList() as M;
+    }
     if (<ServerTime>[] is M) {
       return data.map<ServerTime>((Map<String, dynamic> e) => ServerTime.fromJson(e)).toList() as M;
     }
@@ -192,6 +196,7 @@ class JsonConvertClassCollection {
   Map<String, JsonConvertFunction> convertFuncMap = {
     (AuthLoginEntity).toString(): AuthLoginEntity.fromJson,
     (CaptchaImgEntity).toString(): CaptchaImgEntity.fromJson,
+    (IdNameEntity).toString(): IdNameEntity.fromJson,
     (ServerTime).toString(): ServerTime.fromJson,
     (UserMeEntity).toString(): UserMeEntity.fromJson,
     (UserMeHouseholds).toString(): UserMeHouseholds.fromJson,

+ 33 - 0
packages/cs_domain/lib/generated/json/id_name_entity.g.dart

@@ -0,0 +1,33 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/id_name_entity.dart';
+
+IdNameEntity $IdNameEntityFromJson(Map<String, dynamic> json) {
+  final IdNameEntity idNameEntity = IdNameEntity();
+  final String? id = jsonConvert.convert<String>(json['id']);
+  if (id != null) {
+    idNameEntity.id = id;
+  }
+  final String? name = jsonConvert.convert<String>(json['name']);
+  if (name != null) {
+    idNameEntity.name = name;
+  }
+  return idNameEntity;
+}
+
+Map<String, dynamic> $IdNameEntityToJson(IdNameEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['id'] = entity.id;
+  data['name'] = entity.name;
+  return data;
+}
+
+extension IdNameEntityExtension on IdNameEntity {
+  IdNameEntity copyWith({
+    String? id,
+    String? name,
+  }) {
+    return IdNameEntity()
+      ..id = id ?? this.id
+      ..name = name ?? this.name;
+  }
+}

+ 2 - 2
packages/cs_domain/lib/generated/json/user_me_entity.g.dart

@@ -203,7 +203,7 @@ UserMeEstatesAccounts $UserMeEstatesAccountsFromJson(Map<String, dynamic> json)
   if (isDefault != null) {
     userMeEstatesAccounts.isDefault = isDefault;
   }
-  final dynamic status = json['status'];
+  final String? status = jsonConvert.convert<String>(json['status']);
   if (status != null) {
     userMeEstatesAccounts.status = status;
   }
@@ -233,7 +233,7 @@ extension UserMeEstatesAccountsExtension on UserMeEstatesAccounts {
     String? avatar,
     String? type,
     int? isDefault,
-    dynamic status,
+    String? status,
     UserMeEstatesAccountsUnit? unit,
   }) {
     return UserMeEstatesAccounts()

+ 143 - 0
packages/cs_domain/lib/repository/profile_repository.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/id_name_entity.dart';
 import 'package:domain/entity/user_me_entity.dart';
 import 'package:plugin_platform/platform_export.dart';
 import 'package:plugin_platform/http/dio_engine.dart';
@@ -143,4 +144,146 @@ class ProfileRepository {
     return result.convert();
   }
 
+  /// 设置默认房产单元
+  Future<HttpResult> setUnitAsDefault({
+    required String? unitId,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['unit_id'] = unitId!;
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiSetEstateDefault,
+      params: params,
+      method: HttpMethod.POST,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
+
+  /// 删除指定的房产单元
+  Future<HttpResult> deleteEstateUnit({
+    required String? unitId,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['unit_id'] = unitId!;
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiDeleteEstateUnit,
+      params: params,
+      method: HttpMethod.POST,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
+
+  /// 搜索房产
+  Future<HttpResult<IdNameEntity>> searchEstate({
+    required String? keyword,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['keyword'] = keyword ?? "";
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiEstateSearch,
+      params: params,
+      method: HttpMethod.GET,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final jsonList = result.getListJson();
+
+      //获取List数据 需要转换一次
+      var list = jsonList?.map((value) {
+        if (value is Map<String, dynamic>) {
+          return IdNameEntity.fromJson(value);
+        } else {
+          return null;
+        }
+      }).where((item) => item != null).cast<IdNameEntity>().toList();
+
+      return result.convert<IdNameEntity>(list: list);
+    }
+    return result.convert<IdNameEntity>();
+  }
+
+  /// 加入房产之前的单元验证
+  Future<HttpResult> estateJoinCheck({
+    required String? estateId,
+    required String? block,
+    required String? unit,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['estate_id'] = estateId!;
+    params['block'] = block!;
+    params['unit'] = unit!;
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiEstateUnitCheck,
+      params: params,
+      method: HttpMethod.POST,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
+
+  /// 加入房产的单元
+  Future<HttpResult> joinEstateUnit({
+    required String? estateId,
+    required String? block,
+    required String? unit,
+    required String? type,
+    required List<String>? paths,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['estate_id'] = estateId!;
+    params['block'] = block!;
+    params['unit'] = unit!;
+    params['type'] = type!;
+
+    Map<String,String> files = {};
+    if (paths!= null){
+      paths.asMap().forEach((index, path) {
+        files["files[$index]"] = path;
+      });
+    }
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiEstateUnitJoin,
+      params: params,
+      paths: files,
+      method: HttpMethod.POST,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
 }

+ 1 - 0
packages/cs_plugin_basic/lib/basic_export.dart

@@ -1,5 +1,6 @@
 export 'package:flutter_riverpod/flutter_riverpod.dart';
 export 'package:url_launcher/url_launcher.dart';
 export 'package:share_plus/share_plus.dart';
+export 'package:visibility_detector/visibility_detector.dart';
 
 

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

@@ -20,6 +20,7 @@ class AppConstant {
 
   //消息通知Key
   static const eventProfileRefresh = 'event_profile_refresh'; //通知用户信息需要刷新
+  static const eventEstateRefresh = 'event_estate_refresh'; //通知用户的房产信息需要刷新
 
   //手机短信的国家区号
   static const countryCode = ApiConstants.isServerRelease ? "65" : "86"; //(测试环境为+86,正式环境为+65)

+ 1 - 1
packages/cs_plugin_basic/lib/provider/user_config/user_config_service.dart

@@ -82,6 +82,6 @@ class UserConfigService extends _$UserConfigService {
   /// 处理退出登录之后的数据清除
   void handleLogoutParams() {
     SPUtil.remove(AppConstant.storageToken);
-    state = state.copyWith(token: null, hasLogin: false, registrationId: null, unreadNotificationsCount: 0, user: null, userName: null);
+    state = UserConfig(token: null, hasLogin: false, registrationId: null,user: null,userName: null, unreadNotificationsCount: 0);
   }
 }

+ 3 - 0
packages/cs_plugin_basic/pubspec.yaml

@@ -59,6 +59,9 @@ dependencies:
   #  分享 https://plus.fluttercommunity.dev/docs/share_plus/usage
   share_plus: 7.1.0
 
+  # 显示隐藏监听,声明周期监听
+  visibility_detector: ^0.4.0+2
+
 dev_dependencies:
   flutter_test:
     sdk: flutter

+ 5 - 0
packages/cs_plugin_platform/lib/engine/dialog/dialog_engine.dart

@@ -122,4 +122,9 @@ class DialogEngine {
   static void dismiss({String? tag}) {
     SmartDialog.dismiss(status: SmartStatus.dialog, tag: tag);
   }
+
+  //检查是否已经显示弹窗
+  static bool checkIsExist({String? tag}) {
+    return SmartDialog.checkExist(tag: tag);
+  }
 }

+ 13 - 8
packages/cs_resources/lib/generated/intl/messages_en.dart

@@ -33,7 +33,9 @@ class MessageLookup extends MessageLookupByLibrary {
 
   static String m5(time) => "Sent on ${time}";
 
-  static String m6(name) => "Welcome ${name}";
+  static String m6(name) => "Thank you ${name}";
+
+  static String m7(name) => "Welcome ${name}";
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -79,6 +81,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "booking_fee": MessageLookupByLibrary.simpleMessage("Booking Fee"),
         "booking_successful":
             MessageLookupByLibrary.simpleMessage("BOOKING SUCCESSFUL"),
+        "call_phone": MessageLookupByLibrary.simpleMessage("Call"),
         "cancel": MessageLookupByLibrary.simpleMessage("Cancel"),
         "captcha": MessageLookupByLibrary.simpleMessage("CAPTCHA"),
         "car_cancel_signature_txt": MessageLookupByLibrary.simpleMessage(
@@ -150,6 +153,8 @@ class MessageLookup extends MessageLookupByLibrary {
             "Tell us the name of the estateor building you are applying to"),
         "estate_or_building_name":
             MessageLookupByLibrary.simpleMessage("Estate or Building Name?"),
+        "estate_upload_success_desc": MessageLookupByLibrary.simpleMessage(
+            "You have successfully submitted your application\n\nThe Management may take a few days to process your application\n\nOnce your application is approved you Will be notified via a push notification to the YY Home app\n\nKindly contact the Management if you would like to amend or check the status of your application"),
         "facility": MessageLookupByLibrary.simpleMessage("Facility"),
         "facility_active": MessageLookupByLibrary.simpleMessage("Active"),
         "fee": MessageLookupByLibrary.simpleMessage("Fee"),
@@ -344,6 +349,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "reset_password":
             MessageLookupByLibrary.simpleMessage("Reset Password"),
         "rewards": MessageLookupByLibrary.simpleMessage("Rewards"),
+        "send_email": MessageLookupByLibrary.simpleMessage("Email"),
         "send_feedback": MessageLookupByLibrary.simpleMessage("Send FeedBack"),
         "send_feedback_management": MessageLookupByLibrary.simpleMessage(
             "If you would like more information,please send a feedback to the Management"),
@@ -396,6 +402,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("Terms & Conditions"),
         "terms_of_service":
             MessageLookupByLibrary.simpleMessage("Terms of Service"),
+        "thank_you_name": m6,
         "time_of_arrival":
             MessageLookupByLibrary.simpleMessage("TIME OF ARRIVAL"),
         "title": MessageLookupByLibrary.simpleMessage("Title"),
@@ -410,12 +417,10 @@ class MessageLookup extends MessageLookupByLibrary {
         "upload": MessageLookupByLibrary.simpleMessage("Upload"),
         "upload_a_photo":
             MessageLookupByLibrary.simpleMessage("Upload a Photo"),
-        "upload_doc_desc": MessageLookupByLibrary.simpleMessage(
-            "The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financia information"),
-        "upload_doc_desc1": MessageLookupByLibrary.simpleMessage(
-            "(1)A valid tenancy agreement showing your name,unit numper,tenancy expiration date and a list of occupants (if applicable)"),
-        "upload_doc_desc2": MessageLookupByLibrary.simpleMessage(
-            "(2)Tenancy Agreement Stamp Duty receipt"),
+        "upload_doc_owner_desc": MessageLookupByLibrary.simpleMessage(
+            "The management requires you to upload the following documents to verify your property information. You can edit sensitive financial information\n\n(1)Property ownership certificate, sales contract, (if applicable)\n\n(2)Local tax invoice"),
+        "upload_doc_tenant_desc": MessageLookupByLibrary.simpleMessage(
+            "The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financial information\n\n(1)A valid tenancy agreement showing your name,unit number,tenancy expiration date and a list of occupants (if applicable)\n\n(2)Tenancy Agreement Stamp Duty receipt"),
         "upload_documents":
             MessageLookupByLibrary.simpleMessage("Upload Documents"),
         "upload_pictures":
@@ -441,7 +446,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("Visitor Registration"),
         "waiting_for_the_administrator": MessageLookupByLibrary.simpleMessage(
             "Waiting for the administrator"),
-        "welcome_name": m6,
+        "welcome_name": m7,
         "who_are_owners":
             MessageLookupByLibrary.simpleMessage("Who are owners?"),
         "who_are_tenants":

+ 48 - 18
packages/cs_resources/lib/generated/l10n.dart

@@ -630,31 +630,21 @@ class S {
     );
   }
 
-  /// `The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financia information`
-  String get upload_doc_desc {
+  /// `The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financial information\n\n(1)A valid tenancy agreement showing your name,unit number,tenancy expiration date and a list of occupants (if applicable)\n\n(2)Tenancy Agreement Stamp Duty receipt`
+  String get upload_doc_tenant_desc {
     return Intl.message(
-      'The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financia information',
-      name: 'upload_doc_desc',
+      'The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financial information\n\n(1)A valid tenancy agreement showing your name,unit number,tenancy expiration date and a list of occupants (if applicable)\n\n(2)Tenancy Agreement Stamp Duty receipt',
+      name: 'upload_doc_tenant_desc',
       desc: '',
       args: [],
     );
   }
 
-  /// `(1)A valid tenancy agreement showing your name,unit numper,tenancy expiration date and a list of occupants (if applicable)`
-  String get upload_doc_desc1 {
+  /// `The management requires you to upload the following documents to verify your property information. You can edit sensitive financial information\n\n(1)Property ownership certificate, sales contract, (if applicable)\n\n(2)Local tax invoice`
+  String get upload_doc_owner_desc {
     return Intl.message(
-      '(1)A valid tenancy agreement showing your name,unit numper,tenancy expiration date and a list of occupants (if applicable)',
-      name: 'upload_doc_desc1',
-      desc: '',
-      args: [],
-    );
-  }
-
-  /// `(2)Tenancy Agreement Stamp Duty receipt`
-  String get upload_doc_desc2 {
-    return Intl.message(
-      '(2)Tenancy Agreement Stamp Duty receipt',
-      name: 'upload_doc_desc2',
+      'The management requires you to upload the following documents to verify your property information. You can edit sensitive financial information\n\n(1)Property ownership certificate, sales contract, (if applicable)\n\n(2)Local tax invoice',
+      name: 'upload_doc_owner_desc',
       desc: '',
       args: [],
     );
@@ -2720,6 +2710,46 @@ class S {
     );
   }
 
+  /// `Thank you {name}`
+  String thank_you_name(Object name) {
+    return Intl.message(
+      'Thank you $name',
+      name: 'thank_you_name',
+      desc: '',
+      args: [name],
+    );
+  }
+
+  /// `You have successfully submitted your application\n\nThe Management may take a few days to process your application\n\nOnce your application is approved you Will be notified via a push notification to the YY Home app\n\nKindly contact the Management if you would like to amend or check the status of your application`
+  String get estate_upload_success_desc {
+    return Intl.message(
+      'You have successfully submitted your application\n\nThe Management may take a few days to process your application\n\nOnce your application is approved you Will be notified via a push notification to the YY Home app\n\nKindly contact the Management if you would like to amend or check the status of your application',
+      name: 'estate_upload_success_desc',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Email`
+  String get send_email {
+    return Intl.message(
+      'Email',
+      name: 'send_email',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Call`
+  String get call_phone {
+    return Intl.message(
+      'Call',
+      name: 'call_phone',
+      desc: '',
+      args: [],
+    );
+  }
+
   /// `Other`
   String get other {
     return Intl.message(

+ 6 - 3
packages/cs_resources/lib/l10n/intl_en.arb

@@ -57,9 +57,8 @@
   "tenants_desc3": "I am the tenant of the company that rented the unit",
   "tenants_desc4": "The Management will verify your application accordingly",
   "upload_documents": "Upload Documents",
-  "upload_doc_desc": "The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financia information",
-  "upload_doc_desc1": "(1)A valid tenancy agreement showing your name,unit numper,tenancy expiration date and a list of occupants (if applicable)",
-  "upload_doc_desc2": "(2)Tenancy Agreement Stamp Duty receipt",
+  "upload_doc_tenant_desc": "The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financial information\n\n(1)A valid tenancy agreement showing your name,unit number,tenancy expiration date and a list of occupants (if applicable)\n\n(2)Tenancy Agreement Stamp Duty receipt",
+  "upload_doc_owner_desc" : "The management requires you to upload the following documents to verify your property information. You can edit sensitive financial information\n\n(1)Property ownership certificate, sales contract, (if applicable)\n\n(2)Local tax invoice",
   "upload": "Upload",
   "following": "Following",
   "followers": "Followers",
@@ -266,5 +265,9 @@
   "successful": "Successful",
   "send_sms_successful": "Sending SMS successfully, please enter SMS verification code",
   "get_verification_code": "Get Verification Code",
+  "thank_you_name": "Thank you {name}",
+  "estate_upload_success_desc": "You have successfully submitted your application\n\nThe Management may take a few days to process your application\n\nOnce your application is approved you Will be notified via a push notification to the YY Home app\n\nKindly contact the Management if you would like to amend or check the status of your application",
+  "send_email": "Email",
+  "call_phone": "Call",
   "other": "Other"
 }

+ 6 - 3
packages/cs_resources/lib/l10n/intl_zh_CN.arb

@@ -57,9 +57,8 @@
   "tenants_desc3": "我是租用该单元的公司的租户",
   "tenants_desc4": "管理员将相应地验证您的申请",
   "upload_documents": "上传文档",
-  "upload_doc_desc": "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息",
-  "upload_doc_desc1": "(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)",
-  "upload_doc_desc2": "(2)租赁协议印花税收据",
+  "upload_doc_tenant_desc": "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息\n\n(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)\n\n(2)租赁协议印花税收据",
+  "upload_doc_owner_desc" :"管理员要求您上传以下文件以验证您的房产信息。您可以编辑敏感的财务信息\n\n(1)房产证、销售合同(如适用)\n\n(2)当地税务发票",
   "upload": "上传",
   "following": "关注",
   "followers": "粉丝",
@@ -266,5 +265,9 @@
   "successful": "成功",
   "send_sms_successful": "发送短信成功,请输入短信验证码",
   "get_verification_code": "获取短信验证码",
+  "thank_you_name": "谢谢你 {name}",
+  "estate_upload_success_desc": "您已成功提交申请\n\n管理员可能需要几天时间来处理您的申请\n\n一旦您的申请获得批准,您将通过推送通知YY Home应用程序收到通知\n\n如果您想修改或检查您的申请状态,请联系管理层",
+  "send_email": "发送邮件",
+  "call_phone": "拨打电话",
   "other": "其他"
 }

+ 6 - 3
packages/cs_resources/lib/l10n/intl_zh_HK.arb

@@ -43,9 +43,8 @@
   "type_here": "在此输入",
   "estate_name_desc": "告诉我们您申请的公寓楼的名称",
   "upload_documents": "上传文档",
-  "upload_doc_desc": "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息",
-  "upload_doc_desc1": "(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)",
-  "upload_doc_desc2": "(2)租赁协议印花税收据",
+  "upload_doc_tenant_desc": "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息\n\n(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)\n\n(2)租赁协议印花税收据",
+  "upload_doc_owner_desc": "管理员要求您上传以下文件以验证您的房产信息。您可以编辑敏感的财务信息\n\n(1)房产证、销售合同(如适用)\n\n(2)当地税务发票",
   "upload": "上传",
   "following": "关注",
   "followers": "粉丝",
@@ -252,5 +251,9 @@
   "successful": "成功",
   "send_sms_successful": "发送短信成功,请输入短信验证码",
   "get_verification_code": "获取短信验证码",
+  "thank_you_name": "谢谢你 {name}",
+  "estate_upload_success_desc": "您已成功提交申请\n\n管理员可能需要几天时间来处理您的申请\n\n一旦您的申请获得批准,您将通过推送通知YY Home应用程序收到通知\n\n如果您想修改或检查您的申请状态,请联系管理层",
+  "send_email": "发送邮件",
+  "call_phone": "拨打电话",
   "other": "其他"
 }

+ 15 - 18
packages/cs_router/lib/path/router_path.dart

@@ -15,6 +15,7 @@ class RouterPath {
   static const authSelectUnit = '/auth/select/unit'; //绑定楼栋与房间号
   static const authSelectRole = '/auth/select/role'; //选择角色
   static const authTenantDoc = '/auth/tenant/doc'; //租户的文件上传
+  static const authEstateUploadSuccess = '/auth/estate/success'; //Estate上传流程走完
   static const authResetPassword = '/auth/rest_psd'; //重置密码
 
   //首页
@@ -48,10 +49,8 @@ class RouterPath {
   static const newsFeedPost = '/newsfeed_post';
   static const newsFeedDetail = '/newsfeed_detail';
 
-
   static const garage = '/garage';
 
-
   // static const garageForSale = 'garage/garage_for_sale';
   // static const garageForRent = 'garage/garage_for_rent';
   static const garageSalePost = '/garage_sale_post';
@@ -64,7 +63,6 @@ class RouterPath {
   static const myFollowingFollow = 'my_following/follow';
   static const myFollowingFollower = 'my_following/follower';
 
-
   //设施
   static const facility = '/facility';
   static const facilityDetail = '/facility/detail';
@@ -75,19 +73,19 @@ class RouterPath {
   //表单
   static const form = '/form';
   static const formAttachment = '/form/attachment';
-  static const formPayment= '/form/payment';
-  static const formGuestVehicle ='/form/guest/vehicle';
-  static const formLargeTextBox ='/form/large/text/box';
-  static const formMovingCompany ='/form/moving/company';
-  static const formMovingDate ='/form/moving/date';
-  static const formNoteManagement='/form/note/management';
-  static const formRenovationCompany='/form/renovation/company';
-  static const formRenovationDate='/form/renovation/date';
-  static const formSignature='/form/signature';
-  static const formTypeOfApplication='/form/type/application';
-  static const formVehicleInfo='/form/vehicle/info';
-  static const formTerms='/form/terms';
-  static const formDetail='/form/detail';
+  static const formPayment = '/form/payment';
+  static const formGuestVehicle = '/form/guest/vehicle';
+  static const formLargeTextBox = '/form/large/text/box';
+  static const formMovingCompany = '/form/moving/company';
+  static const formMovingDate = '/form/moving/date';
+  static const formNoteManagement = '/form/note/management';
+  static const formRenovationCompany = '/form/renovation/company';
+  static const formRenovationDate = '/form/renovation/date';
+  static const formSignature = '/form/signature';
+  static const formTypeOfApplication = '/form/type/application';
+  static const formVehicleInfo = '/form/vehicle/info';
+  static const formTerms = '/form/terms';
+  static const formDetail = '/form/detail';
 
   //消息板
   static const noticeBoard = '/notice_board';
@@ -95,9 +93,8 @@ class RouterPath {
   static const event = 'notice_board/event';
   static const documents = 'notice_board/documents';
   static const announcementDetail = '/notice_board/announcement_detail';
-  static const eventDetail = '/notice_board/event_detail';  
+  static const eventDetail = '/notice_board/event_detail';
   static const documentsList = '/notice_board/documents_list';
-  
 
   //支付
   static const payment = '/payment';