3 Commity 75b26443f0 ... 64a934a7b4

Autor SHA1 Wiadomość Data
  liukai 64a934a7b4 选择社区选择楼栋单元房号,选择角色,上传文档 2 tygodni temu
  liukai 9e11134c90 选择业主还是租户 2 tygodni temu
  liukai 733bda7175 选择房子与单元 2 tygodni temu
55 zmienionych plików z 2145 dodań i 146 usunięć
  1. 19 19
      app/pubspec_overrides.yaml
  2. 205 0
      packages/cpt_auth/lib/modules/select_estate/select_estate_page.dart
  3. 33 0
      packages/cpt_auth/lib/modules/select_estate/select_estate_state.dart
  4. 24 0
      packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.dart
  5. 27 0
      packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.g.dart
  6. 64 0
      packages/cpt_auth/lib/modules/select_role/screen_owner.dart
  7. 57 0
      packages/cpt_auth/lib/modules/select_role/screen_tenant.dart
  8. 115 0
      packages/cpt_auth/lib/modules/select_role/select_role_page.dart
  9. 15 0
      packages/cpt_auth/lib/modules/select_role/select_role_state.dart
  10. 23 0
      packages/cpt_auth/lib/modules/select_role/select_role_view_model.dart
  11. 27 0
      packages/cpt_auth/lib/modules/select_role/select_role_view_model.g.dart
  12. 295 0
      packages/cpt_auth/lib/modules/select_unit/select_unit_page.dart
  13. 47 0
      packages/cpt_auth/lib/modules/select_unit/select_unit_state.dart
  14. 24 0
      packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.dart
  15. 27 0
      packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.g.dart
  16. 1 1
      packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_view_model.g.dart
  17. 1 1
      packages/cpt_auth/lib/modules/sing_up_verify/sign_up_verify_view_model.g.dart
  18. 160 0
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_page.dart
  19. 22 0
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_state.dart
  20. 32 0
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.dart
  21. 27 0
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.g.dart
  22. 2 1
      packages/cpt_auth/lib/router/component/auth_component_service.dart
  23. 8 0
      packages/cpt_auth/lib/router/page/auth_page_router.dart
  24. 131 0
      packages/cpt_auth/lib/router/page/auth_page_router.gr.dart
  25. 7 7
      packages/cpt_auth/pubspec_overrides.yaml
  26. 7 7
      packages/cpt_community/pubspec_overrides.yaml
  27. 7 7
      packages/cpt_facility/pubspec_overrides.yaml
  28. 7 7
      packages/cpt_form/pubspec_overrides.yaml
  29. 7 7
      packages/cpt_main/pubspec_overrides.yaml
  30. 7 7
      packages/cpt_notice_board/pubspec_overrides.yaml
  31. 7 7
      packages/cpt_payment/pubspec_overrides.yaml
  32. 7 7
      packages/cpt_profile/pubspec_overrides.yaml
  33. 7 7
      packages/cpt_property/pubspec_overrides.yaml
  34. 7 7
      packages/cpt_rewards/pubspec_overrides.yaml
  35. 7 7
      packages/cpt_services/pubspec_overrides.yaml
  36. 6 6
      packages/cs_domain/pubspec_overrides.yaml
  37. 7 7
      packages/cs_initializer/pubspec_overrides.yaml
  38. 6 6
      packages/cs_plugin_basic/pubspec_overrides.yaml
  39. 137 0
      packages/cs_plugin_platform/lib/engine/image/image_nine_grid.dart
  40. 14 14
      packages/cs_plugin_platform/lib/engine/permission/permission_engine.dart
  41. 2 1
      packages/cs_plugin_platform/lib/platform_export.dart
  42. 4 4
      packages/cs_plugin_platform/pubspec_overrides.yaml
  43. 0 0
      packages/cs_resources/assets/base_lib/image_add_icon.webp
  44. 1 1
      packages/cs_resources/lib/generated/assets.dart
  45. 51 1
      packages/cs_resources/lib/generated/intl/messages_en.dart
  46. 37 1
      packages/cs_resources/lib/generated/intl/messages_zh_CN.dart
  47. 22 1
      packages/cs_resources/lib/generated/intl/messages_zh_HK.dart
  48. 280 0
      packages/cs_resources/lib/generated/l10n.dart
  49. 28 0
      packages/cs_resources/lib/l10n/intl_en.arb
  50. 28 0
      packages/cs_resources/lib/l10n/intl_zh_CN.arb
  51. 14 0
      packages/cs_resources/lib/l10n/intl_zh_HK.arb
  52. 35 1
      packages/cs_resources/lib/theme/app_colors_theme.dart
  53. 5 1
      packages/cs_router/lib/path/router_path.dart
  54. 2 0
      packages/cs_widgets/lib/my_appbar.dart
  55. 3 3
      packages/cs_widgets/pubspec_overrides.yaml

+ 19 - 19
app/pubspec_overrides.yaml

@@ -1,40 +1,40 @@
 # melos_managed_dependency_overrides: cpt_auth,cpt_community,cpt_facility,cpt_form,cpt_main,cpt_notice_board,cpt_payment,cpt_profile,cpt_rewards,cpt_services,cs_resources,domain,initializer,plugin_basic,plugin_platform,router,shared,widgets,cpt_property
 dependency_overrides:
   cpt_auth:
-    path: ..\\packages\\cpt_auth
+    path: ../packages/cpt_auth
   cpt_community:
-    path: ..\\packages\\cpt_community
+    path: ../packages/cpt_community
   cpt_facility:
-    path: ..\\packages\\cpt_facility
+    path: ../packages/cpt_facility
   cpt_form:
-    path: ..\\packages\\cpt_form
+    path: ../packages/cpt_form
   cpt_main:
-    path: ..\\packages\\cpt_main
+    path: ../packages/cpt_main
   cpt_notice_board:
-    path: ..\\packages\\cpt_notice_board
+    path: ../packages/cpt_notice_board
   cpt_payment:
-    path: ..\\packages\\cpt_payment
+    path: ../packages/cpt_payment
   cpt_profile:
-    path: ..\\packages\\cpt_profile
+    path: ../packages/cpt_profile
   cpt_property:
-    path: ..\\packages\\cpt_property
+    path: ../packages/cpt_property
   cpt_rewards:
-    path: ..\\packages\\cpt_rewards
+    path: ../packages/cpt_rewards
   cpt_services:
-    path: ..\\packages\\cpt_services
+    path: ../packages/cpt_services
   cs_resources:
-    path: ..\\packages\\cs_resources
+    path: ../packages/cs_resources
   domain:
-    path: ..\\packages\\cs_domain
+    path: ../packages/cs_domain
   initializer:
-    path: ..\\packages\\cs_initializer
+    path: ../packages/cs_initializer
   plugin_basic:
-    path: ..\\packages\\cs_plugin_basic
+    path: ../packages/cs_plugin_basic
   plugin_platform:
-    path: ..\\packages\\cs_plugin_platform
+    path: ../packages/cs_plugin_platform
   router:
-    path: ..\\packages\\cs_router
+    path: ../packages/cs_router
   shared:
-    path: ..\\packages\\cs_shared
+    path: ../packages/cs_shared
   widgets:
-    path: ..\\packages\\cs_widgets
+    path: ../packages/cs_widgets

+ 205 - 0
packages/cpt_auth/lib/modules/select_estate/select_estate_page.dart

@@ -0,0 +1,205 @@
+import 'package:cpt_auth/modules/select_estate/select_estate_state.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: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 '../../router/page/auth_page_router.dart';
+import 'select_estate_view_model.dart';
+
+@RoutePage()
+class SelectEstatePage extends HookConsumerWidget {
+  SelectEstatePage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(SelectEstatePageRoute());
+    } else {
+      appRouter.push(SelectEstatePageRoute());
+    }
+  }
+
+  // 为需要测量的控件创建 GlobalKey
+  final GlobalKey _appbarKey = GlobalKey();
+  final GlobalKey _topImageKey = GlobalKey();
+  final GlobalKey _titleKey = GlobalKey();
+  final GlobalKey _inputKey = GlobalKey();
+  final GlobalKey _descriptionKey = GlobalKey();
+  final GlobalKey _buttonKey = GlobalKey();
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(selectEstateViewModelProvider.notifier);
+    final state = ref.watch(selectEstateViewModelProvider);
+
+    // 获取屏幕高度
+    final screenHeight = MediaQuery.of(context).size.height;
+    final statusBarHeight = MediaQuery.of(context).padding.top;
+    final navigationBarHeight = MediaQuery.of(context).padding.bottom;
+
+    useEffect(() {
+      double usedHeight = 0;
+      // 组件挂载时执行,获取控件高度
+      WidgetsBinding.instance.addPostFrameCallback((_) {
+        // 获取各个控件的高度
+        usedHeight += _appbarKey.currentContext?.size?.height ?? 0;
+        usedHeight += _topImageKey.currentContext?.size?.height ?? 0;
+        usedHeight += _titleKey.currentContext?.size?.height ?? 0;
+        usedHeight += _inputKey.currentContext?.size?.height ?? 0;
+        usedHeight += _descriptionKey.currentContext?.size?.height ?? 0;
+        usedHeight += _buttonKey.currentContext?.size?.height ?? 0;
+
+        // 计算剩余空间
+        double remainingSpace = screenHeight - statusBarHeight - navigationBarHeight - usedHeight - 38 - 28 - 20 - 19;
+
+        Log.d("计算剩余空间:$remainingSpace");
+
+        if (remainingSpace > 0) {
+          // 设置一个状态来存储剩余空间的高度
+          viewModel.setRemainingSpace(remainingSpace);
+        }
+      });
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, S.current.yy_home_accounts, key: _appbarKey),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Container(
+          padding: const EdgeInsets.symmetric(horizontal: 38),
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //顶部图片
+              MyAssetImage(
+                key: _topImageKey,
+                Assets.authChooseEstateBuilding,
+                width: 267,
+                height: 158,
+              ).marginOnly(top: 28, bottom: 38),
+
+              MyTextView(
+                key: _titleKey,
+                S.current.estate_or_building_name,
+                fontSize: 23,
+                marginBottom: 20,
+                textAlign: TextAlign.center,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              //输入资产的名称
+              _buildInputLayout(
+                context,
+                state,
+                "estate",
+                key: _inputKey,
+                textInputAction: TextInputAction.done,
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                },
+              ),
+
+              MyTextView(
+                key: _descriptionKey,
+                S.current.estate_name_desc,
+                fontSize: 15,
+                marginTop: 19,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              SizedBox(
+                height: state.remainingSpace, // 使用剩余空间的值
+              ),
+
+              MyButton(
+                key: _buttonKey,
+                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: 40, bottom: 30),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  /// 输入框
+  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,
+      ),
+    );
+  }
+}

+ 33 - 0
packages/cpt_auth/lib/modules/select_estate/select_estate_state.dart

@@ -0,0 +1,33 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:flutter/material.dart';
+
+class SelectEstateState {
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  double remainingSpace;
+
+  // ===================================  Begin  ↓  ===================================
+
+  SelectEstateState({
+    this.remainingSpace = 0,
+    Map<String, Map<String, dynamic>>? formData,
+  }) : formData = formData ??
+            {
+              'estate': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': S.current.type_here,
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+            };
+
+  SelectEstateState copyWith({
+    double? remainingSpace,
+  }) {
+    return SelectEstateState(
+      remainingSpace: remainingSpace ?? this.remainingSpace,
+    );
+  }
+}

+ 24 - 0
packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.dart

@@ -0,0 +1,24 @@
+
+import 'package:cpt_auth/modules/select_estate/select_estate_state.dart';
+import 'package:cpt_auth/modules/select_unit/select_unit_page.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+part 'select_estate_view_model.g.dart';
+
+@riverpod
+class SelectEstateViewModel extends _$SelectEstateViewModel {
+
+  @override
+  SelectEstateState build(){
+    return SelectEstateState();
+  }
+
+  /// 提交并进入下一步
+  void submitEstate() {
+    SelectUnitPage.startInstance();
+  }
+
+  void setRemainingSpace(double remainingSpace) {
+    state = state.copyWith(remainingSpace: remainingSpace);
+  }
+}

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

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'select_estate_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$selectEstateViewModelHash() =>
+    r'44d0829cc1f4d48b2fa0991838a8217e77898786';
+
+/// See also [SelectEstateViewModel].
+@ProviderFor(SelectEstateViewModel)
+final selectEstateViewModelProvider = AutoDisposeNotifierProvider<
+    SelectEstateViewModel, SelectEstateState>.internal(
+  SelectEstateViewModel.new,
+  name: r'selectEstateViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$selectEstateViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$SelectEstateViewModel = AutoDisposeNotifier<SelectEstateState>;
+// 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

+ 64 - 0
packages/cpt_auth/lib/modules/select_role/screen_owner.dart

@@ -0,0 +1,64 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:widgets/my_text_view.dart';
+
+class ScreenOwner extends StatelessWidget {
+  const ScreenOwner({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return SingleChildScrollView(
+      scrollDirection: Axis.vertical,
+      physics: const BouncingScrollPhysics(),
+      child: Column(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            S.current.who_are_owners,
+            fontSize: 23.5,
+            marginTop: 25,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.owners_desc1,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.owners_desc2,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.owners_desc3,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.owners_desc4,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.owners_desc5,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 57 - 0
packages/cpt_auth/lib/modules/select_role/screen_tenant.dart

@@ -0,0 +1,57 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:widgets/my_text_view.dart';
+
+class ScreenTenant extends StatelessWidget {
+  const ScreenTenant({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return SingleChildScrollView(
+      scrollDirection: Axis.vertical,
+      physics: const BouncingScrollPhysics(),
+      child: Column(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            S.current.who_are_tenants,
+            fontSize: 23.5,
+            marginTop: 25,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.tenants_desc1,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.tenants_desc2,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.tenants_desc3,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.tenants_desc4,
+            fontSize: 15,
+            marginTop: 22,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 115 - 0
packages/cpt_auth/lib/modules/select_role/select_role_page.dart

@@ -0,0 +1,115 @@
+import 'package:cpt_auth/modules/select_role/screen_owner.dart';
+import 'package:cpt_auth/modules/select_role/screen_tenant.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: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_text_view.dart';
+
+import '../../router/page/auth_page_router.dart';
+import 'select_role_view_model.dart';
+
+@RoutePage()
+class SelectRolePage extends HookConsumerWidget {
+  const SelectRolePage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const SelectRolePageRoute());
+    } else {
+      appRouter.push(const SelectRolePageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(selectRoleViewModelProvider.notifier);
+    final state = ref.watch(selectRoleViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, ""),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: Container(
+        padding: const EdgeInsets.symmetric(horizontal: 15),
+        width: double.infinity,
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            MyTextView(
+              S.current.owner_or_tenant,
+              fontSize: 23.5,
+              marginTop: 25,
+              marginBottom: 25,
+              textAlign: TextAlign.center,
+              isFontMedium: true,
+              textColor: context.appColors.textBlack,
+            ),
+
+            //顶部的Tab切换
+            Row(
+              children: [
+                MyTextView(
+                  S.current.owner,
+                  textColor: state.selectedIndex == 0 ? context.appColors.tabTextSelectedPrimary : context.appColors.tabTextUnSelectedPrimary,
+                  fontSize: 16,
+                  isFontMedium: true,
+                  paddingTop: 16,
+                  paddingBottom: 16,
+                  cornerRadius: 5,
+                  textAlign: TextAlign.center,
+                  onClick: () {
+                    viewModel.selectRole(0);
+                  },
+                  backgroundColor: state.selectedIndex == 0 ? context.appColors.tabBgSelectedPrimary : context.appColors.tabBgUnSelectedPrimary,
+                ).expanded(),
+                MyTextView(
+                  S.current.tenant,
+                  textColor: state.selectedIndex == 1 ? context.appColors.tabTextSelectedPrimary : context.appColors.tabTextUnSelectedPrimary,
+                  fontSize: 16,
+                  marginLeft: 15,
+                  paddingTop: 16,
+                  paddingBottom: 16,
+                  textAlign: TextAlign.center,
+                  isFontMedium: true,
+                  cornerRadius: 5,
+                  onClick: () {
+                    viewModel.selectRole(1);
+                  },
+                  backgroundColor: state.selectedIndex == 1 ? context.appColors.tabBgSelectedPrimary : context.appColors.tabBgUnSelectedPrimary,
+                ).expanded(),
+              ],
+            ),
+
+            IndexedStack(
+              index: state.selectedIndex,
+              children: const [
+                ScreenOwner(),
+                ScreenTenant(),
+              ],
+            ).expanded(),
+
+            //底部的按钮
+            MyButton(
+              onPressed: viewModel.submitRole,
+              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: 30, bottom: 30, left: 18, right: 18),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 15 - 0
packages/cpt_auth/lib/modules/select_role/select_role_state.dart

@@ -0,0 +1,15 @@
+class SelectRoleState {
+  int selectedIndex;
+
+  SelectRoleState({
+    this.selectedIndex = 0,
+  });
+
+  SelectRoleState copyWith({
+    int? selectedIndex,
+  }) {
+    return SelectRoleState(
+      selectedIndex: selectedIndex ?? this.selectedIndex,
+    );
+  }
+}

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

@@ -0,0 +1,23 @@
+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';
+
+part 'select_role_view_model.g.dart';
+
+@riverpod
+class SelectRoleViewModel extends _$SelectRoleViewModel {
+  @override
+  SelectRoleState build() {
+    return SelectRoleState();
+  }
+
+  //进入下一步
+  void submitRole() {
+    TenantDocPage.startInstance();
+  }
+
+  //选择角色
+  void selectRole(int index) {
+    state = state.copyWith(selectedIndex: index);
+  }
+}

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

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'select_role_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$selectRoleViewModelHash() =>
+    r'a42d4ba4dd03754e74e58b1a320793449326bef4';
+
+/// See also [SelectRoleViewModel].
+@ProviderFor(SelectRoleViewModel)
+final selectRoleViewModelProvider =
+    AutoDisposeNotifierProvider<SelectRoleViewModel, SelectRoleState>.internal(
+  SelectRoleViewModel.new,
+  name: r'selectRoleViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$selectRoleViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$SelectRoleViewModel = AutoDisposeNotifier<SelectRoleState>;
+// 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

+ 295 - 0
packages/cpt_auth/lib/modules/select_unit/select_unit_page.dart

@@ -0,0 +1,295 @@
+import 'package:cpt_auth/modules/select_estate/select_estate_state.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: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 '../../router/page/auth_page_router.dart';
+import 'select_unit_state.dart';
+import 'select_unit_view_model.dart';
+
+@RoutePage()
+class SelectUnitPage extends HookConsumerWidget {
+  SelectUnitPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(SelectUnitPageRoute());
+    } else {
+      appRouter.push(SelectUnitPageRoute());
+    }
+  }
+
+  // 为需要测量的控件创建 GlobalKey
+  final GlobalKey _appbarKey = GlobalKey();
+  final GlobalKey _topImageKey = GlobalKey();
+  final GlobalKey _inputKey = GlobalKey();
+  final GlobalKey _description1Key = GlobalKey();
+  final GlobalKey _description2Key = GlobalKey();
+  final GlobalKey _description3Key = GlobalKey();
+  final GlobalKey _buttonKey = GlobalKey();
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(selectUnitViewModelProvider.notifier);
+    final state = ref.watch(selectUnitViewModelProvider);
+
+    // 获取屏幕高度
+    final screenHeight = MediaQuery.of(context).size.height;
+    final statusBarHeight = MediaQuery.of(context).padding.top;
+    final navigationBarHeight = MediaQuery.of(context).padding.bottom;
+
+    useEffect(() {
+      double usedHeight = 0;
+      // 组件挂载时执行,获取控件高度
+      WidgetsBinding.instance.addPostFrameCallback((_) {
+        // 获取各个控件的高度
+        usedHeight += _appbarKey.currentContext?.size?.height ?? 0;
+        usedHeight += _topImageKey.currentContext?.size?.height ?? 0;
+        usedHeight += _inputKey.currentContext?.size?.height ?? 0;
+        usedHeight += _description1Key.currentContext?.size?.height ?? 0;
+        usedHeight += _description2Key.currentContext?.size?.height ?? 0;
+        usedHeight += _description3Key.currentContext?.size?.height ?? 0;
+        usedHeight += _buttonKey.currentContext?.size?.height ?? 0;
+
+        // 计算剩余空间
+        double remainingSpace = screenHeight - statusBarHeight - navigationBarHeight - usedHeight - 28 - 18 - 25 - 20 - 20;
+
+        Log.d("计算剩余空间:$remainingSpace");
+
+        if (remainingSpace > 0) {
+          // 设置一个状态来存储剩余空间的高度
+          viewModel.setRemainingSpace(remainingSpace);
+        }
+      });
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, S.current.yy_home_accounts, key: _appbarKey),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Container(
+          padding: const EdgeInsets.symmetric(horizontal: 20),
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //顶部图片
+              MyAssetImage(
+                key: _topImageKey,
+                Assets.authSignUpUnitImg,
+                width: 266.5,
+                height: 162,
+              ).marginOnly(top: 28, bottom: 18),
+
+              Row(
+                key: _inputKey,
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  //街区
+                  Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      MyTextView(
+                        S.current.block,
+                        marginBottom: 9,
+                        textColor: context.appColors.textBlack,
+                        fontSize: 16,
+                        isFontMedium: true,
+                      ),
+
+                      // 表单 - 街区
+                      _buildInputLayout(
+                        context,
+                        state,
+                        "block",
+                        textInputAction: TextInputAction.next,
+                        onSubmit: (formKey, value) {
+                          state.formData[formKey]!['focusNode'].unfocus();
+                          FocusScope.of(context).requestFocus(state.formData['unit']!['focusNode']);
+                        },
+                      ).constrained(width: 88),
+                    ],
+                  ),
+
+                  MyTextView(
+                    "#",
+                    marginTop: 20,
+                    marginLeft: 8.5,
+                    marginRight: 8.5,
+                    textColor: context.appColors.textBlack,
+                    fontSize: 16,
+                    isFontMedium: true,
+                  ),
+
+                  //单元
+                  Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      MyTextView(
+                        S.current.unit_number,
+                        marginBottom: 9,
+                        textColor: context.appColors.textBlack,
+                        fontSize: 16,
+                        isFontMedium: true,
+                      ),
+                      Row(
+                        children: [
+                          // 表单 - 单元
+                          _buildInputLayout(
+                            context,
+                            state,
+                            "unit",
+                            textInputAction: TextInputAction.next,
+                            onSubmit: (formKey, value) {
+                              state.formData[formKey]!['focusNode'].unfocus();
+                              FocusScope.of(context).requestFocus(state.formData['room']!['focusNode']);
+                            },
+                          ).constrained(width: 83),
+
+                          MyTextView(
+                            "-",
+                            textColor: context.appColors.textBlack,
+                            marginLeft: 4,
+                            marginRight: 4,
+                            isFontMedium: true,
+                          ),
+
+                          // 表单 - 房号
+                          _buildInputLayout(
+                            context,
+                            state,
+                            "room",
+                            textInputAction: TextInputAction.done,
+                            onSubmit: (formKey, value) {
+                              state.formData[formKey]!['focusNode'].unfocus();
+                            },
+                          ).constrained(width: 83),
+                        ],
+                      ),
+                    ],
+                  ),
+                ],
+              ),
+
+              MyTextView(
+                key: _description1Key,
+                S.current.block_desc,
+                fontSize: 15,
+                marginTop: 25,
+                textAlign: TextAlign.center,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              MyTextView(
+                key: _description2Key,
+                S.current.block_example,
+                fontSize: 15,
+                marginTop: 20,
+                textAlign: TextAlign.center,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              MyTextView(
+                key: _description3Key,
+                S.current.block_example_desc,
+                fontSize: 15,
+                marginTop: 20,
+                textAlign: TextAlign.center,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+
+              SizedBox(
+                height: state.remainingSpace, // 使用剩余空间的值
+              ),
+
+              MyButton(
+                key: _buttonKey,
+                onPressed: viewModel.submitUnit,
+                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: 40, bottom: 30, left: 18, right: 18),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  /// 输入框
+  Widget _buildInputLayout(
+    BuildContext context,
+    SelectUnitState state,
+    String key, {
+    double marginTop = 0,
+    bool? showRightIcon = false, //是否展示右侧的布局
+    Widget? rightWidget, //右侧的布局
+    TextInputType textInputType = TextInputType.number,
+    String? errorText,
+    bool obscureText = false,
+    TextInputAction textInputAction = TextInputAction.done,
+    Function? onSubmit,
+  }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['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,
+      ),
+    );
+  }
+}

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

@@ -0,0 +1,47 @@
+import 'package:flutter/material.dart';
+
+class SelectUnitState {
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  double remainingSpace;
+
+  // ===================================  Begin  ↓  ===================================
+
+  SelectUnitState({
+    this.remainingSpace = 0,
+    Map<String, Map<String, dynamic>>? formData,
+  }) : formData = formData ??
+            {
+              'block': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': '',
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'unit': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': '',
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'room': {
+                'value': '',
+                'controller': TextEditingController(),
+                'hintText': '',
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+            };
+
+  SelectUnitState copyWith({
+    double? remainingSpace,
+  }) {
+    return SelectUnitState(
+      remainingSpace: remainingSpace ?? this.remainingSpace,
+    );
+  }
+
+}

+ 24 - 0
packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.dart

@@ -0,0 +1,24 @@
+import 'package:cpt_auth/modules/select_role/select_role_page.dart';
+import 'package:cpt_auth/modules/select_unit/select_unit_state.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+part 'select_unit_view_model.g.dart';
+
+@riverpod
+class SelectUnitViewModel extends _$SelectUnitViewModel {
+
+  @override
+  SelectUnitState build() {
+    return SelectUnitState();
+  }
+
+  /// 提交选择的街道与单元
+  void submitUnit() {
+    SelectRolePage.startInstance();
+  }
+
+  void setRemainingSpace(double remainingSpace) {
+    state = state.copyWith(remainingSpace: remainingSpace);
+  }
+
+}

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

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'select_unit_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$selectUnitViewModelHash() =>
+    r'f31ffde34c823cf1b3ab7477ddcfda312ccce307';
+
+/// See also [SelectUnitViewModel].
+@ProviderFor(SelectUnitViewModel)
+final selectUnitViewModelProvider =
+    AutoDisposeNotifierProvider<SelectUnitViewModel, SelectUnitState>.internal(
+  SelectUnitViewModel.new,
+  name: r'selectUnitViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$selectUnitViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$SelectUnitViewModel = AutoDisposeNotifier<SelectUnitState>;
+// 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/sing_up_success/sign_up_success_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'sign_up_success_view_model.dart';
 // **************************************************************************
 
 String _$signUpSuccessViewModelHash() =>
-    r'2f571b709af1af896a291c7515d60df05e629aa7';
+    r'715f2ae03093839694f7336d2cf8f0b57ce65d95';
 
 /// See also [SignUpSuccessViewModel].
 @ProviderFor(SignUpSuccessViewModel)

+ 1 - 1
packages/cpt_auth/lib/modules/sing_up_verify/sign_up_verify_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'sign_up_verify_view_model.dart';
 // **************************************************************************
 
 String _$signUpVerifyViewModelHash() =>
-    r'505c17b6c8fee69bdc0758c329ecdd14dcb8da3c';
+    r'3ed4563220e5e1ae25ff7650c8d005e496e68334';
 
 /// See also [SignUpVerifyViewModel].
 @ProviderFor(SignUpVerifyViewModel)

+ 160 - 0
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_page.dart

@@ -0,0 +1,160 @@
+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_text_view.dart';
+import 'package:plugin_platform/platform_export.dart';
+
+import '../../router/page/auth_page_router.dart';
+import 'tenant_doc_view_model.dart';
+
+@RoutePage()
+class TenantDocPage extends HookConsumerWidget {
+  TenantDocPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(TenantDocPageRoute());
+    } else {
+      appRouter.push(TenantDocPageRoute());
+    }
+  }
+
+  // 为需要测量的控件创建 GlobalKey
+  final GlobalKey _appbarKey = GlobalKey();
+  final GlobalKey _titleKey = GlobalKey();
+  final GlobalKey _descriptionKey = GlobalKey();
+  final GlobalKey _description1Key = GlobalKey();
+  final GlobalKey _description2Key = GlobalKey();
+  final GlobalKey _nineGridKey = GlobalKey();
+  final GlobalKey _buttonKey = GlobalKey();
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(tenantDocViewModelProvider.notifier);
+    final state = ref.watch(tenantDocViewModelProvider);
+
+    // 获取屏幕高度
+    final screenHeight = MediaQuery.of(context).size.height;
+    final statusBarHeight = MediaQuery.of(context).padding.top;
+    final navigationBarHeight = MediaQuery.of(context).padding.bottom;
+
+    useEffect(() {
+      double usedHeight = 0;
+      // 组件挂载时执行,获取控件高度
+      WidgetsBinding.instance.addPostFrameCallback((_) {
+        // 获取各个控件的高度
+        usedHeight += _appbarKey.currentContext?.size?.height ?? 0;
+        usedHeight += _titleKey.currentContext?.size?.height ?? 0;
+        usedHeight += _descriptionKey.currentContext?.size?.height ?? 0;
+        usedHeight += _description1Key.currentContext?.size?.height ?? 0;
+        usedHeight += _description2Key.currentContext?.size?.height ?? 0;
+        usedHeight += _nineGridKey.currentContext?.size?.height ?? 0;
+        usedHeight += _buttonKey.currentContext?.size?.height ?? 0;
+
+        // 计算剩余空间
+        double remainingSpace = screenHeight - statusBarHeight - navigationBarHeight - usedHeight - 23 - 21;
+
+        Log.d("计算剩余空间:$remainingSpace");
+
+        if (remainingSpace > 0) {
+          // 设置一个状态来存储剩余空间的高度
+          viewModel.setRemainingSpace(remainingSpace);
+        }
+      });
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, "", key: _appbarKey),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: Container(
+        padding: const EdgeInsets.symmetric(horizontal: 15),
+        width: double.infinity,
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            MyTextView(
+              key: _titleKey,
+              S.current.upload_documents,
+              fontSize: 23.5,
+              marginTop: 23,
+              marginBottom: 21,
+              textAlign: TextAlign.center,
+              isFontMedium: true,
+              textColor: context.appColors.textBlack,
+            ),
+
+            MyTextView(
+              key: _descriptionKey,
+              S.current.upload_doc_desc,
+              fontSize: 15,
+              isFontMedium: true,
+              textColor: context.appColors.textBlack,
+            ),
+
+            MyTextView(
+              key: _description1Key,
+              S.current.upload_doc_desc1,
+              fontSize: 15,
+              marginTop: 22,
+              isFontMedium: true,
+              textColor: context.appColors.textBlack,
+            ),
+
+            MyTextView(
+              key: _description2Key,
+              S.current.upload_doc_desc2,
+              fontSize: 15,
+              marginTop: 22,
+              marginBottom: 24,
+              isFontMedium: true,
+              textColor: context.appColors.textBlack,
+            ),
+
+            ImageNineGrid(
+              key: _nineGridKey,
+              isSelectEnable: true,
+              maxImages: 3,
+              spacing: 10,
+              aspectRatio: 108 / 80,
+              initialImages: [],
+              onImagesChanged: (list) {
+                viewModel.setDocList(list);
+              },
+            ),
+
+            SizedBox(
+              height: state.remainingSpace, // 使用剩余空间的值
+            ),
+
+            //底部的按钮
+            MyButton(
+              key: _buttonKey,
+              onPressed: viewModel.submitDoc,
+              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: 30, bottom: 30, left: 18, right: 18),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 22 - 0
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_state.dart

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

+ 32 - 0
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.dart

@@ -0,0 +1,32 @@
+
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+import 'tenant_doc_state.dart';
+
+part 'tenant_doc_view_model.g.dart';
+
+@riverpod
+class TenantDocViewModel extends _$TenantDocViewModel {
+
+  @override
+  TenantDocState build(){
+    return const TenantDocState(docList: []);
+  }
+
+  //设置已选中的文件数组
+  void setDocList(List<String> list){
+    state = state.copyWith(docList: list);
+  }
+
+  //提交文件
+  void submitDoc() {
+
+    ToastEngine.show("请求接口上传文件:${state.docList}");
+  }
+
+  void setRemainingSpace(double remainingSpace) {
+    state = state.copyWith(remainingSpace: remainingSpace);
+  }
+
+}

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

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'tenant_doc_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$tenantDocViewModelHash() =>
+    r'8283e1970743d66a871e1145e15ffd3177d3a42b';
+
+/// See also [TenantDocViewModel].
+@ProviderFor(TenantDocViewModel)
+final tenantDocViewModelProvider =
+    AutoDisposeNotifierProvider<TenantDocViewModel, TenantDocState>.internal(
+  TenantDocViewModel.new,
+  name: r'tenantDocViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$tenantDocViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$TenantDocViewModel = AutoDisposeNotifier<TenantDocState>;
+// 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

+ 2 - 1
packages/cpt_auth/lib/router/component/auth_component_service.dart

@@ -9,6 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 
 import '../../modules/auth_login/auth_login_page.dart';
+import '../../modules/select_estate/select_estate_page.dart';
 
 part 'auth_component_service.g.dart';
 
@@ -25,6 +26,6 @@ class AuthComponentService extends AuthService {
 
   @override
   void startResetPasswordPage() {
-    ForgotInputPage.startInstance();
+    SelectEstatePage.startInstance();
   }
 }

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

@@ -9,6 +9,10 @@ import '../../modules/forgot_verify/forgot_verify_page.dart';
 import '../../modules/sign_up/sign_up_page.dart';
 import '../../modules/sing_up_verify/sign_up_verify_page.dart';
 import '../../modules/sing_up_success/sign_up_success_page.dart';
+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';
 
 
 
@@ -27,5 +31,9 @@ class AuthPageRouter extends _$AuthPageRouter {
     CustomRoute(page: SignUpPageRoute.page, path: RouterPath.authSignUp, transitionsBuilder: applySlideTransition),
     CustomRoute(page: SignUpVerifyPageRoute.page, path: RouterPath.authSignUpVerify, transitionsBuilder: applySlideTransition),
     CustomRoute(page: SignUpSuccessPageRoute.page, path: RouterPath.authSignUpSuccess, transitionsBuilder: applySlideTransition),
+    CustomRoute(page: SelectEstatePageRoute.page, path: RouterPath.authSelectEstate, transitionsBuilder: applySlideTransition),
+    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),
   ];
 }

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

@@ -33,6 +33,28 @@ abstract class _$AuthPageRouter extends RootStackRouter {
         child: const ForgotVerifyPage(),
       );
     },
+    SelectEstatePageRoute.name: (routeData) {
+      final args = routeData.argsAs<SelectEstatePageRouteArgs>(
+          orElse: () => const SelectEstatePageRouteArgs());
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: SelectEstatePage(key: args.key),
+      );
+    },
+    SelectRolePageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const SelectRolePage(),
+      );
+    },
+    SelectUnitPageRoute.name: (routeData) {
+      final args = routeData.argsAs<SelectUnitPageRouteArgs>(
+          orElse: () => const SelectUnitPageRouteArgs());
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: SelectUnitPage(key: args.key),
+      );
+    },
     SignUpPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
@@ -51,6 +73,14 @@ abstract class _$AuthPageRouter extends RootStackRouter {
         child: const SignUpVerifyPage(),
       );
     },
+    TenantDocPageRoute.name: (routeData) {
+      final args = routeData.argsAs<TenantDocPageRouteArgs>(
+          orElse: () => const TenantDocPageRouteArgs());
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: TenantDocPage(key: args.key),
+      );
+    },
   };
 }
 
@@ -97,6 +127,78 @@ class ForgotVerifyPageRoute extends PageRouteInfo<void> {
 }
 
 /// generated route for
+/// [SelectEstatePage]
+class SelectEstatePageRoute extends PageRouteInfo<SelectEstatePageRouteArgs> {
+  SelectEstatePageRoute({
+    Key? key,
+    List<PageRouteInfo>? children,
+  }) : super(
+          SelectEstatePageRoute.name,
+          args: SelectEstatePageRouteArgs(key: key),
+          initialChildren: children,
+        );
+
+  static const String name = 'SelectEstatePageRoute';
+
+  static const PageInfo<SelectEstatePageRouteArgs> page =
+      PageInfo<SelectEstatePageRouteArgs>(name);
+}
+
+class SelectEstatePageRouteArgs {
+  const SelectEstatePageRouteArgs({this.key});
+
+  final Key? key;
+
+  @override
+  String toString() {
+    return 'SelectEstatePageRouteArgs{key: $key}';
+  }
+}
+
+/// generated route for
+/// [SelectRolePage]
+class SelectRolePageRoute extends PageRouteInfo<void> {
+  const SelectRolePageRoute({List<PageRouteInfo>? children})
+      : super(
+          SelectRolePageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'SelectRolePageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [SelectUnitPage]
+class SelectUnitPageRoute extends PageRouteInfo<SelectUnitPageRouteArgs> {
+  SelectUnitPageRoute({
+    Key? key,
+    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}';
+  }
+}
+
+/// generated route for
 /// [SignUpPage]
 class SignUpPageRoute extends PageRouteInfo<void> {
   const SignUpPageRoute({List<PageRouteInfo>? children})
@@ -137,3 +239,32 @@ class SignUpVerifyPageRoute extends PageRouteInfo<void> {
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }
+
+/// generated route for
+/// [TenantDocPage]
+class TenantDocPageRoute extends PageRouteInfo<TenantDocPageRouteArgs> {
+  TenantDocPageRoute({
+    Key? key,
+    List<PageRouteInfo>? children,
+  }) : super(
+          TenantDocPageRoute.name,
+          args: TenantDocPageRouteArgs(key: key),
+          initialChildren: children,
+        );
+
+  static const String name = 'TenantDocPageRoute';
+
+  static const PageInfo<TenantDocPageRouteArgs> page =
+      PageInfo<TenantDocPageRouteArgs>(name);
+}
+
+class TenantDocPageRouteArgs {
+  const TenantDocPageRouteArgs({this.key});
+
+  final Key? key;
+
+  @override
+  String toString() {
+    return 'TenantDocPageRouteArgs{key: $key}';
+  }
+}

+ 7 - 7
packages/cpt_auth/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_community/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_facility/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_form/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_main/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_notice_board/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_payment/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_profile/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_property/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_rewards/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cpt_services/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 6 - 6
packages/cs_domain/pubspec_overrides.yaml

@@ -1,14 +1,14 @@
 # melos_managed_dependency_overrides: cs_resources,plugin_platform,shared,widgets,plugin_basic,router
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 7 - 7
packages/cs_initializer/pubspec_overrides.yaml

@@ -1,16 +1,16 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_basic,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_basic:
-    path: ..\\cs_plugin_basic
+    path: ../cs_plugin_basic
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 6 - 6
packages/cs_plugin_basic/pubspec_overrides.yaml

@@ -1,14 +1,14 @@
 # melos_managed_dependency_overrides: cs_resources,domain,plugin_platform,router,shared,widgets
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   domain:
-    path: ..\\cs_domain
+    path: ../cs_domain
   plugin_platform:
-    path: ..\\cs_plugin_platform
+    path: ../cs_plugin_platform
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

+ 137 - 0
packages/cs_plugin_platform/lib/engine/image/image_nine_grid.dart

@@ -0,0 +1,137 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/media/image_picker_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:widgets/my_text_view.dart';
+import 'image_preview.dart';
+import 'package:cs_resources/generated/l10n.dart';
+
+class ImageNineGrid extends StatefulWidget {
+  final bool isSelectEnable; // 是否能选择
+  final List<String> initialImages; // 初始化图片集合
+  final int maxImages; // 最多选择的图片
+  final double aspectRatio; // 宽高比
+  final double spacing; // 横向竖向的间距
+  final double borderRadius; //整体边框圆角
+  final Function(List<String>) onImagesChanged;
+
+  const ImageNineGrid({
+    Key? key,
+    this.isSelectEnable = true,
+    this.maxImages = 9,
+    this.aspectRatio = 1.0,
+    this.spacing = 8,
+    this.borderRadius = 5.0,
+    required this.initialImages,
+    required this.onImagesChanged,
+  }) : super(key: key);
+
+  @override
+  _ImageNineGridState createState() => _ImageNineGridState();
+}
+
+class _ImageNineGridState extends State<ImageNineGrid> {
+  late List<String> _images;
+
+  @override
+  void initState() {
+    super.initState();
+    _images = List.from(widget.initialImages);
+  }
+
+  // 选择图片
+  Future<void> _pickImage() async {
+    ImagePickerUtils().show(context, (filePath) {
+      if (Utils.isNotEmpty(filePath)) {
+        setState(() {
+          _images.add(filePath);
+        });
+        widget.onImagesChanged(_images);
+      }
+    });
+  }
+
+  // 删除图片
+  void _removeImage(int index) {
+    setState(() {
+      _images.removeAt(index);
+    });
+    widget.onImagesChanged(_images);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final gridChildren = List<Widget>.generate(
+      _images.length,
+      (index) => Stack(
+        children: [
+          ClipRRect(
+            borderRadius: BorderRadius.circular(widget.borderRadius), // 圆角半径
+            child: Hero(
+              tag: _images[index],
+              child: MyLoadImage(
+                _images[index],
+                width: double.infinity,
+                height: double.infinity,
+                fit: BoxFit.cover,
+              ).onTap(() {
+                //预览图片
+                ImagePreviewEngine.singleImagePreview(context, _images[index], heroTag: _images[index]);
+              }),
+            ),
+          ),
+          Positioned(
+            top: 0,
+            right: 0,
+            child: Visibility(
+              visible: widget.isSelectEnable,
+              child: const MyAssetImage(Assets.baseLibDialogDeleteIcon, width: 24, height: 24).onTap(() {
+                if (widget.isSelectEnable) {
+                  _removeImage(index);
+                }
+              }, padding: 5),
+            ),
+          ),
+        ],
+      ),
+    );
+
+    if (widget.isSelectEnable && _images.length < widget.maxImages) {
+      gridChildren.add(
+        GestureDetector(
+          onTap: _pickImage,
+          child: Container(
+            decoration: BoxDecoration(
+              color: context.appColors.imgGrayBg,
+              borderRadius: BorderRadius.circular(widget.borderRadius), // 圆角半径
+            ),
+            child: Column(
+              mainAxisAlignment: MainAxisAlignment.center,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                const MyAssetImage(Assets.baseLibImageAddIcon, width: 211.5, height: 21.5),
+                MyTextView(S.current.upload, fontSize: 10, isFontMedium: true, marginTop: 3, textColor: context.appColors.textDarkGray999),
+              ],
+            ),
+          ),
+        ),
+      );
+    }
+
+    return GridView.builder(
+      shrinkWrap: true,
+      physics: const NeverScrollableScrollPhysics(),
+      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
+        crossAxisCount: 3,
+        childAspectRatio: widget.aspectRatio,
+        mainAxisSpacing: widget.spacing,
+        crossAxisSpacing: widget.spacing,
+      ),
+      itemCount: gridChildren.length,
+      itemBuilder: (context, index) => gridChildren[index],
+    );
+  }
+}

+ 14 - 14
packages/cs_plugin_platform/lib/engine/permission/permission_engine.dart

@@ -40,8 +40,8 @@ class PermissionEngine {
         Log.d("相册无授权,去设置");
         DialogEngine.show(
           widget: AppDefaultDialog(
-            title: "提示",
-            message: '无相册权限,前往设置',
+            title: "Alert",
+            message: 'No album permission, go to settings?',
             confirmAction: () {
               PhotoManager.openSetting();
             },
@@ -60,7 +60,7 @@ class PermissionEngine {
         var permissionRequestFuture = PhotoManager.requestPermissionExtend();
 
         // 延迟500毫秒的Future
-        var delayFuture = Future.delayed(Duration(milliseconds: 500), () => 'delay');
+        var delayFuture = Future.delayed(const Duration(milliseconds: 500), () => 'delay');
 
         // 使用Future.any等待上述两个Future中的任何一个完成
         var firstCompleted = await Future.any([permissionRequestFuture, delayFuture]);
@@ -69,7 +69,7 @@ class PermissionEngine {
         if (firstCompleted == 'delay') {
           Log.d("判断响应结果:1");
           // 如果是延迟Future完成了,表示500毫秒内没有获得权限响应,显示对话框
-          _showPermissionDialog("“YYBusiness”想访问你的多媒体相册 用于图片上传,图片保存等功能,请允许我获取您的权限");
+          _showPermissionDialog("“YYHome” would like to access your multimedia album for functions such as image uploading and saving. Please allow me to obtain your permission");
           // 再次等待权限请求结果
           ps = await permissionRequestFuture;
           DialogEngine.dismiss(tag: "permission");
@@ -87,8 +87,8 @@ class PermissionEngine {
           // 权限被拒绝
           await DialogEngine.show(
             widget: AppDefaultDialog(
-                message: "请到您的手机设置打开相册的权限",
-                title: "提醒",
+                message: "Please set the permission to open the photo album on your phone",
+                title: "Alert",
                 confirmAction: () {
                   openAppSettings();
                 }),
@@ -110,7 +110,7 @@ class PermissionEngine {
       var permissionRequestFuture = Permission.camera.request();
 
       // 延迟500毫秒的Future
-      var delayFuture = Future.delayed(Duration(milliseconds: 500), () => 'delay');
+      var delayFuture = Future.delayed(const Duration(milliseconds: 500), () => 'delay');
 
       // 使用Future.any等待上述两个Future中的任何一个完成
       var firstCompleted = await Future.any([permissionRequestFuture, delayFuture]);
@@ -118,7 +118,7 @@ class PermissionEngine {
       // 判断响应结果
       if (firstCompleted == 'delay') {
         // 如果是延迟Future完成了,表示500毫秒内没有获得权限响应,显示对话框
-        _showPermissionDialog("“YYBusiness”申请调用您的相机权限 用于使用拍摄头像,图片上传保存等功能,请允许我获取您的权限");
+        _showPermissionDialog("“YYHome” requests to use your camera permission for functions such as taking avatars, uploading and saving images. Please allow me to obtain your permission");
         // 再次等待权限请求结果
         status = await permissionRequestFuture;
         DialogEngine.dismiss(tag: "permission");
@@ -135,8 +135,8 @@ class PermissionEngine {
         // 权限被拒绝
         await DialogEngine.show(
           widget: AppDefaultDialog(
-              message: "请到您的手机设置打开相机的权限",
-              title: "提醒",
+              message: "Please set the permission to open the camera on your phone",
+              title: "Alert",
               confirmAction: () {
                 openAppSettings();
               }),
@@ -157,7 +157,7 @@ class PermissionEngine {
       var permissionRequestFuture = Permission.location.request();
 
       // 延迟500毫秒的Future
-      var delayFuture = Future.delayed(Duration(milliseconds: 500), () => 'delay');
+      var delayFuture = Future.delayed(const Duration(milliseconds: 500), () => 'delay');
 
       // 使用Future.any等待上述两个Future中的任何一个完成
       var firstCompleted = await Future.any([permissionRequestFuture, delayFuture]);
@@ -165,7 +165,7 @@ class PermissionEngine {
       // 判断响应结果
       if (firstCompleted == 'delay') {
         // 如果是延迟Future完成了,表示500毫秒内没有获得权限响应,显示对话框
-        _showPermissionDialog("“YYBusiness”想访问您的定位权限获取您的位置来推荐附近的工作");
+        _showPermissionDialog("“YYHome” want to access your location permission to obtain your location and recommend nearby information");
         // 再次等待权限请求结果
         status = await permissionRequestFuture;
         DialogEngine.dismiss(tag: "permission");
@@ -183,8 +183,8 @@ class PermissionEngine {
         // 权限被拒绝
         await DialogEngine.show(
           widget: AppDefaultDialog(
-              message: "请到您的手机设置打开定位的权限",
-              title: "提醒",
+              message: "Please go to your phone settings to enable location permission",
+              title: "Alert",
               confirmAction: () {
                 openAppSettings();
               }),

+ 2 - 1
packages/cs_plugin_platform/lib/platform_export.dart

@@ -1,2 +1,3 @@
 export 'package:dio/dio.dart';
-export 'package:permission_handler/permission_handler.dart';
+export 'package:permission_handler/permission_handler.dart';
+export 'engine/image/image_nine_grid.dart';

+ 4 - 4
packages/cs_plugin_platform/pubspec_overrides.yaml

@@ -1,10 +1,10 @@
 # melos_managed_dependency_overrides: cs_resources,shared,widgets,router
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared
   widgets:
-    path: ..\\cs_widgets
+    path: ../cs_widgets

packages/cs_resources/assets/auth/image_add_icon.webp → packages/cs_resources/assets/base_lib/image_add_icon.webp


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

@@ -8,7 +8,6 @@ class Assets {
   static const String authCountrySg = 'assets/auth/country_sg.webp';
   static const String authForgotInputEmailPhoneImg = 'assets/auth/forgot_input_email_phone_img.webp';
   static const String authForgotResetPasswordImg = 'assets/auth/forgot_reset_password_img.webp';
-  static const String authImageAddIcon = 'assets/auth/image_add_icon.webp';
   static const String authPasswordHide = 'assets/auth/password_hide.webp';
   static const String authPasswordShow = 'assets/auth/password_show.webp';
   static const String authSignUpInputImg = 'assets/auth/sign_up_input_img.webp';
@@ -19,6 +18,7 @@ class Assets {
   static const String baseLibBlackBack = 'assets/base_lib/black_back.webp';
   static const String baseLibDialogBlueDeleteIcon = 'assets/base_lib/dialog_blue_delete_icon.webp';
   static const String baseLibDialogDeleteIcon = 'assets/base_lib/dialog_delete_icon.webp';
+  static const String baseLibImageAddIcon = 'assets/base_lib/image_add_icon.webp';
   static const String baseLibImageDefaultPlaceholder = 'assets/base_lib/image_default_placeholder.png';
   static const String baseLibItemMoreIcon = 'assets/base_lib/item_more_icon.webp';
   static const String baseLibSearchIcon = 'assets/base_lib/search_icon.webp';

+ 51 - 1
packages/cs_resources/lib/generated/intl/messages_en.dart

@@ -25,6 +25,13 @@ class MessageLookup extends MessageLookupByLibrary {
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
         "agree_to": MessageLookupByLibrary.simpleMessage("Agree to"),
+        "block": MessageLookupByLibrary.simpleMessage("Block"),
+        "block_desc": MessageLookupByLibrary.simpleMessage(
+            "Block refers to the street number of the unit\'s official mailing address"),
+        "block_example": MessageLookupByLibrary.simpleMessage(
+            "123 Example Road #08-08 Country 123456"),
+        "block_example_desc": MessageLookupByLibrary.simpleMessage(
+            "123 is the block number #08-08 is the unit number"),
         "confirm_password":
             MessageLookupByLibrary.simpleMessage("Confirm Password"),
         "create_new_yy_home_account":
@@ -32,6 +39,10 @@ class MessageLookup extends MessageLookupByLibrary {
         "did_not_receive":
             MessageLookupByLibrary.simpleMessage("Did Not Receive?"),
         "email": MessageLookupByLibrary.simpleMessage("Email"),
+        "estate_name_desc": MessageLookupByLibrary.simpleMessage(
+            "Tell us the name of the estateor building you are applying to"),
+        "estate_or_building_name":
+            MessageLookupByLibrary.simpleMessage("Estate or Building Name?"),
         "facility": MessageLookupByLibrary.simpleMessage("Facility"),
         "first_name": MessageLookupByLibrary.simpleMessage("First Name"),
         "forgot_password":
@@ -49,6 +60,19 @@ class MessageLookup extends MessageLookupByLibrary {
         "notice_board": MessageLookupByLibrary.simpleMessage("Notice Board"),
         "notification": MessageLookupByLibrary.simpleMessage("Notification"),
         "other": MessageLookupByLibrary.simpleMessage("Other"),
+        "owner": MessageLookupByLibrary.simpleMessage("Owner"),
+        "owner_or_tenant":
+            MessageLookupByLibrary.simpleMessage("Are you an owner or tenant?"),
+        "owners_desc1": MessageLookupByLibrary.simpleMessage(
+            "My name is in the strata title"),
+        "owners_desc2": MessageLookupByLibrary.simpleMessage(
+            "My name is in the strata title and l have rented out my unit"),
+        "owners_desc3": MessageLookupByLibrary.simpleMessage(
+            "I live in the same household as the named owner"),
+        "owners_desc4": MessageLookupByLibrary.simpleMessage(
+            "I am the shareholder of the company that owns the unit"),
+        "owners_desc5": MessageLookupByLibrary.simpleMessage(
+            "The Management will verify your application accordingly"),
         "password": MessageLookupByLibrary.simpleMessage("Password"),
         "password_format":
             MessageLookupByLibrary.simpleMessage("8 Digits Alphanumeric"),
@@ -66,12 +90,38 @@ class MessageLookup extends MessageLookupByLibrary {
             "Now, let\'s get you connected to your estate and community"),
         "sign_up_verify_txt": MessageLookupByLibrary.simpleMessage(
             "We have sent you an SMS verification code Please enter it below"),
+        "tenant": MessageLookupByLibrary.simpleMessage("Tenant"),
+        "tenants_desc1": MessageLookupByLibrary.simpleMessage(
+            "My name is in the lease agreement"),
+        "tenants_desc2": MessageLookupByLibrary.simpleMessage(
+            "I live in the same household as the named tenant"),
+        "tenants_desc3": MessageLookupByLibrary.simpleMessage(
+            "I am the tenant of the company that rented the unit"),
+        "tenants_desc4": MessageLookupByLibrary.simpleMessage(
+            "The Management will verify your application accordingly"),
         "terms_of_service":
             MessageLookupByLibrary.simpleMessage("Terms of Service"),
         "tries_left": MessageLookupByLibrary.simpleMessage("Tries Left"),
+        "type_here": MessageLookupByLibrary.simpleMessage("Type Here"),
+        "unit_number": MessageLookupByLibrary.simpleMessage("Unit Number"),
+        "upload": MessageLookupByLibrary.simpleMessage("Upload"),
+        "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_documents":
+            MessageLookupByLibrary.simpleMessage("Upload Documents"),
         "verification_code":
             MessageLookupByLibrary.simpleMessage("Verification Code"),
         "welcome_name": m0,
-        "you_have": MessageLookupByLibrary.simpleMessage("You have")
+        "who_are_owners":
+            MessageLookupByLibrary.simpleMessage("Who are owners?"),
+        "who_are_tenants":
+            MessageLookupByLibrary.simpleMessage("Who are tenants?"),
+        "you_have": MessageLookupByLibrary.simpleMessage("You have"),
+        "yy_home_accounts":
+            MessageLookupByLibrary.simpleMessage("YY Home Accounts")
       };
 }

+ 37 - 1
packages/cs_resources/lib/generated/intl/messages_zh_CN.dart

@@ -25,11 +25,21 @@ class MessageLookup extends MessageLookupByLibrary {
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
         "agree_to": MessageLookupByLibrary.simpleMessage("同意"),
+        "block": MessageLookupByLibrary.simpleMessage("街区"),
+        "block_desc": MessageLookupByLibrary.simpleMessage("街区是指单位官方邮编街道号"),
+        "block_example":
+            MessageLookupByLibrary.simpleMessage("123 示例路 #08-08 国家 123456"),
+        "block_example_desc":
+            MessageLookupByLibrary.simpleMessage("123 是街区地址邮编 #08-08 是单元号码"),
         "confirm_password": MessageLookupByLibrary.simpleMessage("确认密码"),
         "create_new_yy_home_account":
             MessageLookupByLibrary.simpleMessage("创建新的 YY Home 账户"),
         "did_not_receive": MessageLookupByLibrary.simpleMessage("没有收到验证码?"),
         "email": MessageLookupByLibrary.simpleMessage("邮箱"),
+        "estate_name_desc":
+            MessageLookupByLibrary.simpleMessage("告诉我们您申请的公寓楼的名称"),
+        "estate_or_building_name":
+            MessageLookupByLibrary.simpleMessage("房产或建筑名称?"),
         "facility": MessageLookupByLibrary.simpleMessage("设施"),
         "first_name": MessageLookupByLibrary.simpleMessage("名"),
         "forgot_password": MessageLookupByLibrary.simpleMessage("忘记密码?"),
@@ -44,6 +54,14 @@ class MessageLookup extends MessageLookupByLibrary {
         "notice_board": MessageLookupByLibrary.simpleMessage("消息板"),
         "notification": MessageLookupByLibrary.simpleMessage("通知"),
         "other": MessageLookupByLibrary.simpleMessage("其他"),
+        "owner": MessageLookupByLibrary.simpleMessage("业主"),
+        "owner_or_tenant": MessageLookupByLibrary.simpleMessage("您是业主还是租户?"),
+        "owners_desc1": MessageLookupByLibrary.simpleMessage("我的名字在分层标题上"),
+        "owners_desc2":
+            MessageLookupByLibrary.simpleMessage("我的名字在分层标题上,并且我已经把我的单元租出去了"),
+        "owners_desc3": MessageLookupByLibrary.simpleMessage("我和名字的主人住在同一个家庭"),
+        "owners_desc4": MessageLookupByLibrary.simpleMessage("我是拥有该单元的公司的股东"),
+        "owners_desc5": MessageLookupByLibrary.simpleMessage("管理员将相应地验证您的申请"),
         "password": MessageLookupByLibrary.simpleMessage("密码"),
         "password_format": MessageLookupByLibrary.simpleMessage("8位数字或字母"),
         "payment": MessageLookupByLibrary.simpleMessage("支付"),
@@ -59,10 +77,28 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("现在,让我们把你和你的社区关联起来"),
         "sign_up_verify_txt":
             MessageLookupByLibrary.simpleMessage("我们已经向您发送了短信验证码,请在下面输入"),
+        "tenant": MessageLookupByLibrary.simpleMessage("租户"),
+        "tenants_desc1": MessageLookupByLibrary.simpleMessage("我的名字在租赁协议上"),
+        "tenants_desc2": MessageLookupByLibrary.simpleMessage("我和指定的租户住在同一个家庭"),
+        "tenants_desc3": MessageLookupByLibrary.simpleMessage("我是租用该单元的公司的租户"),
+        "tenants_desc4": MessageLookupByLibrary.simpleMessage("管理员将相应地验证您的申请"),
         "terms_of_service": MessageLookupByLibrary.simpleMessage("服务条款"),
         "tries_left": MessageLookupByLibrary.simpleMessage("次尝试机会"),
+        "type_here": MessageLookupByLibrary.simpleMessage("在此输入"),
+        "unit_number": MessageLookupByLibrary.simpleMessage("单元"),
+        "upload": MessageLookupByLibrary.simpleMessage("上传"),
+        "upload_doc_desc": MessageLookupByLibrary.simpleMessage(
+            "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息"),
+        "upload_doc_desc1": MessageLookupByLibrary.simpleMessage(
+            "(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)"),
+        "upload_doc_desc2":
+            MessageLookupByLibrary.simpleMessage("(2)租赁协议印花税收据"),
+        "upload_documents": MessageLookupByLibrary.simpleMessage("上传文档"),
         "verification_code": MessageLookupByLibrary.simpleMessage("验证码"),
         "welcome_name": m0,
-        "you_have": MessageLookupByLibrary.simpleMessage("你还有")
+        "who_are_owners": MessageLookupByLibrary.simpleMessage("怎样才算业主?"),
+        "who_are_tenants": MessageLookupByLibrary.simpleMessage("怎样才算租户?"),
+        "you_have": MessageLookupByLibrary.simpleMessage("你还有"),
+        "yy_home_accounts": MessageLookupByLibrary.simpleMessage("YY Home 账户")
       };
 }

+ 22 - 1
packages/cs_resources/lib/generated/intl/messages_zh_HK.dart

@@ -25,11 +25,21 @@ class MessageLookup extends MessageLookupByLibrary {
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
         "agree_to": MessageLookupByLibrary.simpleMessage("同意"),
+        "block": MessageLookupByLibrary.simpleMessage("街区"),
+        "block_desc": MessageLookupByLibrary.simpleMessage("街区是指单位官方邮编街道号"),
+        "block_example":
+            MessageLookupByLibrary.simpleMessage("123 示例路 #08-08 国家 123456"),
+        "block_example_desc":
+            MessageLookupByLibrary.simpleMessage("123 是街区地址邮编 #08-08 是单元号码"),
         "confirm_password": MessageLookupByLibrary.simpleMessage("确认密码"),
         "create_new_yy_home_account":
             MessageLookupByLibrary.simpleMessage("创建新的 YY Home 账户"),
         "did_not_receive": MessageLookupByLibrary.simpleMessage("没有收到验证码?"),
         "email": MessageLookupByLibrary.simpleMessage("邮箱"),
+        "estate_name_desc":
+            MessageLookupByLibrary.simpleMessage("告诉我们您申请的公寓楼的名称"),
+        "estate_or_building_name":
+            MessageLookupByLibrary.simpleMessage("房产或建筑名称?"),
         "facility": MessageLookupByLibrary.simpleMessage("設施"),
         "first_name": MessageLookupByLibrary.simpleMessage("名"),
         "forgot_password": MessageLookupByLibrary.simpleMessage("忘记密码?"),
@@ -61,8 +71,19 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("我们已经向您发送了短信验证码,请在下面输入"),
         "terms_of_service": MessageLookupByLibrary.simpleMessage("服务条款"),
         "tries_left": MessageLookupByLibrary.simpleMessage("次尝试机会"),
+        "type_here": MessageLookupByLibrary.simpleMessage("在此输入"),
+        "unit_number": MessageLookupByLibrary.simpleMessage("单元"),
+        "upload": MessageLookupByLibrary.simpleMessage("上传"),
+        "upload_doc_desc": MessageLookupByLibrary.simpleMessage(
+            "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息"),
+        "upload_doc_desc1": MessageLookupByLibrary.simpleMessage(
+            "(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)"),
+        "upload_doc_desc2":
+            MessageLookupByLibrary.simpleMessage("(2)租赁协议印花税收据"),
+        "upload_documents": MessageLookupByLibrary.simpleMessage("上传文档"),
         "verification_code": MessageLookupByLibrary.simpleMessage("验证码"),
         "welcome_name": m0,
-        "you_have": MessageLookupByLibrary.simpleMessage("你还有")
+        "you_have": MessageLookupByLibrary.simpleMessage("你还有"),
+        "yy_home_accounts": MessageLookupByLibrary.simpleMessage("YY Home 账户")
       };
 }

+ 280 - 0
packages/cs_resources/lib/generated/l10n.dart

@@ -390,6 +390,286 @@ class S {
     );
   }
 
+  /// `YY Home Accounts`
+  String get yy_home_accounts {
+    return Intl.message(
+      'YY Home Accounts',
+      name: 'yy_home_accounts',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Block`
+  String get block {
+    return Intl.message(
+      'Block',
+      name: 'block',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Unit Number`
+  String get unit_number {
+    return Intl.message(
+      'Unit Number',
+      name: 'unit_number',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Block refers to the street number of the unit's official mailing address`
+  String get block_desc {
+    return Intl.message(
+      'Block refers to the street number of the unit\'s official mailing address',
+      name: 'block_desc',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `123 Example Road #08-08 Country 123456`
+  String get block_example {
+    return Intl.message(
+      '123 Example Road #08-08 Country 123456',
+      name: 'block_example',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `123 is the block number #08-08 is the unit number`
+  String get block_example_desc {
+    return Intl.message(
+      '123 is the block number #08-08 is the unit number',
+      name: 'block_example_desc',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Estate or Building Name?`
+  String get estate_or_building_name {
+    return Intl.message(
+      'Estate or Building Name?',
+      name: 'estate_or_building_name',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Type Here`
+  String get type_here {
+    return Intl.message(
+      'Type Here',
+      name: 'type_here',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Tell us the name of the estateor building you are applying to`
+  String get estate_name_desc {
+    return Intl.message(
+      'Tell us the name of the estateor building you are applying to',
+      name: 'estate_name_desc',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Are you an owner or tenant?`
+  String get owner_or_tenant {
+    return Intl.message(
+      'Are you an owner or tenant?',
+      name: 'owner_or_tenant',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Owner`
+  String get owner {
+    return Intl.message(
+      'Owner',
+      name: 'owner',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Tenant`
+  String get tenant {
+    return Intl.message(
+      'Tenant',
+      name: 'tenant',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Who are owners?`
+  String get who_are_owners {
+    return Intl.message(
+      'Who are owners?',
+      name: 'who_are_owners',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `My name is in the strata title`
+  String get owners_desc1 {
+    return Intl.message(
+      'My name is in the strata title',
+      name: 'owners_desc1',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `My name is in the strata title and l have rented out my unit`
+  String get owners_desc2 {
+    return Intl.message(
+      'My name is in the strata title and l have rented out my unit',
+      name: 'owners_desc2',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `I live in the same household as the named owner`
+  String get owners_desc3 {
+    return Intl.message(
+      'I live in the same household as the named owner',
+      name: 'owners_desc3',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `I am the shareholder of the company that owns the unit`
+  String get owners_desc4 {
+    return Intl.message(
+      'I am the shareholder of the company that owns the unit',
+      name: 'owners_desc4',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `The Management will verify your application accordingly`
+  String get owners_desc5 {
+    return Intl.message(
+      'The Management will verify your application accordingly',
+      name: 'owners_desc5',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Who are tenants?`
+  String get who_are_tenants {
+    return Intl.message(
+      'Who are tenants?',
+      name: 'who_are_tenants',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `My name is in the lease agreement`
+  String get tenants_desc1 {
+    return Intl.message(
+      'My name is in the lease agreement',
+      name: 'tenants_desc1',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `I live in the same household as the named tenant`
+  String get tenants_desc2 {
+    return Intl.message(
+      'I live in the same household as the named tenant',
+      name: 'tenants_desc2',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `I am the tenant of the company that rented the unit`
+  String get tenants_desc3 {
+    return Intl.message(
+      'I am the tenant of the company that rented the unit',
+      name: 'tenants_desc3',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `The Management will verify your application accordingly`
+  String get tenants_desc4 {
+    return Intl.message(
+      'The Management will verify your application accordingly',
+      name: 'tenants_desc4',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Upload Documents`
+  String get upload_documents {
+    return Intl.message(
+      'Upload Documents',
+      name: 'upload_documents',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financia information`
+  String get upload_doc_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',
+      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 {
+    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',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Upload`
+  String get upload {
+    return Intl.message(
+      'Upload',
+      name: 'upload',
+      desc: '',
+      args: [],
+    );
+  }
+
   /// `Other`
   String get other {
     return Intl.message(

+ 28 - 0
packages/cs_resources/lib/l10n/intl_en.arb

@@ -33,5 +33,33 @@
   "sign_up_success_txt2": "Your username is your email address and please keep your password safe",
   "sign_up_success_txt3": "Now, let's get you connected to your estate and community",
   "get_started": "let's get started",
+  "yy_home_accounts": "YY Home Accounts",
+  "block": "Block",
+  "unit_number": "Unit Number",
+  "block_desc": "Block refers to the street number of the unit's official mailing address",
+  "block_example": "123 Example Road #08-08 Country 123456",
+  "block_example_desc": "123 is the block number #08-08 is the unit number",
+  "estate_or_building_name": "Estate or Building Name?",
+  "type_here": "Type Here",
+  "estate_name_desc": "Tell us the name of the estateor building you are applying to",
+  "owner_or_tenant": "Are you an owner or tenant?",
+  "owner": "Owner",
+  "tenant": "Tenant",
+  "who_are_owners": "Who are owners?",
+  "owners_desc1": "My name is in the strata title",
+  "owners_desc2": "My name is in the strata title and l have rented out my unit",
+  "owners_desc3": "I live in the same household as the named owner",
+  "owners_desc4": "I am the shareholder of the company that owns the unit",
+  "owners_desc5": "The Management will verify your application accordingly",
+  "who_are_tenants": "Who are tenants?",
+  "tenants_desc1": "My name is in the lease agreement",
+  "tenants_desc2": "I live in the same household as the named tenant",
+  "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": "Upload",
   "other": "Other"
 }

+ 28 - 0
packages/cs_resources/lib/l10n/intl_zh_CN.arb

@@ -33,5 +33,33 @@
   "sign_up_success_txt2": "您的用户名是您的电子邮件地址,请保护您的密码安全",
   "sign_up_success_txt3": "现在,让我们把你和你的社区关联起来",
   "get_started": "让我们开始吧",
+  "yy_home_accounts": "YY Home 账户",
+  "block": "街区",
+  "unit_number": "单元",
+  "block_desc": "街区是指单位官方邮编街道号",
+  "block_example": "123 示例路 #08-08 国家 123456",
+  "block_example_desc": "123 是街区地址邮编 #08-08 是单元号码",
+  "estate_or_building_name": "房产或建筑名称?",
+  "type_here": "在此输入",
+  "estate_name_desc": "告诉我们您申请的公寓楼的名称",
+  "owner_or_tenant": "您是业主还是租户?",
+  "owner": "业主",
+  "tenant": "租户",
+  "who_are_owners": "怎样才算业主?",
+  "owners_desc1": "我的名字在分层标题上",
+  "owners_desc2": "我的名字在分层标题上,并且我已经把我的单元租出去了",
+  "owners_desc3": "我和名字的主人住在同一个家庭",
+  "owners_desc4": "我是拥有该单元的公司的股东",
+  "owners_desc5": "管理员将相应地验证您的申请",
+  "who_are_tenants": "怎样才算租户?",
+  "tenants_desc1": "我的名字在租赁协议上",
+  "tenants_desc2": "我和指定的租户住在同一个家庭",
+  "tenants_desc3": "我是租用该单元的公司的租户",
+  "tenants_desc4": "管理员将相应地验证您的申请",
+  "upload_documents": "上传文档",
+  "upload_doc_desc": "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息",
+  "upload_doc_desc1": "(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)",
+  "upload_doc_desc2": "(2)租赁协议印花税收据",
+  "upload": "上传",
   "other": "其他"
 }

+ 14 - 0
packages/cs_resources/lib/l10n/intl_zh_HK.arb

@@ -33,5 +33,19 @@
   "sign_up_success_txt2": "您的用户名是您的电子邮件地址,请保护您的密码安全",
   "sign_up_success_txt3": "现在,让我们把你和你的社区关联起来",
   "get_started": "让我们开始吧",
+  "yy_home_accounts": "YY Home 账户",
+  "block": "街区",
+  "unit_number": "单元",
+  "block_desc": "街区是指单位官方邮编街道号",
+  "block_example": "123 示例路 #08-08 国家 123456",
+  "block_example_desc": "123 是街区地址邮编 #08-08 是单元号码",
+  "estate_or_building_name": "房产或建筑名称?",
+  "type_here": "在此输入",
+  "estate_name_desc": "告诉我们您申请的公寓楼的名称",
+  "upload_documents": "上传文档",
+  "upload_doc_desc": "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息",
+  "upload_doc_desc1": "(1)一份有效的租赁协议,显示您的姓名、单位编号、租赁到期日期和居住者名单(如果适用)",
+  "upload_doc_desc2": "(2)租赁协议印花税收据",
+  "upload": "上传",
   "other": "其他"
 }

+ 35 - 1
packages/cs_resources/lib/theme/app_colors_theme.dart

@@ -19,6 +19,10 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
   static const _colorBDBDBD = Color(0xFFBDBDBD);
   static const _colorF2F2F2 = Color(0xFFF2F2F2);
   static const _colorFE6C00 = Color(0xFFFE6C00);
+  static const _colorD3D3D3 = Color(0xFFD3D3D3);
+  static const _color333333 = Color(0xFF333333);
+  static const _colorF3F3F3 = Color(0xFFF3F3F3);
+  static const _color999999 = Color(0xFF999999);
 
   //暗色主题的一些自定义颜色值
   static const _darkBlackBg = Color(0xFF0F0F0F);
@@ -29,7 +33,7 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
 
   // 页面中真正使用到的颜色名称
   final Color backgroundDefault; //页面背景颜色
-  final Color btnBgDefault;  //按钮背景颜色
+  final Color btnBgDefault; //按钮背景颜色
   final Color searchFiledBorder; //搜索框的边框颜色
   final Color authFiledHint; //输入框默认的提示文本颜色
   final Color authFiledText; //输入框默认的文本颜色
@@ -38,6 +42,12 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
   final Color textBlack; //黑色文本
   final Color textDarkGray; //深灰色 666 文本
   final Color orangeBG; //按钮的橙色背景
+  final Color tabBgSelectedPrimary; //Tab的选中主题色背景
+  final Color tabBgUnSelectedPrimary; //Tab的未选中主题色背景
+  final Color tabTextSelectedPrimary; //Tab的未选中主题色文本
+  final Color tabTextUnSelectedPrimary; //Tab的未选中主题色文本
+  final Color imgGrayBg; //灰色的图片底色背景
+  final Color textDarkGray999; //文本深灰色
 
   // 私有的构造函数
   const AppColorsTheme._internal({
@@ -51,6 +61,12 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
     required this.textBlack,
     required this.textDarkGray,
     required this.orangeBG,
+    required this.tabBgSelectedPrimary,
+    required this.tabBgUnSelectedPrimary,
+    required this.tabTextSelectedPrimary,
+    required this.tabTextUnSelectedPrimary,
+    required this.imgGrayBg,
+    required this.textDarkGray999,
   });
 
   // 浅色主题工厂方法
@@ -66,6 +82,12 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
       textBlack: Colors.black,
       textDarkGray: _color666666,
       orangeBG: _colorFE6C00,
+      tabBgSelectedPrimary: _colorPrimary,
+      tabBgUnSelectedPrimary: _colorD3D3D3,
+      tabTextSelectedPrimary: Colors.white,
+      tabTextUnSelectedPrimary: _color333333,
+      imgGrayBg: _colorF3F3F3,
+      textDarkGray999: _color999999,
     );
   }
 
@@ -82,6 +104,12 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
       textBlack: Colors.white,
       textDarkGray: Colors.white,
       orangeBG: _darkBlackItem,
+      tabBgSelectedPrimary: Colors.white,
+      tabBgUnSelectedPrimary: _darkBlackItem,
+      tabTextSelectedPrimary: Colors.black,
+      tabTextUnSelectedPrimary: Colors.white,
+      imgGrayBg: _darkBlackItem,
+      textDarkGray999: Colors.white,
     );
   }
 
@@ -107,6 +135,12 @@ class AppColorsTheme extends ThemeExtension<AppColorsTheme> {
       textBlack: Color.lerp(textBlack, other.textBlack, t)!,
       textDarkGray: Color.lerp(textDarkGray, other.textDarkGray, t)!,
       orangeBG: Color.lerp(orangeBG, other.orangeBG, t)!,
+      tabBgSelectedPrimary: Color.lerp(tabBgSelectedPrimary, other.tabBgSelectedPrimary, t)!,
+      tabBgUnSelectedPrimary: Color.lerp(tabBgUnSelectedPrimary, other.tabBgUnSelectedPrimary, t)!,
+      tabTextSelectedPrimary: Color.lerp(tabTextSelectedPrimary, other.tabTextSelectedPrimary, t)!,
+      tabTextUnSelectedPrimary: Color.lerp(tabTextUnSelectedPrimary, other.tabTextUnSelectedPrimary, t)!,
+      imgGrayBg: Color.lerp(imgGrayBg, other.imgGrayBg, t)!,
+      textDarkGray999: Color.lerp(textDarkGray999, other.textDarkGray999, t)!,
     );
   }
 }

+ 5 - 1
packages/cs_router/lib/path/router_path.dart

@@ -10,7 +10,11 @@ class RouterPath {
   static const authForgotVerify = '/auth/forgot/verify'; //忘记密码校验
   static const authSignUp = '/auth/signup'; //注册
   static const authSignUpVerify = '/auth/signup/verify'; //注册的短信验证
-  static const authSignUpSuccess = '/auth/signup/success'; //注册的短信验证
+  static const authSignUpSuccess = '/auth/signup/success'; //账号注册成功
+  static const authSelectEstate = '/auth/select/estate'; //绑定社区
+  static const authSelectUnit = '/auth/select/unit'; //绑定楼栋与房间号
+  static const authSelectRole = '/auth/select/role'; //选择角色
+  static const authTenantDoc = '/auth/tenant/doc'; //租户的文件上传
   static const authResetPassword = '/auth/rest_psd'; //重置密码
 
   //首页

+ 2 - 0
packages/cs_widgets/lib/my_appbar.dart

@@ -14,6 +14,7 @@ class MyAppBar {
   ///封装的默认的AppBar,Light默认模式下,黑色图标+黑色文本,Dark模式下,白色图标+白色文本
   static AppBar appBar(BuildContext context, String title,
       {void Function()? backCallback,
+      Key? key,
       String? backIconPath,
       double? backIconWidth,
       double? backIconHeight,
@@ -27,6 +28,7 @@ class MyAppBar {
     final bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
 
     return AppBar(
+      key: key,
       backgroundColor: backgroundColor,
       surfaceTintColor: backgroundColor,
       systemOverlayStyle: systemUiOverlayStyle ?? ThemeConfig.getSystemUiOverlayStyleByTheme(context),

+ 3 - 3
packages/cs_widgets/pubspec_overrides.yaml

@@ -1,8 +1,8 @@
 # melos_managed_dependency_overrides: cs_resources,shared,router
 dependency_overrides:
   cs_resources:
-    path: ..\\cs_resources
+    path: ../cs_resources
   router:
-    path: ..\\cs_router
+    path: ../cs_router
   shared:
-    path: ..\\cs_shared
+    path: ../cs_shared