Pārlūkot izejas kodu

Merge branch 'dev' of http://git.wmzhubo.com/guadoutech/YYHome into dev

glglove 4 dienas atpakaļ
vecāks
revīzija
1aa85865e9
88 mainītis faili ar 3309 papildinājumiem un 1000 dzēšanām
  1. 63 110
      packages/cpt_auth/lib/modules/select_estate/select_estate_page.dart
  2. 0 3
      packages/cpt_auth/lib/modules/select_estate/select_estate_view_model.dart
  3. 1 1
      packages/cpt_auth/lib/modules/select_role/select_role_page.dart
  4. 151 199
      packages/cpt_auth/lib/modules/select_unit/select_unit_page.dart
  5. 0 4
      packages/cpt_auth/lib/modules/select_unit/select_unit_view_model.dart
  6. 0 92
      packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_full_screen.dart
  7. 73 6
      packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_page.dart
  8. 0 90
      packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_small_screen.dart
  9. 3 1
      packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_view_model.dart
  10. 53 100
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_page.dart
  11. 0 4
      packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_view_model.dart
  12. 0 5
      packages/cpt_auth/lib/router/component/auth_component_service.dart
  13. 284 0
      packages/cpt_facility/lib/modules/book_confirm/book_confirm_page.dart
  14. 3 0
      packages/cpt_facility/lib/modules/book_confirm/book_confirm_state.dart
  15. 25 0
      packages/cpt_facility/lib/modules/book_confirm/book_confirm_view_model.dart
  16. 27 0
      packages/cpt_facility/lib/modules/book_confirm/book_confirm_view_model.g.dart
  17. 176 26
      packages/cpt_facility/lib/modules/booking/facility_booking_page.dart
  18. 34 2
      packages/cpt_facility/lib/modules/booking/facility_booking_state.dart
  19. 56 3
      packages/cpt_facility/lib/modules/booking/facility_booking_view_model.dart
  20. 1 1
      packages/cpt_facility/lib/modules/booking/facility_booking_view_model.g.dart
  21. 12 2
      packages/cpt_facility/lib/modules/detail/facility_detail_page.dart
  22. 3 4
      packages/cpt_facility/lib/modules/facility/history/facility_history_screen.dart
  23. 2 0
      packages/cpt_facility/lib/router/page/facility_page_router.dart
  24. 20 0
      packages/cpt_facility/lib/router/page/facility_page_router.gr.dart
  25. 3 1
      packages/cpt_notice_board/lib/modules/documents/page/documents_page.dart
  26. 154 0
      packages/cpt_notice_board/lib/modules/documents_list/page/documents_list_page.dart
  27. 49 0
      packages/cpt_notice_board/lib/modules/documents_list/page/documents_list_state.dart
  28. 70 0
      packages/cpt_notice_board/lib/modules/documents_list/repository/documents_list_repository.dart
  29. 28 0
      packages/cpt_notice_board/lib/modules/documents_list/repository/documents_list_repository.g.dart
  30. 105 0
      packages/cpt_notice_board/lib/modules/documents_list/vm/documents_list_vm.dart
  31. 25 0
      packages/cpt_notice_board/lib/modules/documents_list/vm/documents_list_vm.g.dart
  32. 6 1
      packages/cpt_notice_board/lib/modules/event/page/event_page.dart
  33. 121 0
      packages/cpt_notice_board/lib/modules/event_detail/page/event_detail_page.dart
  34. 49 0
      packages/cpt_notice_board/lib/modules/event_detail/page/event_detail_state.dart
  35. 70 0
      packages/cpt_notice_board/lib/modules/event_detail/repository/event_detail_repository.dart
  36. 28 0
      packages/cpt_notice_board/lib/modules/event_detail/repository/event_detail_repository.g.dart
  37. 105 0
      packages/cpt_notice_board/lib/modules/event_detail/vm/event_detail_vm.dart
  38. 10 10
      packages/cpt_services/lib/modules/services/vm/services_view_model.g.dart
  39. 0 71
      packages/cpt_notice_board/lib/modules/notice_board/page/notice_board_page.dart
  40. 1 1
      packages/cpt_notice_board/lib/modules/notice_board/vm/notice_board_view_model.dart
  41. 1 1
      packages/cpt_notice_board/lib/modules/notice_board/vm/notice_board_view_model.g.dart
  42. 12 0
      packages/cpt_notice_board/lib/router/page/notice_board_page_router.dart
  43. 40 0
      packages/cpt_notice_board/lib/router/page/notice_board_page_router.gr.dart
  44. 122 0
      packages/cpt_services/lib/modules/services/dialog/account_deactivation_dialog.dart
  45. 0 33
      packages/cpt_services/lib/modules/services/page/services_page.dart
  46. 206 0
      packages/cpt_services/lib/modules/services/services_page.dart
  47. 70 0
      packages/cpt_services/lib/modules/services/services_repository.dart
  48. 28 0
      packages/cpt_services/lib/modules/services/services_repository.g.dart
  49. 50 0
      packages/cpt_services/lib/modules/services/services_state.dart
  50. 175 0
      packages/cpt_services/lib/modules/services/services_view_model.dart
  51. 25 0
      packages/cpt_services/lib/modules/services/services_view_model.g.dart
  52. 0 14
      packages/cpt_services/lib/modules/services/vm/services_view_model.dart
  53. 1 1
      packages/cpt_services/lib/router/component/services_component_service.dart
  54. 1 1
      packages/cpt_services/lib/router/page/services_page_router.dart
  55. BIN
      packages/cs_resources/assets/base_lib/calendar_left_icon.webp
  56. BIN
      packages/cs_resources/assets/base_lib/calendar_right_icon.webp
  57. BIN
      packages/cs_resources/assets/service/service_icon_1.png
  58. BIN
      packages/cs_resources/assets/service/service_icon_10.png
  59. BIN
      packages/cs_resources/assets/service/service_icon_11.png
  60. BIN
      packages/cs_resources/assets/service/service_icon_12.png
  61. BIN
      packages/cs_resources/assets/service/service_icon_13.png
  62. BIN
      packages/cs_resources/assets/service/service_icon_14.png
  63. BIN
      packages/cs_resources/assets/service/service_icon_2.png
  64. BIN
      packages/cs_resources/assets/service/service_icon_3.png
  65. BIN
      packages/cs_resources/assets/service/service_icon_4.png
  66. BIN
      packages/cs_resources/assets/service/service_icon_5.png
  67. BIN
      packages/cs_resources/assets/service/service_icon_6.png
  68. BIN
      packages/cs_resources/assets/service/service_icon_7.png
  69. BIN
      packages/cs_resources/assets/service/service_icon_8.png
  70. BIN
      packages/cs_resources/assets/service/service_icon_9.png
  71. 16 0
      packages/cs_resources/lib/generated/assets.dart
  72. 10 2
      packages/cs_resources/lib/generated/intl/messages_en.dart
  73. 8 2
      packages/cs_resources/lib/generated/intl/messages_zh_CN.dart
  74. 8 2
      packages/cs_resources/lib/generated/intl/messages_zh_HK.dart
  75. 40 0
      packages/cs_resources/lib/generated/l10n.dart
  76. 4 0
      packages/cs_resources/lib/l10n/intl_en.arb
  77. 4 0
      packages/cs_resources/lib/l10n/intl_zh_CN.arb
  78. 4 0
      packages/cs_resources/lib/l10n/intl_zh_HK.arb
  79. 1 0
      packages/cs_resources/pubspec.yaml
  80. 0 2
      packages/cs_router/lib/componentRouter/auth_service.dart
  81. 4 1
      packages/cs_router/lib/path/router_path.dart
  82. 49 0
      packages/cs_widgets/lib/shatter/select_calendar/calendar_bottom_sheet.dart
  83. 336 0
      packages/cs_widgets/lib/shatter/select_calendar/full_calendar.dart
  84. 32 10
      packages/cs_widgets/lib/shatter/weekly_calendar/calendar_utils.dart
  85. 5 6
      packages/cs_widgets/lib/shatter/weekly_calendar/day_cell.dart
  86. 5 9
      packages/cs_widgets/lib/shatter/weekly_calendar/day_table_view.dart
  87. 203 151
      packages/cs_widgets/lib/shatter/weekly_calendar/week_page.dart
  88. 38 28
      packages/cs_widgets/lib/shatter/weekly_calendar/weekly_calendar.dart

+ 63 - 110
packages/cpt_auth/lib/modules/select_estate/select_estate_page.dart

@@ -4,10 +4,8 @@ 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';
@@ -32,121 +30,76 @@ class SelectEstatePage extends HookConsumerWidget {
     }
   }
 
-  // 为需要测量的控件创建 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),
+      appBar: MyAppBar.appBar(context, S.current.yy_home_accounts),
       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),
-            ],
-          ),
+      body: Container(
+        padding: const EdgeInsets.symmetric(horizontal: 38),
+        width: double.infinity,
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            SingleChildScrollView(
+                scrollDirection: Axis.vertical,
+                physics: const BouncingScrollPhysics(),
+                child: Column(
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    //顶部图片
+                    const MyAssetImage(
+                      Assets.authChooseEstateBuilding,
+                      width: 267,
+                      height: 158,
+                    ).marginOnly(top: 28, bottom: 38),
+
+                    MyTextView(
+                      S.current.estate_or_building_name,
+                      fontSize: 23,
+                      marginBottom: 20,
+                      textAlign: TextAlign.center,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+
+                    //输入资产的名称
+                    _buildInputLayout(
+                      context,
+                      state,
+                      "estate",
+                      textInputAction: TextInputAction.done,
+                      onSubmit: (formKey, value) {
+                        state.formData[formKey]!['focusNode'].unfocus();
+                      },
+                    ),
+
+                    MyTextView(
+                      S.current.estate_name_desc,
+                      fontSize: 15,
+                      marginTop: 19,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                  ],
+                )).expanded(),
+
+            MyButton(
+              onPressed: viewModel.submitEstate,
+              text: S.current.next,
+              textColor: Colors.white,
+              backgroundColor: context.appColors.btnBgDefault,
+              fontWeight: FontWeight.w500,
+              type: ClickType.throttle,
+              fontSize: 16,
+              minHeight: 50,
+              radius: 5,
+            ).marginOnly(top: 50, bottom: 50),
+          ],
         ),
       ),
     );

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

@@ -18,7 +18,4 @@ class SelectEstateViewModel extends _$SelectEstateViewModel {
     SelectUnitPage.startInstance();
   }
 
-  void setRemainingSpace(double remainingSpace) {
-    state = state.copyWith(remainingSpace: remainingSpace);
-  }
 }

+ 1 - 1
packages/cpt_auth/lib/modules/select_role/select_role_page.dart

@@ -106,7 +106,7 @@ class SelectRolePage extends HookConsumerWidget {
               fontSize: 16,
               minHeight: 50,
               radius: 5,
-            ).marginOnly(top: 30, bottom: 30, left: 18, right: 18),
+            ).marginOnly(top: 50, bottom: 50, left: 18, right: 18),
           ],
         ),
       ),

+ 151 - 199
packages/cpt_auth/lib/modules/select_unit/select_unit_page.dart

@@ -32,212 +32,164 @@ class SelectUnitPage extends HookConsumerWidget {
     }
   }
 
-  // 为需要测量的控件创建 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),
+      appBar: MyAppBar.appBar(context, S.current.yy_home_accounts),
       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),
-            ],
-          ),
+      body: Container(
+        padding: const EdgeInsets.symmetric(horizontal: 20),
+        width: double.infinity,
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            SingleChildScrollView(
+                scrollDirection: Axis.vertical,
+                physics: const BouncingScrollPhysics(),
+                child: Column(
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    //顶部图片
+                    const MyAssetImage(
+                      Assets.authSignUpUnitImg,
+                      width: 266.5,
+                      height: 162,
+                    ).marginOnly(top: 28, bottom: 18),
+
+                    Row(
+                      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(
+                      S.current.block_desc,
+                      fontSize: 15,
+                      marginTop: 25,
+                      textAlign: TextAlign.center,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+
+                    MyTextView(
+                      S.current.block_example,
+                      fontSize: 15,
+                      marginTop: 20,
+                      textAlign: TextAlign.center,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+
+                    MyTextView(
+                      S.current.block_example_desc,
+                      fontSize: 15,
+                      marginTop: 20,
+                      textAlign: TextAlign.center,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                  ],
+                )).expanded(),
+
+            MyButton(
+              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: 50, bottom: 50, left: 18, right: 18),
+          ],
         ),
       ),
     );

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

@@ -17,8 +17,4 @@ class SelectUnitViewModel extends _$SelectUnitViewModel {
     SelectRolePage.startInstance();
   }
 
-  void setRemainingSpace(double remainingSpace) {
-    state = state.copyWith(remainingSpace: remainingSpace);
-  }
-
 }

+ 0 - 92
packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_full_screen.dart

@@ -1,92 +0,0 @@
-import 'package:cs_resources/generated/assets.dart';
-import 'package:cs_resources/generated/l10n.dart';
-import 'package:cs_resources/theme/app_colors_theme.dart';
-import 'package:flutter/material.dart';
-import 'package:auto_route/auto_route.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:router/ext/auto_router_extensions.dart';
-import 'package:widgets/ext/ex_widget.dart';
-import 'package:widgets/my_appbar.dart';
-import 'package:widgets/my_button.dart';
-import 'package:widgets/my_load_image.dart';
-import 'package:widgets/my_text_view.dart';
-
-import '../../router/page/auth_page_router.dart';
-import 'sign_up_success_view_model.dart';
-
-//全面屏手机
-class SignUpSuccessFullScreen extends HookConsumerWidget {
-  const SignUpSuccessFullScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    final viewModel = ref.watch(signUpSuccessViewModelProvider.notifier);
-
-    return LayoutBuilder(
-      builder: (context, constraints) {
-        return Container(
-          padding: const EdgeInsets.symmetric(horizontal: 20),
-          width: double.infinity,
-          height: constraints.maxHeight, // 占满父容器的高度
-          child: Column(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: [
-              //顶部图片
-              const MyAssetImage(
-                Assets.authYyHomeSuccess,
-                width: 264,
-                height: 180,
-              ).alignCenter().marginOnly(top: 12),
-
-              MyTextView(
-                S.current.welcome_name("Hu yu"),
-                fontSize: 23,
-                marginTop: 30,
-                isFontMedium: true,
-                textColor: context.appColors.textBlack,
-              ),
-
-              MyTextView(
-                S.current.sign_up_success_txt1,
-                fontSize: 15,
-                marginTop: 25,
-                isFontMedium: true,
-                textColor: context.appColors.textBlack,
-              ),
-
-              MyTextView(
-                S.current.sign_up_success_txt2,
-                fontSize: 15,
-                marginTop: 20,
-                isFontMedium: true,
-                textColor: context.appColors.textBlack,
-              ),
-
-              MyTextView(
-                S.current.sign_up_success_txt3,
-                fontSize: 15,
-                marginTop: 20,
-                isFontMedium: true,
-                textColor: context.appColors.textBlack,
-              ),
-
-              const Spacer(),
-
-              MyButton(
-                onPressed: viewModel.gotoSelectEstatePage,
-                text: S.current.get_started,
-                textColor: Colors.white,
-                backgroundColor: context.appColors.btnBgDefault,
-                fontWeight: FontWeight.w500,
-                type: ClickType.throttle,
-                fontSize: 16,
-                minHeight: 50,
-                radius: 5,
-              ).marginOnly(top: 50, bottom: 50, left: 18, right: 18),
-            ],
-          ),
-        );
-      },
-    );
-  }
-}

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

@@ -1,4 +1,4 @@
-import 'package:cpt_auth/modules/sing_up_success/sign_up_success_full_screen.dart';
+import 'package:cpt_auth/modules/sing_up_success/sign_up_success_view_model.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
@@ -6,10 +6,12 @@ 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/responsive_widget.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
 import '../../router/page/auth_page_router.dart';
-import 'sign_up_success_small_screen.dart';
 
 @RoutePage()
 class SignUpSuccessPage extends HookConsumerWidget {
@@ -26,12 +28,77 @@ class SignUpSuccessPage extends HookConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(signUpSuccessViewModelProvider.notifier);
+
     return Scaffold(
       appBar: MyAppBar.appBar(context, ""),
       backgroundColor: context.appColors.backgroundDefault,
-      body: const ResponsiveWidget(
-        smallScreen: SignUpSuccessSmallScreen(),
-        smallFullScreen: SignUpSuccessFullScreen(),
+      body: Container(
+        padding: const EdgeInsets.symmetric(horizontal: 20),
+        width: double.infinity,
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            SingleChildScrollView(
+                scrollDirection: Axis.vertical,
+                physics: const BouncingScrollPhysics(),
+                child: Column(
+                  children: [
+                    //顶部图片
+                    const MyAssetImage(
+                      Assets.authYyHomeSuccess,
+                      width: 264,
+                      height: 180,
+                    ).alignCenter().marginOnly(top: 12),
+
+                    MyTextView(
+                      S.current.welcome_name("Huyu"),
+                      fontSize: 23,
+                      marginTop: 30,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+
+                    MyTextView(
+                      S.current.sign_up_success_txt1,
+                      fontSize: 15,
+                      marginTop: 25,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+
+                    MyTextView(
+                      S.current.sign_up_success_txt2,
+                      fontSize: 15,
+                      marginTop: 20,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+
+                    MyTextView(
+                      S.current.sign_up_success_txt3,
+                      fontSize: 15,
+                      marginTop: 20,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                  ],
+                )).expanded(),
+
+            MyButton(
+              onPressed: viewModel.gotoSelectEstatePage,
+              text: S.current.get_started,
+              textColor: Colors.white,
+              backgroundColor: context.appColors.btnBgDefault,
+              fontWeight: FontWeight.w500,
+              type: ClickType.throttle,
+              fontSize: 16,
+              minHeight: 50,
+              radius: 5,
+            ).marginOnly(top: 50, bottom: 50, left: 18, right: 18),
+          ],
+        ),
       ),
     );
   }

+ 0 - 90
packages/cpt_auth/lib/modules/sing_up_success/sign_up_success_small_screen.dart

@@ -1,90 +0,0 @@
-import 'package:cs_resources/generated/assets.dart';
-import 'package:cs_resources/generated/l10n.dart';
-import 'package:cs_resources/theme/app_colors_theme.dart';
-import 'package:flutter/material.dart';
-import 'package:auto_route/auto_route.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:router/ext/auto_router_extensions.dart';
-import 'package:widgets/ext/ex_widget.dart';
-import 'package:widgets/my_appbar.dart';
-import 'package:widgets/my_button.dart';
-import 'package:widgets/my_load_image.dart';
-import 'package:widgets/my_text_view.dart';
-
-import '../../router/page/auth_page_router.dart';
-import 'sign_up_success_view_model.dart';
-
-//小屏手机
-class SignUpSuccessSmallScreen extends HookConsumerWidget {
-  const SignUpSuccessSmallScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    final viewModel = ref.watch(signUpSuccessViewModelProvider.notifier);
-
-    return 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.start,
-          children: [
-            //顶部图片
-            const MyAssetImage(
-              Assets.authYyHomeSuccess,
-              width: 264,
-              height: 180,
-            ).alignCenter().marginOnly(top: 12),
-
-            MyTextView(
-              S.current.welcome_name("Huyu"),
-              fontSize: 23,
-              marginTop: 30,
-              isFontMedium: true,
-              textColor: context.appColors.textBlack,
-            ),
-
-            MyTextView(
-              S.current.sign_up_success_txt1,
-              fontSize: 15,
-              marginTop: 25,
-              isFontMedium: true,
-              textColor: context.appColors.textBlack,
-            ),
-
-            MyTextView(
-              S.current.sign_up_success_txt2,
-              fontSize: 15,
-              marginTop: 20,
-              isFontMedium: true,
-              textColor: context.appColors.textBlack,
-            ),
-
-            MyTextView(
-              S.current.sign_up_success_txt3,
-              fontSize: 15,
-              marginTop: 20,
-              isFontMedium: true,
-              textColor: context.appColors.textBlack,
-            ),
-
-            MyButton(
-              onPressed: viewModel.gotoSelectEstatePage,
-              text: S.current.get_started,
-              textColor: Colors.white,
-              backgroundColor: context.appColors.btnBgDefault,
-              fontWeight: FontWeight.w500,
-              type: ClickType.throttle,
-              fontSize: 16,
-              minHeight: 50,
-              radius: 5,
-            ).marginOnly(top: 50, bottom: 50, left: 18, right: 18),
-          ],
-        ),
-      ),
-    );
-  }
-}

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

@@ -1,6 +1,8 @@
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 
+import '../select_estate/select_estate_page.dart';
+
 part 'sign_up_success_view_model.g.dart';
 
 @riverpod
@@ -10,6 +12,6 @@ class SignUpSuccessViewModel extends _$SignUpSuccessViewModel {
 
   //去选择社区的页面
   void gotoSelectEstatePage() {
-    ToastEngine.show("去选择社区的页面");
+    SelectEstatePage.startInstance();
   }
 }

+ 53 - 100
packages/cpt_auth/lib/modules/tenant_doc/tenant_doc_page.dart

@@ -2,10 +2,8 @@ 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';
@@ -28,55 +26,16 @@ class TenantDocPage extends HookConsumerWidget {
     }
   }
 
-  // 为需要测量的控件创建 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),
+      appBar: MyAppBar.appBar(
+        context,
+        "",
+      ),
       backgroundColor: context.appColors.backgroundDefault,
       body: Container(
         padding: const EdgeInsets.symmetric(horizontal: 15),
@@ -85,63 +44,57 @@ class TenantDocPage extends HookConsumerWidget {
           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, // 使用剩余空间的值
-            ),
+            SingleChildScrollView(
+                scrollDirection: Axis.vertical,
+                physics: const BouncingScrollPhysics(),
+                child: Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      S.current.upload_documents,
+                      fontSize: 23.5,
+                      marginTop: 23,
+                      marginBottom: 21,
+                      textAlign: TextAlign.center,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                    MyTextView(
+                      S.current.upload_doc_desc,
+                      fontSize: 15,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                    MyTextView(
+                      S.current.upload_doc_desc1,
+                      fontSize: 15,
+                      marginTop: 22,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                    MyTextView(
+                      S.current.upload_doc_desc2,
+                      fontSize: 15,
+                      marginTop: 22,
+                      marginBottom: 24,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                    ImageNineGrid(
+                      isSelectEnable: true,
+                      maxImages: 3,
+                      spacing: 10,
+                      aspectRatio: 108 / 80,
+                      initialImages: [],
+                      onImagesChanged: (list) {
+                        viewModel.setDocList(list);
+                      },
+                    ),
+                  ],
+                )).expanded(),
 
             //底部的按钮
             MyButton(
-              key: _buttonKey,
               onPressed: viewModel.submitDoc,
               text: S.current.next,
               textColor: Colors.white,
@@ -151,7 +104,7 @@ class TenantDocPage extends HookConsumerWidget {
               fontSize: 16,
               minHeight: 50,
               radius: 5,
-            ).marginOnly(top: 30, bottom: 30, left: 18, right: 18),
+            ).marginOnly(top: 50, bottom: 50, left: 18, right: 18),
           ],
         ),
       ),

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

@@ -21,12 +21,8 @@ class TenantDocViewModel extends _$TenantDocViewModel {
 
   //提交文件
   void submitDoc() {
-
     ToastEngine.show("请求接口上传文件:${state.docList}");
   }
 
-  void setRemainingSpace(double remainingSpace) {
-    state = state.copyWith(remainingSpace: remainingSpace);
-  }
 
 }

+ 0 - 5
packages/cpt_auth/lib/router/component/auth_component_service.dart

@@ -22,11 +22,6 @@ class AuthComponentService extends AuthService {
   }
 
   @override
-  void startResetPasswordPage() {
-    SelectEstatePage.startInstance();
-  }
-
-  @override
   void startSelectEstatePage() {
     SelectEstatePage.startInstance();
   }

+ 284 - 0
packages/cpt_facility/lib/modules/book_confirm/book_confirm_page.dart

@@ -0,0 +1,284 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import '../../router/page/facility_page_router.dart';
+import 'book_confirm_view_model.dart';
+
+@RoutePage()
+class BookConfirmPage extends HookConsumerWidget {
+  const BookConfirmPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const BookConfirmPageRoute());
+    } else {
+      appRouter.push(const BookConfirmPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(bookConfirmViewModelProvider.notifier);
+    final state = ref.watch(bookConfirmViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        "Function Room",
+        showBackButton: true,
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      backgroundColor: context.appColors.backgroundDark,
+      body: Column(
+        children: [
+          Expanded(
+            child: SingleChildScrollView(
+              scrollDirection: Axis.vertical,
+              physics: const BouncingScrollPhysics(),
+              child: Column(
+                mainAxisSize: MainAxisSize.max,
+                crossAxisAlignment: CrossAxisAlignment.center,
+                children: [
+                  const SizedBox(height: 7.5),
+
+                  // 预定
+                  _buildConfirmItem(
+                    context,
+                    ref,
+                    S.current.book,
+                    Assets.facilityConfirmDateIcon,
+                    28.5,
+                    29,
+                    "Tue,24 Oct 2023",
+                    null,
+                    "05:00 PM-10:00 PM",
+                    null,
+                  ),
+
+                  // 设施
+                  _buildConfirmItem(
+                    context,
+                    ref,
+                    S.current.facility,
+                    Assets.facilityConfirmFacilityIcon,
+                    25.0,
+                    30.5,
+                    "Kids party room",
+                    null,
+                    "Blue room",
+                    null,
+                  ),
+
+                  // 付款
+                  _buildConfirmItem(
+                    context,
+                    ref,
+                    S.current.payment,
+                    Assets.facilityConfirmPaymentIcon,
+                    27.0,
+                    22.0,
+                    S.current.booking_fee,
+                    "10.80",
+                    S.current.total,
+                    "\$10.80",
+                  ),
+
+                  // 押金
+                  _buildConfirmItem(
+                    context,
+                    ref,
+                    S.current.deposit,
+                    Assets.facilityConfirmDepositIcon,
+                    28.0,
+                    26.5,
+                    S.current.deposit_hold,
+                    "\$100.00",
+                    null,
+                    null,
+                  ),
+
+                  // 添加间隔
+                  const SizedBox(height: 7.5),
+
+                ],
+              ),
+            ),
+          ),
+
+          // 显示支付信息
+          _paymentInfo(context),
+
+          // 底部按钮
+          MyButton(
+            onPressed:viewModel.doPayment,
+            text: S.current.proceed_with_payment,
+            textColor: Colors.white,
+            backgroundColor: context.appColors.btnBgDefault,
+            fontWeight: FontWeight.w500,
+            type: ClickType.throttle,
+            fontSize: 16,
+            minHeight: 50,
+            radius: 0,
+          ).marginOnly(top: 15),
+        ],
+      ),
+    );
+  }
+
+
+  //展示的Item
+  Widget _buildConfirmItem(
+    BuildContext context,
+    WidgetRef ref,
+    String title,
+    String iconPath,
+    double iconWidth,
+    double iconHeight,
+    String line1Txt,
+    String? line1Content,
+    String? line2Txt,
+    String? line2Content,
+  ) {
+    return Container(
+      width: double.infinity,
+      height: 92.5,
+      padding: const EdgeInsets.only(left: 20, right: 20),
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 7.5, bottom: 7.5),
+      decoration: BoxDecoration(
+        color: context.appColors.whiteBG,
+        borderRadius: BorderRadius.circular(6.0), // 圆角
+        boxShadow: [
+          BoxShadow(
+            color: const Color(0xFFB8BFD9).withOpacity(0.3), // 阴影颜色
+            offset: const Offset(0, 3), // 阴影的偏移量
+            blurRadius: 8.0, // 模糊半径
+            spreadRadius: 3.0, // 扩散半径
+          ),
+        ],
+      ),
+      child: Center(
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            MyTextView(
+              title,
+              textColor: context.appColors.textBlack,
+              fontSize: 16,
+              marginBottom: 7,
+              isFontMedium: true,
+            ),
+            Row(
+              mainAxisSize: MainAxisSize.max,
+              children: [
+                MyAssetImage(
+                  iconPath,
+                  width: iconWidth,
+                  height: iconHeight,
+                ).marginOnly(right: 15),
+                Column(
+                  mainAxisSize: MainAxisSize.min,
+                  children: [
+                    Row(
+                      children: [
+                        MyTextView(
+                          line1Txt,
+                          textColor: context.appColors.textBlack,
+                          fontSize: 14,
+                          isFontRegular: true,
+                        ).expanded(),
+                        MyTextView(
+                          line1Content ?? "",
+                          textColor: context.appColors.textBlack,
+                          fontSize: 14,
+                          isFontRegular: true,
+                        ),
+                      ],
+                    ),
+                    Visibility(
+                      visible: line2Txt != null,
+                      child: Row(
+                        children: [
+                          MyTextView(
+                            line2Txt ?? "",
+                            textColor: context.appColors.textBlack,
+                            fontSize: 14,
+                            isFontRegular: true,
+                          ).expanded(),
+                          MyTextView(
+                            line2Content ?? "",
+                            textColor: context.appColors.textBlack,
+                            fontSize: 14,
+                            isFontRegular: true,
+                          ),
+                        ],
+                      ).marginOnly(top: 6),
+                    ),
+                  ],
+                ).expanded(),
+              ],
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  //底部的支付信息
+  Widget _paymentInfo(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.symmetric(vertical: 17.5, horizontal: 23),
+      color: context.appColors.whiteBG,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            S.current.card_caps,
+            marginBottom: 17,
+            textColor: context.appColors.textPrimary,
+            fontSize: 17,
+            isFontMedium: true,
+          ),
+          Row(
+            children: [
+              const MyAssetImage(
+                Assets.facilityConfirmEcardIcon,
+                height: 38,
+              ),
+              MyTextView(
+                "Ending 9423",
+                marginLeft: 15,
+                marginRight: 15,
+                textColor: context.appColors.textBlack,
+                fontSize: 15,
+                isFontMedium: true,
+              ).expanded(),
+              MyTextView(
+                S.current.change,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                paddingRight: 16,
+                paddingLeft: 16,
+                paddingTop: 8,
+                paddingBottom: 8,
+                cornerRadius: 7,
+                fontSize: 15,
+                isFontMedium: true,
+              )
+            ],
+          )
+        ],
+      ),
+    );
+  }
+}

+ 3 - 0
packages/cpt_facility/lib/modules/book_confirm/book_confirm_state.dart

@@ -0,0 +1,3 @@
+class BookConfirmState{
+
+}

+ 25 - 0
packages/cpt_facility/lib/modules/book_confirm/book_confirm_view_model.dart

@@ -0,0 +1,25 @@
+import 'package:cpt_facility/modules/detail/facility_detail_page.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'book_confirm_state.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+
+part 'book_confirm_view_model.g.dart';
+
+@riverpod
+class BookConfirmViewModel extends _$BookConfirmViewModel {
+  @override
+  BookConfirmState build() {
+    return BookConfirmState();
+  }
+
+  //执行支付
+  void doPayment(){
+
+    ToastEngine.show("点击了确定");
+
+    FacilityDetailPage.startWithPop2Main();
+  }
+
+}

+ 27 - 0
packages/cpt_facility/lib/modules/book_confirm/book_confirm_view_model.g.dart

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

+ 176 - 26
packages/cpt_facility/lib/modules/booking/facility_booking_page.dart

@@ -1,11 +1,22 @@
+import 'dart:math';
+
+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/date_time_utils.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
+import 'package:widgets/shatter/select_calendar/calendar_bottom_sheet.dart';
 import 'package:widgets/widget_export.dart';
 
 import '../../router/page/facility_page_router.dart';
@@ -29,38 +40,177 @@ class FacilityBookingPage extends HookConsumerWidget {
     final viewModel = ref.watch(facilityBookingViewModelProvider.notifier);
     final state = ref.watch(facilityBookingViewModelProvider);
 
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchListByDate());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
     return Scaffold(
       appBar: MyAppBar.appBar(context, "Kids party room", backgroundColor: context.appColors.whiteBG),
       backgroundColor: context.appColors.backgroundDark,
-      body: SingleChildScrollView(
-        scrollDirection: Axis.vertical,
-        physics: const BouncingScrollPhysics(),
-        child: Column(
-          mainAxisSize: MainAxisSize.max,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            MyTextView(
-              "Friday,11 October 2024",
-              textColor: context.appColors.textBlack,
-              fontSize: 17,
-              marginTop: 18,
-              marginBottom: 16,
-              marginLeft: 15,
+      body: Column(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        children: [
+          //顶部的选中的日期与日历选择
+          Row(
+            mainAxisSize: MainAxisSize.max,
+            children: [
+              MyTextView(
+                "${DateTimeUtils.getWeekday(state.selectedDate, languageCode: 'en')}, ${DateTimeUtils.formatDate(state.selectedDate, format: 'dd MMM yyyy')}",
+                textColor: context.appColors.textBlack,
+                fontSize: 17,
+                marginTop: 18,
+                marginBottom: 16,
+                marginLeft: 15,
+                isFontMedium: true,
+              ).expanded(),
+              const MyAssetImage(Assets.facilityConfirmDateIcon, width: 22.5, height: 22.5).marginOnly(right: 10).onTap(() {
+                //日历日期选择器
+                _datePickerBottomSheet(context, ref);
+              }, padding: 5),
+            ],
+          ),
+
+          //二周的日期选择
+          WeeklyCalendar(
+            selectedDate: state.selectedDate,
+            onChangedSelectedDate: (dateTime) {
+              Log.d("onChangedSelectedDate选中 - ${dateTime}}");
+              viewModel.changeSelectedDate(dateTime);
+            },
+          ),
+
+          //每天的单独数据
+          LoadStateLayout(
+            state: state.loadingState,
+            errorMessage: state.errorMessage,
+            errorRetry: () {
+              viewModel.retryRequest();
+            },
+            successSliverWidget: [
+              SliverToBoxAdapter(
+                child: MyTextView(
+                  S.current.quota_left_msg(1, DateTimeUtils.formatDate(state.selectedDate, format: 'dd MMM yyyy')),
+                  marginTop: 7,
+                  marginBottom: 15,
+                  textColor: context.appColors.textBlack,
+                  fontSize: 12,
+                  isFontMedium: true,
+                ),
+              ),
+              SliverList(
+                  delegate: SliverChildBuilderDelegate(
+                (context, index) {
+                  return _buildFacilityOption(context, state.datas[index]);
+                },
+                childCount: state.datas.length,
+              ))
+            ],
+          ).marginOnly(top: 5).expanded(),
+
+          //底部按钮
+          MyButton(
+            onPressed: viewModel.gotoConfirmPage,
+            text: S.current.next,
+            textColor: Colors.white,
+            backgroundColor: context.appColors.btnBgDefault,
+            fontWeight: FontWeight.w500,
+            type: ClickType.throttle,
+            fontSize: 16,
+            minHeight: 50,
+            radius: 0,
+          )
+        ],
+      ),
+    );
+  }
+
+  //日期日历的选择器,底部弹窗选择
+  void _datePickerBottomSheet(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(facilityBookingViewModelProvider.notifier);
+    final state = ref.watch(facilityBookingViewModelProvider);
+
+    showModalBottomSheet<void>(
+      context: context,
+      isScrollControlled: true,
+      shape: const RoundedRectangleBorder(
+        borderRadius: BorderRadius.only(topLeft: Radius.circular(30.0), topRight: Radius.circular(30.0)),
+      ),
+      builder: (BuildContext context) {
+        return CustomCalendarBottomSheet(
+          firstDate: DateTime.now(),
+          lastDate: DateTime.now().add(const Duration(days: 365)),
+          selectedDate: state.selectedDate,
+          locale: "en",
+          onDateChange: (dateTime) {
+            Navigator.pop(context);
+            viewModel.changeSelectedDate(dateTime);
+          },
+        );
+      },
+    );
+  }
+
+  //生产当前设施的选项
+  Widget _buildFacilityOption(BuildContext context, String item) {
+    return Column(
+      children: [
+        Container(
+          width: double.infinity,
+          height: 38,
+          color: context.appColors.btnBgDefault,
+          child: Center(
+            child: MyTextView(
+              item,
+              fontSize: 16,
+              textColor: Colors.white,
+              textAlign: TextAlign.center,
               isFontMedium: true,
             ),
-            WeeklyCalendar(
-              isAutoSelect: false,
-              selectedDate: DateTime.now().add(Duration(days: 1)),
-              onChangedSelectedDate: (dateTime) {
-                Log.d("onChangedSelectedDate选中 - ${dateTime}}");
-              },
-              onChangedPage: (dateTime, state) {
-                Log.d("onChangedPage - ${dateTime} state:${state}");
-              },
-            ),
-          ],
+          ),
         ),
-      ),
+        GridView.builder(
+          shrinkWrap: true,
+          physics: const NeverScrollableScrollPhysics(),
+          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
+            crossAxisCount: 4,
+            childAspectRatio: 82 / 43,
+            mainAxisSpacing: 6.5,
+            crossAxisSpacing: 6.5,
+          ),
+          itemCount: 4,
+          itemBuilder: (context, index) {
+            return Container(
+              decoration: BoxDecoration(
+                color: context.appColors.whiteBG,
+                borderRadius: BorderRadius.circular(5.0),
+              ),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.center,
+                mainAxisAlignment: MainAxisAlignment.center, // 垂直居中
+                children: [
+                  MyTextView(
+                    "10.00 AM",
+                    fontSize: 12,
+                    textColor: context.appColors.textBlack,
+                    isFontMedium: true,
+                  ),
+                  MyTextView(
+                    "04.00 PM",
+                    fontSize: 12,
+                    textColor: context.appColors.textBlack,
+                    isFontMedium: true,
+                  ),
+                ],
+              ),
+            );
+          },
+        ).marginSymmetric(horizontal: 10, vertical: 17),
+      ],
     );
   }
 }

+ 34 - 2
packages/cpt_facility/lib/modules/booking/facility_booking_state.dart

@@ -1,3 +1,35 @@
-class FacilityBookingState{
+import 'package:widgets/load_state_layout.dart';
 
-}
+class FacilityBookingState {
+  //当前选中的时间日期
+  DateTime selectedDate;
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas;
+
+  // ===================================  Begin  ↓  ===================================
+
+  FacilityBookingState({
+    required this.selectedDate,
+    this.loadingState = LoadState.State_Loading,
+    required this.datas,
+    this.errorMessage,
+  });
+
+  FacilityBookingState copyWith({
+    DateTime? selectedDate,
+    LoadState? loadingState,
+    String? errorMessage,
+    List<String>? datas,
+  }) {
+    return FacilityBookingState(
+      selectedDate: selectedDate ?? this.selectedDate,
+      loadingState: loadingState ?? this.loadingState,
+      errorMessage: errorMessage ?? this.errorMessage,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 56 - 3
packages/cpt_facility/lib/modules/booking/facility_booking_view_model.dart

@@ -1,13 +1,66 @@
+import 'package:cs_resources/generated/l10n.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
-
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/load_state_layout.dart';
+import '../book_confirm/book_confirm_page.dart';
 import 'facility_booking_state.dart';
 
 part 'facility_booking_view_model.g.dart';
 
 @riverpod
-class FacilityBookingViewModel extends _$FacilityBookingViewModel{
+class FacilityBookingViewModel extends _$FacilityBookingViewModel {
   @override
   FacilityBookingState build() {
-    return FacilityBookingState();
+    final state = FacilityBookingState(
+      selectedDate: DateTime.now(),
+      datas: [],
+    );
+    initListener(state);
+    ref.onDispose(() {
+      onDispose(state);
+    });
+
+    return state;
+  }
+
+  //修改选中的时间
+  void changeSelectedDate(DateTime dateTime) {
+    state = state.copyWith(selectedDate: dateTime);
+    Log.d("当前选中的日期:$dateTime");
+    fetchListByDate();
+  }
+
+  //失败的重试
+  void retryRequest() {
+    fetchListByDate();
+  }
+
+  /// 获取服务器数据
+  Future fetchListByDate() async {
+    state = state.copyWith(loadingState: LoadState.State_Loading);
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    List<String> list = ["Orange Room", "Purple Room", "Red Room"];
+
+    if (list.isNotEmpty) {
+      //加载成功
+      state = state.copyWith(datas: list, loadingState: LoadState.State_Success);
+    } else {
+      //无数据
+      state = state.copyWith(datas: [], loadingState: LoadState.State_Empty);
+    }
+  }
+
+  void initListener(FacilityBookingState state) {}
+
+  void onDispose(FacilityBookingState state) {
+    Log.d("FacilityBookingViewModel - onDispose");
+  }
+
+  //去付款确认页面
+  void gotoConfirmPage() {
+    BookConfirmPage.startInstance();
   }
 }

+ 1 - 1
packages/cpt_facility/lib/modules/booking/facility_booking_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'facility_booking_view_model.dart';
 // **************************************************************************
 
 String _$facilityBookingViewModelHash() =>
-    r'd90fc41489be510e703686650b6027f6f6cdf77d';
+    r'c6d1d64d1d7100b6864c53327150a9893201e3a9';
 
 /// See also [FacilityBookingViewModel].
 @ProviderFor(FacilityBookingViewModel)

+ 12 - 2
packages/cpt_facility/lib/modules/detail/facility_detail_page.dart

@@ -25,6 +25,16 @@ class FacilityDetailPage extends HookConsumerWidget {
     }
   }
 
+  //启动当前页面并回退至设施首页
+  static void startWithPop2Main() {
+    appRouter.pushAndPopUntil(
+      const FacilityDetailPageRoute(),
+      predicate: (route) {
+        return route.settings.name == 'FacilityPageRoute';
+      },
+    );
+  }
+
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final viewModel = ref.watch(facilityDetailViewModelProvider.notifier);
@@ -79,7 +89,7 @@ class FacilityDetailPage extends HookConsumerWidget {
               Assets.facilityConfirmPaymentIcon,
               27.0,
               22.0,
-              "Booking Fee",
+              S.current.booking_fee,
               "10.80",
               S.current.total,
               "\$10.80",
@@ -93,7 +103,7 @@ class FacilityDetailPage extends HookConsumerWidget {
               Assets.facilityConfirmDepositIcon,
               28.0,
               26.5,
-              "On Hold",
+              S.current.on_hold,
               "\$100.00",
               null,
               null,

+ 3 - 4
packages/cpt_facility/lib/modules/facility/history/facility_history_screen.dart

@@ -25,7 +25,7 @@ class FacilityHistoryScreen extends HookConsumerWidget {
       };
     }, []);
 
-    return Container(
+    return SizedBox(
       width: double.infinity,
       height: double.infinity,
       child: EasyRefresh(
@@ -40,14 +40,13 @@ class FacilityHistoryScreen extends HookConsumerWidget {
           },
           successSliverWidget: [
             SliverList(
-                delegate: SliverChildBuilderDelegate(
-                      (context, index) {
+                delegate: SliverChildBuilderDelegate((context, index) {
                     return FacilityHistoryItem(index: index, item: state.datas[index]).onTap((){
                       FacilityDetailPage.startInstance(context: context);
                     });
                   },
                   childCount: state.datas.length,
-                ))
+                )),
           ],
         ),
       ).marginOnly(top: 5, bottom: 5),

+ 2 - 0
packages/cpt_facility/lib/router/page/facility_page_router.dart

@@ -10,6 +10,7 @@ import '../../modules/facility/deposit/facility_deposit_screen.dart';
 import '../../modules/facility/history/facility_history_screen.dart';
 import '../../modules/detail/facility_detail_page.dart';
 import '../../modules/booking/facility_booking_page.dart';
+import '../../modules/book_confirm/book_confirm_page.dart';
 
 part 'facility_page_router.gr.dart';
 
@@ -33,5 +34,6 @@ class FacilityPageRouter extends _$FacilityPageRouter {
         ),
         CustomRoute(page: FacilityDetailPageRoute.page, path: RouterPath.facilityDetail, transitionsBuilder: applySlideTransition),
         CustomRoute(page: FacilityBookingPageRoute.page, path: RouterPath.facilityBook, transitionsBuilder: applySlideTransition),
+        CustomRoute(page: BookConfirmPageRoute.page, path: RouterPath.facilityBookConfirm, transitionsBuilder: applySlideTransition),
       ];
 }

+ 20 - 0
packages/cpt_facility/lib/router/page/facility_page_router.gr.dart

@@ -15,6 +15,12 @@ abstract class _$FacilityPageRouter extends RootStackRouter {
 
   @override
   final Map<String, PageFactory> pagesMap = {
+    BookConfirmPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const BookConfirmPage(),
+      );
+    },
     FacilityActivePageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
@@ -61,6 +67,20 @@ abstract class _$FacilityPageRouter extends RootStackRouter {
 }
 
 /// generated route for
+/// [BookConfirmPage]
+class BookConfirmPageRoute extends PageRouteInfo<void> {
+  const BookConfirmPageRoute({List<PageRouteInfo>? children})
+      : super(
+          BookConfirmPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'BookConfirmPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
 /// [FacilityActiveScreen]
 class FacilityActivePageRoute extends PageRouteInfo<void> {
   const FacilityActivePageRoute({List<PageRouteInfo>? children})

+ 3 - 1
packages/cpt_notice_board/lib/modules/documents/page/documents_page.dart

@@ -11,6 +11,7 @@ import 'package:widgets/widget_export.dart';
 import 'package:cs_resources/generated/assets.dart';
 
 import '../../../router/page/notice_board_page_router.dart';
+import '../../documents_list/page/documents_list_page.dart';
 import '../vm/documents_vm.dart';
 
 @RoutePage()
@@ -104,7 +105,8 @@ class DocumentsPage extends HookConsumerWidget {
         ],
       ).onTap(() {
         // 去详情
-        _vm.goNewsDetail(item);
+        // _vm.goNewsDetail(item);
+        DocumentsListPage.startInstance(context: context);
       }),
     ).marginOnly(left: 15, bottom: 15, right: 15);
   }

+ 154 - 0
packages/cpt_notice_board/lib/modules/documents_list/page/documents_list_page.dart

@@ -0,0 +1,154 @@
+import 'package:cpt_notice_board/modules/notice_board/page/notice_board_page.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:shared/utils/log_utils.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:cs_resources/generated/assets.dart';
+
+import '../../../router/page/notice_board_page_router.dart';
+import '../vm/documents_list_vm.dart';
+
+@RoutePage()
+class DocumentsListPage extends HookConsumerWidget {
+  const DocumentsListPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const DocumentsListPageRoute());
+    } else {
+      appRouter.push(const DocumentsListPageRoute());
+    }
+  }
+
+  Widget _buildItemLeftSection(BuildContext context, WidgetRef ref, item, _vm) {
+    return Container(
+      // color: Colors.blue,
+      child: Text(
+        item['title'],
+        maxLines: 2, // 设置最大行数为2
+        overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
+        style: const TextStyle(
+            fontSize: 16.0,
+            color: Colors.black,
+            fontWeight: FontWeight.w700), // 设置字体大小
+      ),
+    ).marginOnly(right: 17.5);
+  }
+
+  Widget _buildItemRightSection(
+      BuildContext context, WidgetRef ref, item, _vm) {
+    return Container(
+      color: Colors.white,
+      child: TextButton(
+        onPressed: () {},
+        style: TextButton.styleFrom(
+          foregroundColor: Colors.black,
+          backgroundColor: ColorUtils.string2Color('#4161D0'), // 背景颜色
+          minimumSize: const Size(91.5, 30), // 最小宽度和高度
+          padding:
+              const EdgeInsets.symmetric(horizontal: 11.0, vertical: 9), // 内边距
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(5), // 圆角
+            side: BorderSide(
+              color: ColorUtils.string2Color('#4161D0'),
+              width: 1.0,
+            ), // 边框
+          ),
+        ),
+        child: const Text('Open Folder',
+          style: const TextStyle(color: Colors.white,),
+        ),
+      ),
+    );
+  }
+
+  // listitem
+  Widget _buildSaleItem(BuildContext context, WidgetRef ref, item, _vm) {
+    return Container(
+      decoration: const BoxDecoration(
+        color: Colors.white,
+        borderRadius: BorderRadius.all(Radius.circular(6.0)),
+        boxShadow: [
+          BoxShadow(color: Color.fromRGBO(184, 191, 217, 0.3), blurRadius: 6)
+        ],
+      ),
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.center,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        mainAxisSize: MainAxisSize.max,
+        children: [
+          Container(
+            width: MediaQuery.of(context).size.width - 30,
+            height: 70,
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.start,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                Expanded(child: _buildItemLeftSection(context, ref, item, _vm)),
+                Container(
+                  // width: 120,
+                  // child: _buildItemRightSection(context, ref, item, _vm),
+                  // child: TextButton(onPressed: (){}, child: Text("fdsfds")),
+                ),
+              ],
+            ).paddingOnly(left: 20,right: 20),
+          ).constrained(
+            minHeight: 70,
+          ),
+        ],
+      ).onTap(() {
+        // 去详情
+        _vm.goNewsDetail(item);
+      }),
+    ).marginOnly(left: 15, bottom: 15, right: 15);
+  }
+
+  // list
+  Widget _buildSaleList(BuildContext context, WidgetRef ref, _vm) {
+    List itemsList = _vm.state.list.toList();
+    return ListView.builder(
+      itemCount: itemsList.length,
+      itemBuilder: (context, index) {
+        return _buildSaleItem(context, ref, itemsList[index], _vm);
+      },
+    );
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final _vm = ref.read(documentsListVmProvider.notifier);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        "Documents",
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      body: Container(
+          child: EasyRefresh(
+        // 上拉加载
+        onLoad: () async {
+          Log.d("----onLoad");
+          _vm.onLoadData();
+        },
+        // 下拉刷新
+        onRefresh: () async {
+          Log.d("----onRefresh");
+          _vm.refreshListData();
+        },
+        child: Container(
+            color: ColorUtils.string2Color('#F2F3F6'),
+            padding: const EdgeInsets.only(top: 15),
+            child: _buildSaleList(context, ref, _vm)),
+      )),
+    );
+  }
+}

+ 49 - 0
packages/cpt_notice_board/lib/modules/documents_list/page/documents_list_state.dart

@@ -0,0 +1,49 @@
+/// YApi QuickType插件生成,具体参考文档:https://plugins.jetbrains.com/plugin/18847-yapi-quicktype/documentation
+
+import 'dart:convert';
+
+DocumentsListState documentsListStateFromJson(String str) => DocumentsListState.fromJson(json.decode(str));
+
+String documentsListStateToJson(DocumentsListState data) => json.encode(data.toJson());
+
+class DocumentsListState {
+  DocumentsListState({
+    required this.curPage,
+    required this.pageSize,
+    required this.list,
+    required this.filterCount,
+  });
+
+  int curPage;
+  int pageSize;
+  List<Map<String, dynamic>> list;
+  int filterCount;
+
+  factory DocumentsListState.fromJson(Map<dynamic, dynamic> json) => DocumentsListState(
+    curPage: json["curPage"],
+    pageSize: json["pageSize"],
+    list: List<Map<String, dynamic>>.from(json["list"].map((x) => x)),
+    filterCount: json["filterCount"],
+  );
+
+  Map<dynamic, dynamic> toJson() => {
+    "curPage": curPage,
+    "pageSize": pageSize,
+    "list": List<dynamic>.from(list.map((x) => x)),
+    "filterCount": filterCount,
+  };
+
+  DocumentsListState copyWith({
+    int? curPage,
+    int? pageSize,
+    List<Map<String, dynamic>>? list,
+    int? filterCount,
+  }) {
+    return DocumentsListState(
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      list: list ?? this.list,
+      filterCount: filterCount ?? this.filterCount,
+    );
+  }
+}

+ 70 - 0
packages/cpt_notice_board/lib/modules/documents_list/repository/documents_list_repository.dart

@@ -0,0 +1,70 @@
+import 'package:domain/constants/api_constants.dart';
+import 'package:domain/entity/server_time.dart';
+import 'package:plugin_platform/platform_export.dart';
+import 'package:plugin_platform/http/dio_engine.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/util.dart';
+
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:plugin_basic/provider/http_provider/http_provider.dart';
+
+import '../page/documents_list_state.dart';
+part 'documents_list_repository.g.dart';
+
+@Riverpod(keepAlive: true)
+DocumentsListRepository documentsListRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return DocumentsListRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class DocumentsListRepository {
+  DioEngine dioEngine;
+
+  DocumentsListRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchPropertyNewsList(
+      Map<String, dynamic>? data, {
+        CancelToken? cancelToken,
+      }) async {
+    Map<String, dynamic> params = {};
+
+    // if (!Utils.isEmpty(type)) {
+    //   params["type"] = type!;
+    // }
+
+    params = data!;
+
+
+    Map<String, String> headers = {};
+
+    headers["Content-Type"] = "application/x-www-form-urlencoded";
+    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+
+    final result = await dioEngine.requestNetResult(
+      // ApiConstants.apiServerTime, // api 地址
+      '/index.php/api/employee/extra/time', // api 地址
+      params: params,
+      headers: headers,
+      method: HttpMethod.GET,
+      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
+      networkDebounce: true,   //是否防抖防止重复请求
+      cancelToken: cancelToken,
+    );
+
+    //根据返回的结果,封装原始数据为Bean/Entity对象
+    if (result.isSuccess) {
+      //重新赋值data或list
+      final json = result.getDataJson();
+      var data = DocumentsListState.fromJson(json!);
+      //重新赋值data或list
+      return result.convert<DocumentsListState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 28 - 0
packages/cpt_notice_board/lib/modules/documents_list/repository/documents_list_repository.g.dart

@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'documents_list_repository.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$documentsListRepositoryHash() =>
+    r'68370656250ee691445b4293c3b30568d4ebf20b';
+
+/// See also [documentsListRepository].
+@ProviderFor(documentsListRepository)
+final documentsListRepositoryProvider = Provider<DocumentsListRepository>.internal(
+  documentsListRepository,
+  name: r'documentsListRepositoryProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$documentsListRepositoryHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+@Deprecated('Will be removed in 3.0. Use Ref instead')
+// ignore: unused_element
+typedef DocumentsListRepositoryRef = ProviderRef<DocumentsListRepository>;
+// 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

+ 105 - 0
packages/cpt_notice_board/lib/modules/documents_list/vm/documents_list_vm.dart

@@ -0,0 +1,105 @@
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import '../page/documents_list_state.dart';
+import '../repository/documents_list_repository.dart';
+part 'documents_list_vm.g.dart';
+
+@riverpod
+class DocumentsListVm extends _$DocumentsListVm {
+  late DocumentsListRepository documentsListRepository;
+  DocumentsListState initState() {
+    return DocumentsListState(
+      curPage: 1,
+      pageSize: 10,
+      list: [
+        {
+          "id": 1,
+          "title": "18 Sep 2024 BIK 39#09-XX 1337 psd 1001 sqft 39#09-XX 1337 psd 1001",
+          "price": "\$1.338 M",
+        },  
+        {
+          "id": 2,
+          "title": "18 Sep 2024 BIK 39#09-XX 1337 psd 1001 sqft",
+          "price": "\$1.338 M",
+        },
+      ],
+      filterCount: 2,
+    );
+  }
+
+  @override
+  DocumentsListState build() {
+    // 引入数据仓库
+    documentsListRepository = ref.read(documentsListRepositoryProvider);
+    // 初始化状态
+    DocumentsListState state = initState();
+    // 初始化列表数据
+    return state;
+  }
+
+  // 初始化页面数据
+  initPageData() {
+    Log.d("----property_news_vm-----initPageData");
+    refreshListData();
+  }
+
+  // 上拉加载
+  Future onLoadData() async {
+    Log.d("----property_news_vm-----initListData");
+    // await Future.delayed(const Duration(seconds: 2));
+    // if(state.list.length >= state.filterCount){
+    //   return;
+    // }else {
+    //   int curPage = state.curPage + 1;
+    //   state = state.copyWith(curPage: curPage,);
+    //   getListData();
+    // }
+    getListData();
+  }
+// 去新闻详情页
+  void goNewsDetail(String item) {
+    Log.d(item);
+    // PropertyPage.startInstance(context: context, item: item);
+  }
+  // 获取list 列表数据
+  void getListData<T>() async {
+    Log.d("加载listData数据---------------start-----");
+    try {
+      //请求网络
+      Map<String, dynamic>  params = {
+        "curPage": state.curPage,
+        "pageSize": state.pageSize,
+      };
+      Log.d("请求参数------$params");
+      final result = await documentsListRepository.fetchPropertyNewsList(params);
+      Log.d("请求完成结果------${result.data}");
+      //校验成功失败
+      if (result.isSuccess) {
+        // state = state.copyWith(serverTime: result.data);
+        state = state;
+        ToastEngine.show("获取数据成功");
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+  }
+
+
+  // 下拉刷新
+  Future refreshListData() async {
+    Log.d("----property_news_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(propertyNewsVmProvider);
+    getListData();
+
+  }
+
+}

+ 25 - 0
packages/cpt_notice_board/lib/modules/documents_list/vm/documents_list_vm.g.dart

@@ -0,0 +1,25 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'documents_list_vm.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$documentsListVmHash() => r'066315b56e78a801d048576f75f1e30b4816dbf5';
+
+/// See also [DocumentsListVm].
+@ProviderFor(DocumentsListVm)
+final documentsListVmProvider =
+    AutoDisposeNotifierProvider<DocumentsListVm, DocumentsListState>.internal(
+  DocumentsListVm.new,
+  name: r'documentsListVmProvider',
+  debugGetCreateSourceHash:
+      const bool.fromEnvironment('dart.vm.product') ? null : _$documentsListVmHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$DocumentsListVm = AutoDisposeNotifier<DocumentsListState>;
+// 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

+ 6 - 1
packages/cpt_notice_board/lib/modules/event/page/event_page.dart

@@ -1,3 +1,4 @@
+import 'package:cpt_notice_board/modules/event_detail/page/event_detail_page.dart';
 import 'package:cpt_notice_board/modules/notice_board/page/notice_board_page.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
@@ -86,7 +87,11 @@ class EventPage extends HookConsumerWidget {
         ],
       ).onTap(() {
         // 去详情
-        _vm.goNewsDetail(item['title']);
+        // _vm.goNewsDetail(item['title']);
+        Navigator.push(
+          context,
+          MaterialPageRoute(builder: (context) => const EventDetailPage()),
+        );
       }),
     ).marginOnly(left: 15, bottom: 15, right: 15);
   }

+ 121 - 0
packages/cpt_notice_board/lib/modules/event_detail/page/event_detail_page.dart

@@ -0,0 +1,121 @@
+import 'package:cpt_notice_board/modules/notice_board/page/notice_board_page.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:shared/utils/log_utils.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:cs_resources/generated/assets.dart';
+
+import '../../../router/page/notice_board_page_router.dart';
+import '../vm/event_detail_vm.dart';
+
+@RoutePage()
+class EventDetailPage extends HookConsumerWidget {
+  const EventDetailPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const EventDetailPageRoute());
+    } else {
+      appRouter.push(const EventDetailPageRoute());
+    }
+  }
+
+  Widget _buildDetailTop(BuildContext context, WidgetRef ref, _vm) {
+    // List itemsList = _vm.state.list.toList();
+    return Column(
+      children: [
+        Column(children: [
+          const Text(
+            'STANDARD OPERATING PROCEDURE FOR REPLACEMENT VEHICLES AND OVERNICHT PARKING VEHICLES(REMINDER)',
+            style: TextStyle(
+                fontSize: 18.0,
+                color: Colors.black,
+                fontWeight: FontWeight.w700), // 设置字体大小
+          ),
+          Row(
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              const MyAssetImage(
+                Assets.noticeBoardAnnouncementDetailOur,
+                width: 15,
+                height: 15,
+              ).marginOnly(right: 8),
+              const Text(
+                'Our ref: ',
+                style: TextStyle(
+                    fontSize: 15.0,
+                    color: Colors.black,
+                    fontWeight: FontWeight.w700), // 设置字体大小
+              ),
+              const Text(
+                '2024/CORR/CIR/112.V5',
+                style: TextStyle(
+                    fontSize: 15.0,
+                    color: Colors.black,
+                    fontWeight: FontWeight.w400), // 设置字体大小
+              ),
+            ],
+          ).marginOnly(top: 15),
+          const MyAssetImage(
+            Assets.propertyHomeLoanBg,
+            // width: 15,
+            // height: 15,
+          ).marginOnly(top: 25),
+        ]).paddingOnly(bottom: 25),
+        Column(
+          children: [
+            const Column(
+              mainAxisAlignment: MainAxisAlignment.center,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                Text(
+                  'IMPORTANT',
+                  style: TextStyle(
+                      fontSize: 18.0,
+                      color: Colors.black,
+                      fontWeight: FontWeight.w700), // 设置字体大小
+                )
+              ],
+            ).marginOnly(bottom: 25),
+            const Text(
+              'Dear Residents,STANDARD OPERATING PROCEDURE FORREPLACEMENT VEHICLES ANDOVERNICHT PARKING VEHICLES',
+              style: TextStyle(
+                  fontSize: 15.0,
+                  color: Colors.black,
+                  fontWeight: FontWeight.w400), // 设置字体大小
+            ),
+          ],
+        ).paddingOnly(top: 25, bottom: 50),
+      ],
+    );
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final _vm = ref.read(eventDetailVmProvider.notifier);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        "Lift Padding",
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      body: Container(
+          child: EasyRefresh(
+        child: Container(
+            color: ColorUtils.string2Color('#FFFFFF'),
+            padding: const EdgeInsets.only(top: 30, left: 15, right: 15),
+            child: _buildDetailTop(context, ref, _vm)),
+      )),
+    );
+  }
+}

+ 49 - 0
packages/cpt_notice_board/lib/modules/event_detail/page/event_detail_state.dart

@@ -0,0 +1,49 @@
+/// YApi QuickType插件生成,具体参考文档:https://plugins.jetbrains.com/plugin/18847-yapi-quicktype/documentation
+
+import 'dart:convert';
+
+EventDetailState eventDetailStateFromJson(String str) => EventDetailState.fromJson(json.decode(str));
+
+String eventDetailStateToJson(EventDetailState data) => json.encode(data.toJson());
+
+class EventDetailState {
+  EventDetailState({
+    required this.curPage,
+    required this.pageSize,
+    required this.list,
+    required this.filterCount,
+  });
+
+  int curPage;
+  int pageSize;
+  List<Map<String, dynamic>> list;
+  int filterCount;
+
+  factory EventDetailState.fromJson(Map<dynamic, dynamic> json) => EventDetailState(
+    curPage: json["curPage"],
+    pageSize: json["pageSize"],
+    list: List<Map<String, dynamic>>.from(json["list"].map((x) => x)),
+    filterCount: json["filterCount"],
+  );
+
+  Map<dynamic, dynamic> toJson() => {
+    "curPage": curPage,
+    "pageSize": pageSize,
+    "list": List<dynamic>.from(list.map((x) => x)),
+    "filterCount": filterCount,
+  };
+
+  EventDetailState copyWith({
+    int? curPage,
+    int? pageSize,
+    List<Map<String, dynamic>>? list,
+    int? filterCount,
+  }) {
+    return EventDetailState(
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      list: list ?? this.list,
+      filterCount: filterCount ?? this.filterCount,
+    );
+  }
+}

+ 70 - 0
packages/cpt_notice_board/lib/modules/event_detail/repository/event_detail_repository.dart

@@ -0,0 +1,70 @@
+import 'package:domain/constants/api_constants.dart';
+import 'package:domain/entity/server_time.dart';
+import 'package:plugin_platform/platform_export.dart';
+import 'package:plugin_platform/http/dio_engine.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/util.dart';
+
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:plugin_basic/provider/http_provider/http_provider.dart';
+
+import '../page/event_detail_state.dart';
+part 'event_detail_repository.g.dart';
+
+@Riverpod(keepAlive: true)
+EventDetailRepository eventDetailRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return EventDetailRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class EventDetailRepository {
+  DioEngine dioEngine;
+
+  EventDetailRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchPropertyNewsList(
+      Map<String, dynamic>? data, {
+        CancelToken? cancelToken,
+      }) async {
+    Map<String, dynamic> params = {};
+
+    // if (!Utils.isEmpty(type)) {
+    //   params["type"] = type!;
+    // }
+
+    params = data!;
+
+
+    Map<String, String> headers = {};
+
+    headers["Content-Type"] = "application/x-www-form-urlencoded";
+    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+
+    final result = await dioEngine.requestNetResult(
+      // ApiConstants.apiServerTime, // api 地址
+      '/index.php/api/employee/extra/time', // api 地址
+      params: params,
+      headers: headers,
+      method: HttpMethod.GET,
+      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
+      networkDebounce: true,   //是否防抖防止重复请求
+      cancelToken: cancelToken,
+    );
+
+    //根据返回的结果,封装原始数据为Bean/Entity对象
+    if (result.isSuccess) {
+      //重新赋值data或list
+      final json = result.getDataJson();
+      var data = EventDetailState.fromJson(json!);
+      //重新赋值data或list
+      return result.convert<EventDetailState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 28 - 0
packages/cpt_notice_board/lib/modules/event_detail/repository/event_detail_repository.g.dart

@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'event_detail_repository.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$eventDetailRepositoryHash() =>
+    r'73919ad1420beb9634eb70952bebb29e6b8f21d7';
+
+/// See also [eventDetailRepository].
+@ProviderFor(eventDetailRepository)
+final eventDetailRepositoryProvider = Provider<EventDetailRepository>.internal(
+  eventDetailRepository,
+  name: r'eventDetailRepositoryProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$eventDetailRepositoryHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+@Deprecated('Will be removed in 3.0. Use Ref instead')
+// ignore: unused_element
+typedef EventDetailRepositoryRef = ProviderRef<EventDetailRepository>;
+// 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

+ 105 - 0
packages/cpt_notice_board/lib/modules/event_detail/vm/event_detail_vm.dart

@@ -0,0 +1,105 @@
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import '../page/event_detail_state.dart';
+import '../repository/event_detail_repository.dart';
+part 'event_detail_vm.g.dart';
+
+@riverpod
+class EventDetailVm extends _$EventDetailVm {
+  late EventDetailRepository eventDetailRepository;
+  EventDetailState initState() {
+    return EventDetailState(
+      curPage: 1,
+      pageSize: 10,
+      list: [
+        {
+          "id": 1,
+          "title":
+              "The community will hold the activity of making Zongzi on the Loong Boat ……",
+          "price": "Monday 14 0ct 2024, 15:00 PM~18:00PM",
+        },
+        {
+          "id": 2,
+          "title": "Community basketball competition activities",
+          "price": "Monday 14 Oct 2024, 10:19 AM",
+        },
+      ],
+      filterCount: 2,
+    );
+  }
+
+  @override
+  EventDetailState build() {
+    // 引入数据仓库
+    eventDetailRepository = ref.read(eventDetailRepositoryProvider);
+    // 初始化状态
+    EventDetailState state = initState();
+    // 初始化列表数据
+    return state;
+  }
+
+  // 初始化页面数据
+  initPageData() {
+    Log.d("----property_news_vm-----initPageData");
+    refreshListData();
+  }
+
+  // 上拉加载
+  Future onLoadData() async {
+    Log.d("----property_news_vm-----initListData");
+    // await Future.delayed(const Duration(seconds: 2));
+    // if(state.list.length >= state.filterCount){
+    //   return;
+    // }else {
+    //   int curPage = state.curPage + 1;
+    //   state = state.copyWith(curPage: curPage,);
+    //   getListData();
+    // }
+    getListData();
+  }
+
+// 去新闻详情页
+  void goNewsDetail(String item) {
+    Log.d(item);
+    // PropertyPage.startInstance(context: context, item: item);
+  }
+
+  // 获取list 列表数据
+  void getListData<T>() async {
+    Log.d("加载listData数据---------------start-----");
+    try {
+      //请求网络
+      Map<String, dynamic> params = {
+        "curPage": state.curPage,
+        "pageSize": state.pageSize,
+      };
+      Log.d("请求参数------$params");
+      final result = await eventDetailRepository.fetchPropertyNewsList(params);
+      Log.d("请求完成结果------${result.data}");
+      //校验成功失败
+      if (result.isSuccess) {
+        // state = state.copyWith(serverTime: result.data);
+        state = state;
+        ToastEngine.show("获取数据成功");
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+  }
+
+  // 下拉刷新
+  Future refreshListData() async {
+    Log.d("----property_news_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(propertyNewsVmProvider);
+    getListData();
+  }
+}

+ 10 - 10
packages/cpt_services/lib/modules/services/vm/services_view_model.g.dart

@@ -1,26 +1,26 @@
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
-part of 'services_view_model.dart';
+part of 'event_detail_vm.dart';
 
 // **************************************************************************
 // RiverpodGenerator
 // **************************************************************************
 
-String _$servicesViewModelHash() => r'f2f28efe8edb9b152be0a1a4de4563d8d50cee29';
+String _$eventDetailVmHash() => r'7fe0ebbd7df15c661751f2b01a9d2efe53f975c7';
 
-/// See also [ServicesViewModel].
-@ProviderFor(ServicesViewModel)
-final servicesViewModelProvider =
-    AutoDisposeNotifierProvider<ServicesViewModel, void>.internal(
-  ServicesViewModel.new,
-  name: r'servicesViewModelProvider',
+/// See also [EventDetailVm].
+@ProviderFor(EventDetailVm)
+final eventDetailVmProvider =
+    AutoDisposeNotifierProvider<EventDetailVm, EventDetailState>.internal(
+  EventDetailVm.new,
+  name: r'eventDetailVmProvider',
   debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
       ? null
-      : _$servicesViewModelHash,
+      : _$eventDetailVmHash,
   dependencies: null,
   allTransitiveDependencies: null,
 );
 
-typedef _$ServicesViewModel = AutoDisposeNotifier<void>;
+typedef _$EventDetailVm = AutoDisposeNotifier<EventDetailState>;
 // 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

+ 0 - 71
packages/cpt_notice_board/lib/modules/notice_board/page/notice_board_page.dart

@@ -128,75 +128,4 @@ class NoticeBoardPage extends HookConsumerWidget {
           },
         ));
   }
-  // @override
-  // Widget build(BuildContext context, WidgetRef ref) {
-  //   final _viewModel = ref.read(noticeBoardVmProvider.notifier);
-  //   return Scaffold(
-  //     // appBar: MyAppBar.titleBar(context, "Test Title"),
-  //     body: Container(
-  //       child: Column(
-  //         children: [
-
-  //           MyAppBar.titleBar(context, "Test Title"),
-  //           const Padding(
-  //             padding: EdgeInsets.fromLTRB(15, 0, 15, 30),
-  //             child: Row(
-  //               mainAxisAlignment: MainAxisAlignment.spaceBetween,
-  //               children: [
-  //                 Column(children: [
-  //                   MyAssetImage(
-  //                     Assets.noticeBoardAnnouncementIcon,
-  //                     height: 70,
-  //                     width: 70,
-  //                   ),
-  //                   Text(
-  //                     "Announcement",
-  //                     style: TextStyle(
-  //                       color: Colors.black,
-  //                       fontSize: 15,
-  //                       fontWeight: FontWeight.bold,
-  //                       height: 1.5,
-  //                     ),
-  //                   )
-  //                 ]),
-  //                 Column(children: [
-  //                   MyAssetImage(
-  //                     Assets.noticeBoardEventIcon,
-  //                     height: 70,
-  //                     width: 70,
-  //                   ),
-  //                   Text(
-  //                     "Event",
-  //                     style: TextStyle(
-  //                       color: Colors.black,
-  //                       fontSize: 15,
-  //                       fontWeight: FontWeight.bold,
-  //                       height: 1.5,
-  //                     ),
-  //                   )
-  //                 ]),
-  //                 Column(children: [
-  //                   MyAssetImage(
-  //                     Assets.noticeBoardDocumentsIcon,
-  //                     height: 70,
-  //                     width: 70,
-  //                   ),
-  //                   Text(
-  //                     "Documents",
-  //                     style: TextStyle(
-  //                       color: Colors.black,
-  //                       fontSize: 15,
-  //                       fontWeight: FontWeight.bold,
-  //                       height: 1.5,
-  //                     ),
-  //                   )
-  //                 ]),
-  //               ],
-  //             ),
-  //           ),
-  //         ],
-  //       ),
-  //     ),
-  //   );
-  // }
 }

+ 1 - 1
packages/cpt_notice_board/lib/modules/notice_board/vm/notice_board_view_model.dart

@@ -82,7 +82,7 @@ class NoticeBoardVm extends _$NoticeBoardVm {
 
     // 初始时导航到子路由
     WidgetsBinding.instance.addPostFrameCallback((_) {
-      switchPage(state.curIdx ?? 0, null, true);
+      // switchPage(state.curIdx ?? 0, null, true);
     });
 
     return state;

+ 1 - 1
packages/cpt_notice_board/lib/modules/notice_board/vm/notice_board_view_model.g.dart

@@ -6,7 +6,7 @@ part of 'notice_board_view_model.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$noticeBoardVmHash() => r'35dfbf4845c7dca80ef6f737fbc529cb1f232a4f';
+String _$noticeBoardVmHash() => r'6692916d5cff8146096cd702bc90d2e5a53b355d';
 
 /// See also [NoticeBoardVm].
 @ProviderFor(NoticeBoardVm)

+ 12 - 0
packages/cpt_notice_board/lib/router/page/notice_board_page_router.dart

@@ -8,6 +8,8 @@ import '../../modules/announ/page/announ_page.dart';
 import '../../modules/event/page/event_page.dart';
 import '../../modules/documents/page/documents_page.dart';
 import '../../modules/announcement_detail/page/announcement_detail_page.dart';
+import '../../modules/event_detail/page/event_detail_page.dart';
+import '../../modules/documents_list/page/documents_list_page.dart';
 
 part 'notice_board_page_router.gr.dart';
 
@@ -44,5 +46,15 @@ class NoticeBoardPageRouter extends _$NoticeBoardPageRouter {
             path: RouterPath.announcementDetail,
             transitionsBuilder: applySlideTransition,
             children: []),
+            CustomRoute(
+            page: EventDetailPageRoute.page,
+            path: RouterPath.eventDetail,
+            transitionsBuilder: applySlideTransition,
+            children: []),
+            CustomRoute(
+            page: DocumentsListPageRoute.page,
+            path: RouterPath.documentsList,
+            transitionsBuilder: applySlideTransition,
+            children: []),
       ];
 }

+ 40 - 0
packages/cpt_notice_board/lib/router/page/notice_board_page_router.gr.dart

@@ -33,6 +33,18 @@ abstract class _$NoticeBoardPageRouter extends RootStackRouter {
         child: const DocumentsPage(),
       );
     },
+    EventDetailPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const EventDetailPage(),
+      );
+    },
+    DocumentsListPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const DocumentsListPage(),
+      );
+    },
     EventPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
@@ -91,6 +103,34 @@ class DocumentsPageRoute extends PageRouteInfo<void> {
 }
 
 /// generated route for
+/// [EventDetailPage]
+class EventDetailPageRoute extends PageRouteInfo<void> {
+  const EventDetailPageRoute({List<PageRouteInfo>? children})
+      : super(
+          EventDetailPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'EventDetailPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [DocumentsListPage]
+class DocumentsListPageRoute extends PageRouteInfo<void> {
+  const DocumentsListPageRoute({List<PageRouteInfo>? children})
+      : super(
+          DocumentsListPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'DocumentsListPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
 /// [EventPage]
 class EventPageRoute extends PageRouteInfo<void> {
   const EventPageRoute({List<PageRouteInfo>? children})

+ 122 - 0
packages/cpt_services/lib/modules/services/dialog/account_deactivation_dialog.dart

@@ -0,0 +1,122 @@
+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:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+class AccountDeactivationDialog extends StatelessWidget {
+  VoidCallback confirmAction;
+
+  AccountDeactivationDialog({
+    required this.confirmAction,
+  });
+  Widget CheckboxList(BuildContext context) {
+    final List<String> items = ['苹果', '香蕉', '橙子'];
+    final List<bool> selections = [false, false, false];
+    return Expanded(child:ListView.builder(
+      itemCount: items.length,
+      itemBuilder: (context, index) {
+        return Container(
+          padding: EdgeInsets.symmetric(vertical: 5.0),
+          child: CheckboxListTile(
+            value: selections[index],
+            onChanged: (bool? val) {
+              selections[index] = val!;
+            },
+            title: Text(items[index]),
+          ),
+        );
+      },
+    )
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.center,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Container(
+          width: double.infinity,
+          height: 55,
+          decoration: BoxDecoration(
+            color: context.appColors.btnBgDefault,
+            borderRadius: const BorderRadius.only(
+              topRight: Radius.circular(15),
+              topLeft: Radius.circular(15),
+            ),
+          ),
+          child: Row(
+            children: [
+              const SizedBox(width: 45),
+              MyTextView(
+                'Choose a Category',
+                fontSize: 18,
+                textAlign: TextAlign.center,
+                isFontMedium: true,
+                textColor: Colors.white,
+              ).expanded(),
+              const MyAssetImage(
+                Assets.baseServiceDialogDeleteIcon,
+                width: 25,
+                height: 25.5,
+              ).onTap(() {
+                onCancel();
+              }, padding: 10)
+            ],
+          ),
+        ),
+        Container(
+          width: double.infinity,
+          padding: const EdgeInsets.only(top: 22),
+          decoration: BoxDecoration(
+            color: context.appColors.whiteSecondBG,
+            borderRadius: const BorderRadius.only(
+              bottomLeft: Radius.circular(15),
+              bottomRight: Radius.circular(15),
+            ),
+          ),
+          child: Column(
+            children: [
+              CheckboxList(context),
+              Row(
+                children: [
+                  const SizedBox(width: 18),
+                  Expanded(
+                      flex: 1,
+                      child: InkWell(
+                        onTap: () async {
+                          onCancel();
+                          confirmAction();
+                        },
+                        child: MyTextView(
+                          'Ok',
+                          fontSize: 16,
+                          paddingTop: 13,
+                          paddingBottom: 13,
+                          isFontMedium: true,
+                          textAlign: TextAlign.center,
+                          textColor: Colors.white,
+                          backgroundColor: context.appColors.btnBgDefault,
+                          cornerRadius: 7,
+                        ),
+                      )),
+                  const SizedBox(width: 18),
+                ],
+              ).marginOnly(bottom: 30, top: 28),
+            ],
+          ),
+        ),
+      ],
+    ).constrained(width: 340);
+  }
+
+//取消弹框
+  void onCancel() async {
+    SmartDialog.dismiss();
+  }
+}

+ 0 - 33
packages/cpt_services/lib/modules/services/page/services_page.dart

@@ -1,33 +0,0 @@
-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 '../../../router/page/services_page_router.dart';
-import '../../services/vm/services_view_model.dart';
-
-@RoutePage()
-class ServicesPage extends HookConsumerWidget {
-  const ServicesPage({Key? key}) : super(key: key);
-
-  //启动当前页面
-  static void startInstance({BuildContext? context}) {
-    if (context != null) {
-      context.router.push(const ServicesPageRoute());
-    } else {
-      appRouter.push(const ServicesPageRoute());
-    }
-  }
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    final _viewModel = ref.read(servicesViewModelProvider.notifier);
-
-    return Scaffold(
-      appBar: AppBar(title: Text("广告服务")),
-      body: Center(
-        child: Text("广告服务的主页面"),
-      ),
-    );
-  }
-}

+ 206 - 0
packages/cpt_services/lib/modules/services/services_page.dart

@@ -0,0 +1,206 @@
+import 'package:shared/utils/log_utils.dart';
+import 'package:cs_resources/generated/assets.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/color_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../../router/page/services_page_router.dart';
+import 'services_view_model.dart';
+
+@RoutePage()
+class ServicesPage extends HookConsumerWidget {
+  const ServicesPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const ServicesPageRoute());
+    } else {
+      appRouter.push(const ServicesPageRoute());
+    }
+  }
+
+  Widget _buildTop(BuildContext context, WidgetRef ref, _vm) {
+    // List itemsList = _vm.state.list.toList();
+    return Container(
+        color: ColorUtils.string2Color('#FFFFFF'),
+        child: Column(children: [
+          Container(
+            width: double.infinity,
+            height: 160,
+            decoration: const BoxDecoration(
+              image: DecorationImage(
+                image: AssetImage(
+                    'packages/cs_resources/${Assets.propertyHomeLoanBg}'),
+                fit: BoxFit.fill, // 设置图片平铺
+              ),
+            ),
+          ).marginOnly(bottom: 15),
+          Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              const Text(
+                'Home Services!',
+                style: TextStyle(
+                    fontSize: 16.0,
+                    color: Colors.black,
+                    fontWeight: FontWeight.w400), // 设置字体大小
+              ),
+              TextButton(
+                onPressed: () {
+                  _vm.doDeleteAccount();
+                },
+                style: TextButton.styleFrom(
+                  foregroundColor: Colors.black,
+                  backgroundColor: ColorUtils.string2Color('#4161D0'), // 背景颜色
+                  minimumSize: const Size(70, 30), // 最小宽度和高度
+                  padding: const EdgeInsets.symmetric(
+                      horizontal: 11.0, vertical: 9), // 内边距
+                  shape: RoundedRectangleBorder(
+                    borderRadius: BorderRadius.circular(5), // 圆角
+                    side: BorderSide(
+                      color: ColorUtils.string2Color('#4161D0'),
+                      width: 1.0,
+                    ), // 边框
+                  ),
+                ),
+                child: const Text(
+                  'Filter',
+                  style: const TextStyle(
+                    color: Colors.white,
+                  ),
+                ),
+              ),
+            ],
+          ),
+        ])).paddingOnly(top: 10, left: 15, right: 15);
+  }
+
+  Widget _buildItem(BuildContext context, WidgetRef ref, _vm, item) {
+    return Container(
+            width: MediaQuery.of(context).size.width / 2 - 25,
+            height: 146,
+            decoration: const BoxDecoration(
+              color: Colors.white,
+              borderRadius: BorderRadius.all(Radius.circular(6.0)),
+              boxShadow: [
+                BoxShadow(
+                    color: Color.fromRGBO(184, 191, 217, 0.3), blurRadius: 6)
+              ],
+            ),
+            child: Column(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Row(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    Expanded(
+                      child: Text(
+                        maxLines: 2, // 设置最大行数为2
+                        overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
+                        item['title'],
+                        style: const TextStyle(
+                            fontSize: 16.0,
+                            color: Colors.black,
+                            fontWeight: FontWeight.w700),
+                      ),
+                    )
+                  ],
+                ),
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.end,
+                  children: [
+                    MyAssetImage(
+                      item['price'],
+                      width: 110,
+                      height: 80,
+                    )
+                  ],
+                ),
+              ],
+            ).paddingOnly(top: 15, left: 15))
+        .marginOnly(bottom: 15);
+  }
+
+// list
+  Widget _buildSaleList(BuildContext context, WidgetRef ref, _vm) {
+    List itemsList = _vm.state.list.toList();
+    return ListView.builder(
+      itemCount: itemsList.length,
+      itemBuilder: (context, index) {
+        bool noLast = !(index == itemsList.length - 1);
+        bool isLast = index == itemsList.length - 1;
+        if (index % 2 == 0 && noLast) {
+          return Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              _buildItem(context, ref, _vm, itemsList[index]),
+              _buildItem(context, ref, _vm, itemsList[index + 1]),
+            ],
+          );
+        } else if (index % 2 != 0 && noLast) {
+          return Row();
+        } else if (index % 2 != 0 && isLast) {
+          return Row();
+        } else {
+          return Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              _buildItem(context, ref, _vm, itemsList[index]),
+            ],
+          );
+        }
+        // _buildSaleItem(context, ref, itemsList[index], _vm);
+      },
+    );
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final state = ref.watch(servicesVmProvider);
+    final _vm = ref.read(servicesVmProvider.notifier);
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        "Service",
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      body: Container(
+        child: Column(
+          children: [
+            _buildTop(context, ref, _vm),
+            Expanded(
+              child: EasyRefresh(
+                // 上拉加载
+                onLoad: () async {
+                  Log.d("----onLoad");
+                  _vm.onLoadData();
+                },
+                // 下拉刷新
+                onRefresh: () async {
+                  Log.d("----onRefresh");
+                  _vm.refreshListData();
+                },
+                child: Container(
+                    color: ColorUtils.string2Color('#F2F3F6'),
+                    padding: const EdgeInsets.only(
+                        bottom: 15, left: 15, right: 15, top: 15),
+                    child: _buildSaleList(context, ref, _vm)),
+              ),
+            )
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 70 - 0
packages/cpt_services/lib/modules/services/services_repository.dart

@@ -0,0 +1,70 @@
+import 'package:domain/constants/api_constants.dart';
+import 'package:domain/entity/server_time.dart';
+import 'package:plugin_platform/platform_export.dart';
+import 'package:plugin_platform/http/dio_engine.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/util.dart';
+
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:plugin_basic/provider/http_provider/http_provider.dart';
+
+import 'services_state.dart';
+part 'services_repository.g.dart';
+
+@Riverpod(keepAlive: true)
+ServicesRepository servicesRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return ServicesRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class ServicesRepository {
+  DioEngine dioEngine;
+
+  ServicesRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchPropertyNewsList(
+      Map<String, dynamic>? data, {
+        CancelToken? cancelToken,
+      }) async {
+    Map<String, dynamic> params = {};
+
+    // if (!Utils.isEmpty(type)) {
+    //   params["type"] = type!;
+    // }
+
+    params = data!;
+
+
+    Map<String, String> headers = {};
+
+    headers["Content-Type"] = "application/x-www-form-urlencoded";
+    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+
+    final result = await dioEngine.requestNetResult(
+      // ApiConstants.apiServerTime, // api 地址
+      '/index.php/api/employee/extra/time', // api 地址
+      params: params,
+      headers: headers,
+      method: HttpMethod.GET,
+      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
+      networkDebounce: true,   //是否防抖防止重复请求
+      cancelToken: cancelToken,
+    );
+
+    //根据返回的结果,封装原始数据为Bean/Entity对象
+    if (result.isSuccess) {
+      //重新赋值data或list
+      final json = result.getDataJson();
+      var data = ServicesState.fromJson(json!);
+      //重新赋值data或list
+      return result.convert<ServicesState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 28 - 0
packages/cpt_services/lib/modules/services/services_repository.g.dart

@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'services_repository.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$servicesRepositoryHash() =>
+    r'68370656250ee691445b4293c3b30568d4ebf20b';
+
+/// See also [servicesRepository].
+@ProviderFor(servicesRepository)
+final servicesRepositoryProvider = Provider<ServicesRepository>.internal(
+  servicesRepository,
+  name: r'servicesRepositoryProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$servicesRepositoryHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+@Deprecated('Will be removed in 3.0. Use Ref instead')
+// ignore: unused_element
+typedef ServicesRepositoryRef = ProviderRef<ServicesRepository>;
+// 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

+ 50 - 0
packages/cpt_services/lib/modules/services/services_state.dart

@@ -0,0 +1,50 @@
+/// YApi QuickType插件生成,具体参考文档:https://plugins.jetbrains.com/plugin/18847-yapi-quicktype/documentation
+
+import 'dart:convert';
+
+ServicesState servicesStateFromJson(String str) =>
+    ServicesState.fromJson(json.decode(str));
+
+String servicesStateToJson(ServicesState data) => json.encode(data.toJson());
+
+class ServicesState {
+  ServicesState({
+    required this.curPage,
+    required this.pageSize,
+    required this.list,
+    required this.filterCount,
+  });
+
+  int curPage;
+  int pageSize;
+  List<Map<String, dynamic>> list;
+  int filterCount;
+
+  factory ServicesState.fromJson(Map<dynamic, dynamic> json) => ServicesState(
+        curPage: json["curPage"],
+        pageSize: json["pageSize"],
+        list: List<Map<String, dynamic>>.from(json["list"].map((x) => x)),
+        filterCount: json["filterCount"],
+      );
+
+  Map<dynamic, dynamic> toJson() => {
+        "curPage": curPage,
+        "pageSize": pageSize,
+        "list": List<dynamic>.from(list.map((x) => x)),
+        "filterCount": filterCount,
+      };
+
+  ServicesState copyWith({
+    int? curPage,
+    int? pageSize,
+    List<Map<String, dynamic>>? list,
+    int? filterCount,
+  }) {
+    return ServicesState(
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      list: list ?? this.list,
+      filterCount: filterCount ?? this.filterCount,
+    );
+  }
+}

+ 175 - 0
packages/cpt_services/lib/modules/services/services_view_model.dart

@@ -0,0 +1,175 @@
+import 'package:cpt_services/modules/services/dialog/account_deactivation_dialog.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/http/http_result.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'services_state.dart';
+import 'services_repository.dart';
+part 'services_view_model.g.dart';
+
+@riverpod
+class ServicesVm extends _$ServicesVm {
+  late ServicesRepository servicesRepository;
+  ServicesState initState() {
+    return ServicesState(
+      curPage: 1,
+      pageSize: 10,
+      list: [
+        {
+          "id": 1,
+          "title": "Part-TimeCleaning",
+          "price": Assets.serviceServiceIcon1,
+        },
+        {
+          "id": 2,
+          "title": "Move in/outcleaning",
+          "price": Assets.serviceServiceIcon2,
+        },
+        {
+          "id": 3,
+          "title": "Laundry AnddryCleaning",
+          "price": Assets.serviceServiceIcon3,
+        },
+        {
+          "id": 4,
+          "title": "SofaCleaning",
+          "price": Assets.serviceServiceIcon4,
+        },
+        {
+          "id": 5,
+          "title": "MattressCleaning",
+          "price": Assets.serviceServiceIcon5,
+        },
+         {
+          "id": 5,
+          "title": "MarbleCleaning",
+          "price": Assets.serviceServiceIcon6,
+        },
+        {
+          "id": 6,
+          "title": "ParquetCleaning",
+          "price": Assets.serviceServiceIcon7,
+        },
+        {
+          "id": 6,
+          "title": "Removalist",
+          "price": Assets.serviceServiceIcon8,
+        },
+         {
+          "id": 7,
+          "title": "CarpetCleaning",
+          "price": Assets.serviceServiceIcon9,
+        },
+        {
+          "id": 7,
+          "title": "InteriorDesign",
+          "price": Assets.serviceServiceIcon10,
+        },
+        {
+          "id": 7,
+          "title": "DomesticHelper agency",
+          "price": Assets.serviceServiceIcon11,
+        },
+        {
+          "id": 7,
+          "title": "Recycling AndDisposal Service",
+          "price": Assets.serviceServiceIcon12,
+        },
+        {
+          "id": 7,
+          "title": "Sell YourPre-Loved Items",
+          "price": Assets.serviceServiceIcon13,
+        },
+        {
+          "id": 7,
+          "title": "UpholsteryCleaning",
+          "price": Assets.serviceServiceIcon14,
+        },
+      ],
+      filterCount: 6,
+    );
+  }
+
+  @override
+  ServicesState build() {
+    // 引入数据仓库
+    servicesRepository = ref.read(servicesRepositoryProvider);
+    // 初始化状态
+    ServicesState state = initState();
+    // 初始化列表数据
+    return state;
+  }
+
+  // 初始化页面数据
+  initPageData() {
+    Log.d("----property_news_vm-----initPageData");
+    refreshListData();
+  }
+
+  // 上拉加载
+  Future onLoadData() async {
+    Log.d("----property_news_vm-----initListData");
+    // await Future.delayed(const Duration(seconds: 2));
+    // if(state.list.length >= state.filterCount){
+    //   return;
+    // }else {
+    //   int curPage = state.curPage + 1;
+    //   state = state.copyWith(curPage: curPage,);
+    //   getListData();
+    // }
+    getListData();
+  }
+
+// 去新闻详情页
+  void goNewsDetail(String item) {
+    Log.d(item);
+    // PropertyPage.startInstance(context: context, item: item);
+  }
+
+  // 获取list 列表数据
+  void getListData<T>() async {
+    Log.d("加载listData数据---------------start-----");
+    try {
+      //请求网络
+      Map<String, dynamic> params = {
+        "curPage": state.curPage,
+        "pageSize": state.pageSize,
+      };
+      Log.d("请求参数------$params");
+      final result = await servicesRepository.fetchPropertyNewsList(params);
+      Log.d("请求完成结果------${result.data}");
+      //校验成功失败
+      if (result.isSuccess) {
+        // state = state.copyWith(serverTime: result.data);
+        state = state;
+        ToastEngine.show("获取数据成功");
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+  }
+
+  // 下拉刷新
+  Future refreshListData() async {
+    Log.d("----property_news_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(propertyNewsVmProvider);
+    getListData();
+  }
+
+  void doDeleteAccount() {
+    DialogEngine.show(widget: AccountDeactivationDialog(
+      confirmAction: () {
+        ToastEngine.show("点击了确定");
+      },
+    ));
+  }
+}

+ 25 - 0
packages/cpt_services/lib/modules/services/services_view_model.g.dart

@@ -0,0 +1,25 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'services_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$servicesVmHash() => r'066315b56e78a801d048576f75f1e30b4816dbf5';
+
+/// See also [ServicesVm].
+@ProviderFor(ServicesVm)
+final servicesVmProvider =
+    AutoDisposeNotifierProvider<ServicesVm, ServicesState>.internal(
+  ServicesVm.new,
+  name: r'servicesVmProvider',
+  debugGetCreateSourceHash:
+      const bool.fromEnvironment('dart.vm.product') ? null : _$servicesVmHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$ServicesVm = AutoDisposeNotifier<ServicesState>;
+// 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

+ 0 - 14
packages/cpt_services/lib/modules/services/vm/services_view_model.dart

@@ -1,14 +0,0 @@
-
-import 'package:riverpod_annotation/riverpod_annotation.dart';
-
-part 'services_view_model.g.dart';
-
-@riverpod
-class ServicesViewModel extends _$ServicesViewModel {
-
-  @override
-  void build(){
-
-  }
-
-}

+ 1 - 1
packages/cpt_services/lib/router/component/services_component_service.dart

@@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 
-import '../../modules/services/page/services_page.dart';
+import '../../modules/services/services_page.dart';
 
 part 'services_component_service.g.dart';
 

+ 1 - 1
packages/cpt_services/lib/router/page/services_page_router.dart

@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:router/path/router_path.dart';
 
-import '../../modules/services/page/services_page.dart';
+import '../../modules/services/services_page.dart';
 
 
 part 'services_page_router.gr.dart';

BIN
packages/cs_resources/assets/base_lib/calendar_left_icon.webp


BIN
packages/cs_resources/assets/base_lib/calendar_right_icon.webp


BIN
packages/cs_resources/assets/service/service_icon_1.png


BIN
packages/cs_resources/assets/service/service_icon_10.png


BIN
packages/cs_resources/assets/service/service_icon_11.png


BIN
packages/cs_resources/assets/service/service_icon_12.png


BIN
packages/cs_resources/assets/service/service_icon_13.png


BIN
packages/cs_resources/assets/service/service_icon_14.png


BIN
packages/cs_resources/assets/service/service_icon_2.png


BIN
packages/cs_resources/assets/service/service_icon_3.png


BIN
packages/cs_resources/assets/service/service_icon_4.png


BIN
packages/cs_resources/assets/service/service_icon_5.png


BIN
packages/cs_resources/assets/service/service_icon_6.png


BIN
packages/cs_resources/assets/service/service_icon_7.png


BIN
packages/cs_resources/assets/service/service_icon_8.png


BIN
packages/cs_resources/assets/service/service_icon_9.png


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

@@ -16,6 +16,8 @@ class Assets {
   static const String authSmsVerifyImg = 'assets/auth/sms_verify_img.webp';
   static const String authYyHomeSuccess = 'assets/auth/yy_home_success.webp';
   static const String baseLibBlackBack = 'assets/base_lib/black_back.webp';
+  static const String baseLibCalendarLeftIcon = 'assets/base_lib/calendar_left_icon.webp';
+  static const String baseLibCalendarRightIcon = 'assets/base_lib/calendar_right_icon.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';
@@ -143,5 +145,19 @@ class Assets {
   static const String propertyRefinancing = 'assets/property/refinancing.webp';
   static const String propertyRent = 'assets/property/rent.webp';
   static const String propertySale = 'assets/property/sale.webp';
+  static const String serviceServiceIcon1 = 'assets/service/service_icon_1.png';
+  static const String serviceServiceIcon10 = 'assets/service/service_icon_10.png';
+  static const String serviceServiceIcon11 = 'assets/service/service_icon_11.png';
+  static const String serviceServiceIcon12 = 'assets/service/service_icon_12.png';
+  static const String serviceServiceIcon13 = 'assets/service/service_icon_13.png';
+  static const String serviceServiceIcon14 = 'assets/service/service_icon_14.png';
+  static const String serviceServiceIcon2 = 'assets/service/service_icon_2.png';
+  static const String serviceServiceIcon3 = 'assets/service/service_icon_3.png';
+  static const String serviceServiceIcon4 = 'assets/service/service_icon_4.png';
+  static const String serviceServiceIcon5 = 'assets/service/service_icon_5.png';
+  static const String serviceServiceIcon6 = 'assets/service/service_icon_6.png';
+  static const String serviceServiceIcon7 = 'assets/service/service_icon_7.png';
+  static const String serviceServiceIcon8 = 'assets/service/service_icon_8.png';
+  static const String serviceServiceIcon9 = 'assets/service/service_icon_9.png';
 
 }

+ 10 - 2
packages/cs_resources/lib/generated/intl/messages_en.dart

@@ -24,7 +24,10 @@ class MessageLookup extends MessageLookupByLibrary {
 
   static String m1(count) => "${count} Characters";
 
-  static String m2(name) => "Welcome ${name}";
+  static String m2(count, date) =>
+      "You have ${count}x quota left (resets on ${date})";
+
+  static String m3(name) => "Welcome ${name}";
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -53,6 +56,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "booking_successful":
             MessageLookupByLibrary.simpleMessage("BOOKING SUCCESSFUL"),
         "cancel": MessageLookupByLibrary.simpleMessage("Cancel"),
+        "card_caps": MessageLookupByLibrary.simpleMessage("CARD"),
+        "change": MessageLookupByLibrary.simpleMessage("Change"),
         "change_mobile_phone":
             MessageLookupByLibrary.simpleMessage("Change Mobile Phone"),
         "characters": m1,
@@ -177,6 +182,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "phone_email": MessageLookupByLibrary.simpleMessage("Phone/Email"),
         "privacy_policy":
             MessageLookupByLibrary.simpleMessage("Privacy Policy"),
+        "proceed_with_payment":
+            MessageLookupByLibrary.simpleMessage("Proceed With Payment"),
         "property": MessageLookupByLibrary.simpleMessage("Property"),
         "property_guide":
             MessageLookupByLibrary.simpleMessage("Property Guide"),
@@ -186,6 +193,7 @@ class MessageLookup extends MessageLookupByLibrary {
             "Your feedback has been successfully sent! We will reply to you as soon as possible! thank you!"),
         "published_successfully":
             MessageLookupByLibrary.simpleMessage("Published Successfully"),
+        "quota_left_msg": m2,
         "rate_us": MessageLookupByLibrary.simpleMessage("Rate Us"),
         "remove": MessageLookupByLibrary.simpleMessage("Remove"),
         "remove_account":
@@ -257,7 +265,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("Visitor Registration"),
         "waiting_for_the_administrator": MessageLookupByLibrary.simpleMessage(
             "Waiting for the administrator"),
-        "welcome_name": m2,
+        "welcome_name": m3,
         "who_are_owners":
             MessageLookupByLibrary.simpleMessage("Who are owners?"),
         "who_are_tenants":

+ 8 - 2
packages/cs_resources/lib/generated/intl/messages_zh_CN.dart

@@ -24,7 +24,9 @@ class MessageLookup extends MessageLookupByLibrary {
 
   static String m1(count) => "${count} 字符";
 
-  static String m2(name) => "欢迎你 ${name}";
+  static String m2(count, date) => "你还剩余${count}次的配额 (重置于${date})";
+
+  static String m3(name) => "欢迎你 ${name}";
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -49,6 +51,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "booking_fee": MessageLookupByLibrary.simpleMessage("预定费用"),
         "booking_successful": MessageLookupByLibrary.simpleMessage("预定成功"),
         "cancel": MessageLookupByLibrary.simpleMessage("取消"),
+        "card_caps": MessageLookupByLibrary.simpleMessage("信用卡"),
+        "change": MessageLookupByLibrary.simpleMessage("更换"),
         "change_mobile_phone": MessageLookupByLibrary.simpleMessage("修改手机号码"),
         "characters": m1,
         "choose_category": MessageLookupByLibrary.simpleMessage("选择类型"),
@@ -144,6 +148,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "payment": MessageLookupByLibrary.simpleMessage("支付"),
         "phone_email": MessageLookupByLibrary.simpleMessage("电话或邮箱"),
         "privacy_policy": MessageLookupByLibrary.simpleMessage("隐私协议"),
+        "proceed_with_payment": MessageLookupByLibrary.simpleMessage("继续付款"),
         "property": MessageLookupByLibrary.simpleMessage("房产"),
         "property_guide": MessageLookupByLibrary.simpleMessage("物业指南"),
         "property_news": MessageLookupByLibrary.simpleMessage("资产新闻"),
@@ -151,6 +156,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "published_successful_txt":
             MessageLookupByLibrary.simpleMessage("您的反馈已发送成功,我们会尽快回复您的反馈,谢谢!"),
         "published_successfully": MessageLookupByLibrary.simpleMessage("发布成功"),
+        "quota_left_msg": m2,
         "rate_us": MessageLookupByLibrary.simpleMessage("评价我们"),
         "remove": MessageLookupByLibrary.simpleMessage("移除"),
         "remove_account": MessageLookupByLibrary.simpleMessage("移除账号"),
@@ -209,7 +215,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "visitor_registration": MessageLookupByLibrary.simpleMessage("访客登记"),
         "waiting_for_the_administrator":
             MessageLookupByLibrary.simpleMessage("等待管理员回复"),
-        "welcome_name": m2,
+        "welcome_name": m3,
         "who_are_owners": MessageLookupByLibrary.simpleMessage("怎样才算业主?"),
         "who_are_tenants": MessageLookupByLibrary.simpleMessage("怎样才算租户?"),
         "yes": MessageLookupByLibrary.simpleMessage("是"),

+ 8 - 2
packages/cs_resources/lib/generated/intl/messages_zh_HK.dart

@@ -24,7 +24,9 @@ class MessageLookup extends MessageLookupByLibrary {
 
   static String m1(count) => "${count} 字符";
 
-  static String m2(name) => "欢迎你 ${name}";
+  static String m2(count, date) => "你还剩余${count}次的配额 (重置于${date})";
+
+  static String m3(name) => "欢迎你 ${name}";
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@@ -49,6 +51,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "booking_fee": MessageLookupByLibrary.simpleMessage("预定费用"),
         "booking_successful": MessageLookupByLibrary.simpleMessage("预定成功"),
         "cancel": MessageLookupByLibrary.simpleMessage("取消"),
+        "card_caps": MessageLookupByLibrary.simpleMessage("信用卡"),
+        "change": MessageLookupByLibrary.simpleMessage("更换"),
         "change_mobile_phone": MessageLookupByLibrary.simpleMessage("修改手机号码"),
         "characters": m1,
         "choose_category": MessageLookupByLibrary.simpleMessage("选择类型"),
@@ -136,6 +140,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "payment": MessageLookupByLibrary.simpleMessage("支付"),
         "phone_email": MessageLookupByLibrary.simpleMessage("电话或邮箱"),
         "privacy_policy": MessageLookupByLibrary.simpleMessage("隐私协议"),
+        "proceed_with_payment": MessageLookupByLibrary.simpleMessage("继续付款"),
         "property": MessageLookupByLibrary.simpleMessage("房产"),
         "property_guide": MessageLookupByLibrary.simpleMessage("物业指南"),
         "property_news": MessageLookupByLibrary.simpleMessage("资产新闻"),
@@ -143,6 +148,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "published_successful_txt":
             MessageLookupByLibrary.simpleMessage("您的反馈已发送成功,我们会尽快回复您的反馈,谢谢!"),
         "published_successfully": MessageLookupByLibrary.simpleMessage("发布成功"),
+        "quota_left_msg": m2,
         "rate_us": MessageLookupByLibrary.simpleMessage("评价我们"),
         "remove": MessageLookupByLibrary.simpleMessage("移除"),
         "remove_account": MessageLookupByLibrary.simpleMessage("移除账号"),
@@ -196,7 +202,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "visitor_registration": MessageLookupByLibrary.simpleMessage("访客登记"),
         "waiting_for_the_administrator":
             MessageLookupByLibrary.simpleMessage("等待管理员回复"),
-        "welcome_name": m2,
+        "welcome_name": m3,
         "yes": MessageLookupByLibrary.simpleMessage("是"),
         "you_have": MessageLookupByLibrary.simpleMessage("你还有"),
         "your_roles_responsibilities":

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

@@ -1680,6 +1680,46 @@ class S {
     );
   }
 
+  /// `You have {count}x quota left (resets on {date})`
+  String quota_left_msg(Object count, Object date) {
+    return Intl.message(
+      'You have ${count}x quota left (resets on $date)',
+      name: 'quota_left_msg',
+      desc: '',
+      args: [count, date],
+    );
+  }
+
+  /// `CARD`
+  String get card_caps {
+    return Intl.message(
+      'CARD',
+      name: 'card_caps',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Change`
+  String get change {
+    return Intl.message(
+      'Change',
+      name: 'change',
+      desc: '',
+      args: [],
+    );
+  }
+
+  /// `Proceed With Payment`
+  String get proceed_with_payment {
+    return Intl.message(
+      'Proceed With Payment',
+      name: 'proceed_with_payment',
+      desc: '',
+      args: [],
+    );
+  }
+
   /// `Other`
   String get other {
     return Intl.message(

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

@@ -162,5 +162,9 @@
   "booking_fee": "Booking Fee",
   "on_hold": "On Hold",
   "total": "Total",
+  "quota_left_msg": "You have {count}x quota left (resets on {date})",
+  "card_caps": "CARD",
+  "change": "Change",
+  "proceed_with_payment": "Proceed With Payment",
   "other": "Other"
 }

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

@@ -162,5 +162,9 @@
   "booking_fee": "预定费用",
   "on_hold": "持有",
   "total": "共计",
+  "quota_left_msg": "你还剩余{count}次的配额 (重置于{date})",
+  "card_caps": "信用卡",
+  "change": "更换",
+  "proceed_with_payment": "继续付款",
   "other": "其他"
 }

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

@@ -148,5 +148,9 @@
   "booking_fee": "预定费用",
   "on_hold": "持有",
   "total": "共计",
+  "quota_left_msg": "你还剩余{count}次的配额 (重置于{date})",
+  "card_caps": "信用卡",
+  "change": "更换",
+  "proceed_with_payment": "继续付款",
   "other": "其他"
 }

+ 1 - 0
packages/cs_resources/pubspec.yaml

@@ -33,6 +33,7 @@ flutter:
     - assets/main/
     - assets/profile/
     - assets/facility/
+    - assets/service/
 
 
 flutter_intl:

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

@@ -5,7 +5,5 @@ abstract class AuthService {
 
   void startLoginPage();
 
-  void startResetPasswordPage();
-
   void startSelectEstatePage();
 }

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

@@ -58,6 +58,7 @@ class RouterPath {
   static const facility = '/facility';
   static const facilityDetail = '/facility/detail';
   static const facilityBook = '/facility/book';
+  static const facilityBookConfirm = '/facility/book/confirm';
 
   //表单
   static const form = '/form';
@@ -67,7 +68,9 @@ class RouterPath {
   static const announ = 'notice_board/announ';
   static const event = 'notice_board/event';
   static const documents = 'notice_board/documents';
-  static const announcementDetail = '/notice_board/announcement_detail';  
+  static const announcementDetail = '/notice_board/announcement_detail';
+  static const eventDetail = '/notice_board/event_detail';  
+  static const documentsList = '/notice_board/documents_list';
   
 
   //支付

+ 49 - 0
packages/cs_widgets/lib/shatter/select_calendar/calendar_bottom_sheet.dart

@@ -0,0 +1,49 @@
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'full_calendar.dart';
+
+class CustomCalendarBottomSheet extends StatelessWidget {
+  final DateTime firstDate;
+  final DateTime? lastDate;
+  final String locale;
+  final DateTime selectedDate;
+  final Function(DateTime) onDateChange;
+
+  const CustomCalendarBottomSheet({
+    Key? key,
+    required this.firstDate,
+    this.lastDate,
+    required this.selectedDate,
+    required this.locale,
+    required this.onDateChange,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        const SizedBox(height: 20),
+        Container(
+          width: 60,
+          height: 6,
+          decoration: BoxDecoration(borderRadius: BorderRadius.circular(3.0), color: const Color(0xFFE0E0E0)),
+        ),
+        const SizedBox(height: 13.0),
+        FullCalendar(
+          startDate: firstDate,
+          endDate: lastDate,
+          selectedDate: selectedDate,
+          padding: 25,
+          locale: locale,
+          dateColor: context.appColors.textBlack,
+          dateSelectedBg: context.appColors.btnBgDefault,
+          dateSelectedColor: Colors.white,
+          events: [],
+          onDateChange: onDateChange,
+        ),
+      ],
+    );
+  }
+}

+ 336 - 0
packages/cs_widgets/lib/shatter/select_calendar/full_calendar.dart

@@ -0,0 +1,336 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+
+//日历的具体展示
+class FullCalendar extends StatefulWidget {
+  final DateTime startDate;
+  final DateTime? endDate;
+  final DateTime? selectedDate;
+  final Color? dateColor;
+  final Color? dateSelectedColor;
+  final Color? dateSelectedBg;
+  final double? padding;
+  final String? locale;
+  final Widget? calendarBackground;
+  final List<String>? events;
+  final Function onDateChange;
+
+  const FullCalendar({
+    Key? key,
+    this.endDate,
+    required this.startDate,
+    required this.padding,
+    required this.onDateChange,
+    this.calendarBackground,
+    this.events,
+    this.dateColor,
+    this.dateSelectedColor,
+    this.dateSelectedBg,
+    this.locale,
+    this.selectedDate,
+  }) : super(key: key);
+
+  @override
+  State<FullCalendar> createState() => _FullCalendarState();
+}
+
+class _FullCalendarState extends State<FullCalendar> {
+  late DateTime endDate;
+
+  late DateTime startDate;
+  late int _initialPage;
+
+  List<String>? _events = [];
+
+  late PageController _horizontalScroll;
+
+  @override
+  void initState() {
+    setState(() {
+      startDate = DateTime.parse("${widget.startDate.toString().split(" ").first} 00:00:00.000");
+
+      endDate = DateTime.parse("${widget.endDate.toString().split(" ").first} 23:00:00.000");
+
+      _events = widget.events;
+    });
+
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    List<String> partsStart = startDate.toString().split(" ").first.split("-");
+
+    DateTime firstDate = DateTime.parse("${partsStart.first}-${partsStart[1].padLeft(2, '0')}-01 00:00:00.000");
+
+    List<String> partsEnd = endDate.toString().split(" ").first.split("-");
+
+    DateTime lastDate =
+        DateTime.parse("${partsEnd.first}-${(int.parse(partsEnd[1]) + 1).toString().padLeft(2, '0')}-01 23:00:00.000").subtract(const Duration(days: 1));
+
+    double width = MediaQuery.of(context).size.width - (2 * widget.padding!);
+
+    List<DateTime?> dates = [];
+
+    DateTime referenceDate = firstDate;
+
+    while (referenceDate.isBefore(lastDate)) {
+      List<String> referenceParts = referenceDate.toString().split(" ");
+      DateTime newDate = DateTime.parse("${referenceParts.first} 12:00:00.000");
+      dates.add(newDate);
+
+      referenceDate = newDate.add(const Duration(days: 1));
+    }
+
+    if (firstDate.year == lastDate.year && firstDate.month == lastDate.month) {
+      return Padding(
+        padding: EdgeInsets.fromLTRB(widget.padding!, 40.0, widget.padding!, 0.0),
+        child: month(dates, width, widget.locale),
+      );
+    } else {
+      List<DateTime?> months = [];
+      for (int i = 0; i < dates.length; i++) {
+        if (i == 0 || (dates[i]!.month != dates[i - 1]!.month)) {
+          months.add(dates[i]);
+        }
+      }
+
+      months.sort((b, a) => a!.compareTo(b!));
+
+      final index = months.indexWhere((element) => element!.month == widget.selectedDate!.month && element.year == widget.selectedDate!.year);
+
+      _initialPage = index;
+      _horizontalScroll = PageController(initialPage: _initialPage);
+
+      double monthHeight = 6 * (width / 7) + 16 + 10 + 10 + 80; // 固定高度,6行的高度加上80额外空间
+
+      return Container(
+        height: monthHeight, // 使用固定的高度
+        padding: const EdgeInsets.fromLTRB(25, 10.0, 25, 20.0),
+        //只是PageView
+        child: Stack(
+          children: [
+            //主题
+            PageView.builder(
+              physics: const BouncingScrollPhysics(),
+              controller: _horizontalScroll,
+              reverse: true,
+              scrollDirection: Axis.horizontal,
+              itemCount: months.length,
+              itemBuilder: (context, index) {
+                DateTime? date = months[index];
+                List<DateTime?> daysOfMonth = [];
+                for (var item in dates) {
+                  if (date!.month == item!.month && date.year == item.year) {
+                    daysOfMonth.add(item);
+                  }
+                }
+
+                bool isLast = index == 0;
+
+                return Container(
+                  padding: EdgeInsets.only(bottom: isLast ? 0.0 : 10.0),
+                  child: month(daysOfMonth, width, widget.locale),
+                );
+              },
+            ),
+
+            //返回按钮
+            Positioned(
+              top: -11,
+              width: MediaQuery.of(context).size.width * 0.88,
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                children: [
+                  const MyAssetImage(
+                    Assets.baseLibCalendarLeftIcon,
+                    width: 44,
+                    height: 44,
+                  ).onTap(() {
+                    _horizontalScroll.nextPage(
+                      duration: const Duration(milliseconds: 300),
+                      curve: Curves.ease,
+                    );
+                  }),
+                  const MyAssetImage(
+                    Assets.baseLibCalendarRightIcon,
+                    width: 44,
+                    height: 44,
+                  ).onTap(() {
+                    _horizontalScroll.previousPage(
+                      duration: const Duration(milliseconds: 300),
+                      curve: Curves.ease,
+                    );
+                  }),
+                ],
+              ),
+            )
+          ],
+        ),
+      );
+    }
+  }
+
+  //顶部星期的文本数据
+  Widget daysOfWeek(double width, String? locale) {
+    List daysNames = [];
+    for (var day = 12; day <= 18; day++) {
+      daysNames.add(DateFormat.E(locale.toString()).format(DateTime.parse('1970-01-$day')));
+    }
+
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+      children: [
+        dayName(width / 7, daysNames[0]),
+        dayName(width / 7, daysNames[1]),
+        dayName(width / 7, daysNames[2]),
+        dayName(width / 7, daysNames[3]),
+        dayName(width / 7, daysNames[4]),
+        dayName(width / 7, daysNames[5]),
+        dayName(width / 7, daysNames[6]),
+      ],
+    );
+  }
+
+  //顶部星期的文本控件展示
+  Widget dayName(double width, String text) {
+    return Container(
+      width: width,
+      alignment: Alignment.center,
+      child: Text(
+        text,
+        style: const TextStyle(
+          fontSize: 13.0,
+          fontWeight: FontWeight.w500,
+        ),
+        overflow: TextOverflow.ellipsis,
+      ),
+    );
+  }
+
+  //当前月份,每一天的布局
+  Widget dateInCalendar(DateTime date, bool outOfRange, double width, bool event) {
+    bool isSelectedDate = date.toString().split(" ").first == widget.selectedDate.toString().split(" ").first;
+    return GestureDetector(
+      onTap: () => outOfRange ? null : widget.onDateChange(date),
+      child: Container(
+        width: width / 7,
+        height: width / 7,
+        decoration: BoxDecoration(
+          shape: BoxShape.circle,
+          color: isSelectedDate ? widget.dateSelectedBg : Colors.transparent,
+        ),
+        alignment: Alignment.center,
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            const SizedBox(
+              height: 5.0,
+            ),
+            Padding(
+              padding: const EdgeInsets.symmetric(vertical: 4.0),
+              child: Text(
+                DateFormat("dd").format(date),
+                style: TextStyle(
+                    color: outOfRange
+                        ? isSelectedDate
+                            ? widget.dateSelectedColor!.withOpacity(0.9)
+                            : widget.dateColor!.withOpacity(0.4)
+                        : isSelectedDate
+                            ? widget.dateSelectedColor
+                            : widget.dateColor,
+                    fontWeight: FontWeight.w500,
+                    fontSize: 13),
+              ),
+            ),
+            event
+                ? Icon(
+                    Icons.bookmark,
+                    size: 8,
+                    color: isSelectedDate ? widget.dateSelectedColor : widget.dateSelectedBg,
+                  )
+                : const SizedBox(height: 5.0),
+          ],
+        ),
+      ),
+    );
+  }
+
+  //单独一个月的Page布局
+  Widget month(List dates, double width, String? locale) {
+    DateTime first = dates.first;
+
+    // 获取这个月的第一天
+    DateTime firstDayOfMonth = DateTime(first.year, first.month, 1);
+
+    // 找到这个月的第一天是星期几
+    int firstWeekday = firstDayOfMonth.weekday;
+
+    // 计算需要的前导空格数量
+    int leadingDaysCount = (firstWeekday - DateTime.monday + 7) % 7;
+
+    // 只保留当前月份的日期
+    List<DateTime?> fullDates = List.from(dates);
+
+    // 在视图中添加用于填充的空日期(如果需要,这里就不填充上个月尾的日期了)
+    for (int i = 0; i < leadingDaysCount; i++) {
+      fullDates.insert(0, null); // 用null填充前导位置
+    }
+
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        Text(
+          DateFormat.yMMMM(Locale(locale!).toString()).format(first),
+          style: TextStyle(fontSize: 18.0, color: widget.dateColor, fontWeight: FontWeight.w500),
+        ),
+
+        // 周一到周天的星期文本
+        Padding(
+          padding: const EdgeInsets.only(top: 30.0),
+          child: daysOfWeek(width, widget.locale),
+        ),
+
+        // 底部的每月的每一天
+        Container(
+          padding: const EdgeInsets.only(top: 10.0),
+          height: (fullDates.length > 28)
+              ? (fullDates.length > 35 ? 6.2 * width / 7 : 5.2 * width / 7)
+              : 4 * width / 7,
+          width: MediaQuery.of(context).size.width - 2 * widget.padding!,
+          child: GridView.builder(
+            itemCount: fullDates.length,
+            physics: const NeverScrollableScrollPhysics(),
+            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 7),
+            itemBuilder: (context, index) {
+              DateTime? date = fullDates[index]; // 使用 DateTime? 类型以支持 null
+
+              // 如果 date 为 null,表示该位置为空,返回一个透明的容器
+              if (date == null) {
+                return Container(
+                  width: width / 7,
+                  height: width / 7,
+                  color: Colors.transparent, // 透明或其他样式
+                );
+              }
+
+              bool outOfRange = date.isBefore(startDate) || date.isAfter(endDate);
+
+              return dateInCalendar(
+                date,
+                outOfRange,
+                width,
+                _events!.contains(date.toString().split(" ").first) && !outOfRange,
+              );
+            },
+          ),
+        )
+      ],
+    );
+  }
+
+}

+ 32 - 10
packages/cs_widgets/lib/shatter/weekly_calendar/calendar_utils.dart

@@ -1,3 +1,5 @@
+import 'package:shared/utils/date_time_utils.dart';
+
 DateTime addDay(DateTime date, int days) {
   return date.add(Duration(days: days));
 }
@@ -6,11 +8,35 @@ DateTime subtractDay(DateTime date, int days) {
   return date.subtract(Duration(days: days));
 }
 
+//一周的第一天从哪里开始,Sun 还是 Mon
 DateTime firstDayOfWeek(DateTime date) {
-  if (date.weekday == DateTime.sunday) {
-    return date;
+  //返回星期天开始
+  // if (date.weekday == DateTime.sunday) {
+  //   return date;
+  // }
+  // return date.subtract(Duration(days: date.weekday));
+
+  // 从星期一开始
+  return date.subtract(Duration(days: date.weekday - 1));
+}
+
+//是否包含选中的日期
+bool hasSelectedDate(List<DateTime> list, DateTime selected) {
+  for (DateTime date in list) {
+    // 格式化日期并进行比较
+    if (DateTimeUtils.formatDate(date, format: 'yyyyMMdd') == DateTimeUtils.formatDate(selected, format: 'yyyyMMdd')) {
+      return true;
+    }
   }
-  return date.subtract(Duration(days: date.weekday));
+  return false;
+}
+
+// 检查日期是否小于今天
+bool isPastDate(DateTime now, DateTime date) {
+  // 获取当前日期的凌晨时间
+  DateTime todayMidnight = DateTime(now.year, now.month, now.day);
+  // 判断给定日期是否小于今天的凌晨时间
+  return date.isBefore(todayMidnight);
 }
 
 // ===================================  获取一周的数据  ↓  ===================================
@@ -35,9 +61,7 @@ List<DateTime> _subtractWeek(DateTime date, int subtract) {
 }
 
 List<DateTime> _getWeekDaysAt(DateTime date) {
-  return List.generate(7, (index) => index)
-      .map((index) => date.add(Duration(days: index)))
-      .toList();
+  return List.generate(7, (index) => index).map((index) => date.add(Duration(days: index))).toList();
 }
 
 // ===================================  获取二周的数据  ↓  ===================================
@@ -62,7 +86,5 @@ List<DateTime> _subtract2Week(DateTime date, int subtract) {
 }
 
 List<DateTime> _get2WeekDaysAt(DateTime date) {
-  return List.generate(14, (index) => index)
-      .map((index) => date.add(Duration(days: index)))
-      .toList();
-}
+  return List.generate(14, (index) => index).map((index) => date.add(Duration(days: index))).toList();
+}

+ 5 - 6
packages/cs_widgets/lib/shatter/weekly_calendar/day_cell.dart

@@ -1,6 +1,7 @@
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:shared/utils/date_time_utils.dart';
+import 'calendar_utils.dart';
 
 class DayCell extends StatelessWidget {
   const DayCell({
@@ -26,8 +27,8 @@ class DayCell extends StatelessWidget {
       width: 40,
       height: 40,
       decoration: BoxDecoration(
-        color: _isPastDate(display)
-            ? context.appColors.disEnableGray // 小于今天的日期背景颜色,禁用
+        color: isPastDate(current,display)
+            ? context.appColors.disEnableGray.withOpacity(0.6) // 小于今天的日期背景颜色,禁用
             : _isSelected(display)
                 ? _isToday(display)
                     ? context.appColors.btnBgDefault // 今天的日期背景颜色
@@ -79,8 +80,6 @@ class DayCell extends StatelessWidget {
     return DateTimeUtils.formatDate(date, format: 'yyyyMMdd') == DateTimeUtils.formatDate(current, format: 'yyyyMMdd');
   }
 
-  // 检查日期是否小于今天
-  bool _isPastDate(DateTime date) {
-    return date.isBefore(DateTime.now().subtract(const Duration(days: 1))); // 小于今天
-  }
+
+
 }

+ 5 - 9
packages/cs_widgets/lib/shatter/weekly_calendar/day_table_view.dart

@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
+import 'calendar_utils.dart';
 import 'day_cell.dart';
 
 /// 一周的数据为一行,展示两周共两行
@@ -24,9 +25,9 @@ class DayTableView extends StatelessWidget {
         Row(
           mainAxisAlignment: MainAxisAlignment.spaceAround,
           children: weekdays.sublist(0, 7).map(
-                (date) {
+            (date) {
               return GestureDetector(
-                onTap: _isPastDate(date) ? null : () => onSelect?.call(date),
+                onTap: isPastDate(currentDate, date) ? null : () => onSelect?.call(date),
                 child: SizedBox(
                   width: 40,
                   height: 40,
@@ -47,9 +48,9 @@ class DayTableView extends StatelessWidget {
         Row(
           mainAxisAlignment: MainAxisAlignment.spaceAround,
           children: weekdays.sublist(7, 14).map(
-                (date) {
+            (date) {
               return GestureDetector(
-                onTap: _isPastDate(date) ? null : () => onSelect?.call(date),
+                onTap: isPastDate(currentDate, date) ? null : () => onSelect?.call(date),
                 child: SizedBox(
                   width: 40,
                   height: 40,
@@ -66,9 +67,4 @@ class DayTableView extends StatelessWidget {
       ],
     );
   }
-
-  // 检查日期是否小于今天
-  bool _isPastDate(DateTime date) {
-    return date.isBefore(DateTime.now().subtract(const Duration(days: 1))); // 小于今天
-  }
 }

+ 203 - 151
packages/cs_widgets/lib/shatter/weekly_calendar/week_page.dart

@@ -1,151 +1,203 @@
-import 'package:flutter/material.dart';
-import 'calendar_utils.dart' show get2Weekdays, addDay, subtractDay, firstDayOfWeek;
-import 'day_table_view.dart';
-
-enum PageState {
-  previous,
-  current,
-  next,
-}
-
-/// 一周的Days的PageView页面
-class WeekPage extends StatefulWidget {
-  const WeekPage({
-    super.key,
-    required this.selectedDate,
-    required this.now,
-    required this.isAutoSelect,
-    this.onChangedSelectedDate,
-    this.onChangedPage,
-  });
-
-  final DateTime now;
-  final DateTime selectedDate;
-  final bool isAutoSelect;
-
-  final Function(DateTime)? onChangedSelectedDate; //选择日期变化的监听
-  final Function(DateTime date, PageState state)? onChangedPage; //切换日期Page的监听
-
-  final double height = 40 + 40 + 10;
-
-  @override
-  State<StatefulWidget> createState() => _WeekPageState();
-}
-
-class _WeekPageState extends State<WeekPage> {
-  double get height => widget.height;
-  final int initialPage = 999;
-  List<int> pageCounts = [0, 1, 2];
-  int currentPage = 1;
-  late DateTime _currentPageDate;
-  late DateTime _slectedDate;
-
-  DateTime get now => widget.now;
-
-  DateTime get selectedDate => widget.selectedDate;
-
-  @override
-  void initState() {
-    super.initState();
-    _currentPageDate = selectedDate;
-    _slectedDate = selectedDate;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Flexible(
-      child: AnimatedSize(
-        duration: const Duration(milliseconds: 250),
-        curve: Curves.easeInOut,
-        alignment: Alignment.topCenter,
-        child: SizedBox(
-          height: height,
-          child: pageViewBuilder(),
-        ),
-      ),
-    );
-  }
-
-  //PageView的方式展示不同的星期,每周每一个Page
-  Widget pageViewBuilder() {
-    final PageController pageController = PageController(initialPage: initialPage);
-    return PageView.builder(
-      itemBuilder: (context, index) {
-        final idx = _getIndex(index);
-        return dayTable(idx);
-      },
-      onPageChanged: onPageChanged,
-      controller: pageController,
-    );
-  }
-
-  //两周的数据
-  Widget dayTable(int index) {
-    int at = pageCounts[index] - 1;
-    final weekdays = get2Weekdays(now, at);
-    return DayTableView(
-      weekdays: weekdays,
-      onSelect: (date) {
-        setState(() {
-          _slectedDate = date;
-        });
-        //主动点击之后回调
-        widget.onChangedSelectedDate?.call(date);
-      },
-      selectedDate: _slectedDate,
-      currentDate: now,
-    );
-  }
-
-  //是否需要切换页面的时候自动选中
-  void changeSelectedDate(int value) {
-    if (_pageState(value) == PageState.next) {
-      if (widget.isAutoSelect) {
-        _slectedDate = addDay(selectedDate, 14);
-        widget.onChangedSelectedDate?.call(_slectedDate);
-      }
-    } else {
-      if (widget.isAutoSelect) {
-        _slectedDate = subtractDay(selectedDate, 14);
-        widget.onChangedSelectedDate?.call(_slectedDate);
-      }
-    }
-  }
-
-  //当切换页面的时候更新当前页面数据,返回当前页面第一条数据的日期
-  void updateCurrentPageDate(int value) {
-    final first = firstDayOfWeek(_currentPageDate);
-
-    if (_pageState(value) == PageState.next) {
-      _currentPageDate = addDay(first, 14);
-      widget.onChangedPage?.call(_currentPageDate, PageState.next);
-    } else {
-      _currentPageDate = subtractDay(first, 14);
-      widget.onChangedPage?.call(_currentPageDate, PageState.previous);
-    }
-  }
-
-  void onPageChanged(int value) {
-    changeSelectedDate(value);
-    updateCurrentPageDate(value);
-
-    int currentIndex = _getIndex(value);
-    int leftIndex = (currentIndex - 1 < 0) ? pageCounts.length - 1 : currentIndex - 1;
-    int rightIndex = (currentIndex + 1 > pageCounts.length - 1) ? 0 : currentIndex + 1;
-
-    pageCounts[leftIndex] = pageCounts[currentIndex] - 1;
-    pageCounts[rightIndex] = pageCounts[currentIndex] + 1;
-
-    currentPage = pageCounts[currentIndex];
-  }
-
-  int _getIndex(int idx) {
-    return (idx + 1) % pageCounts.length;
-  }
-
-  PageState _pageState(int idx) {
-    final prePage = currentPage;
-    final current = pageCounts[_getIndex(idx)];
-    return (prePage < current) ? PageState.next : PageState.previous;
-  }
-}
+// import 'package:flutter/material.dart';
+// import 'package:shared/utils/log_utils.dart';
+// import 'calendar_utils.dart' show get2Weekdays, addDay, subtractDay, firstDayOfWeek;
+// import 'day_table_view.dart';
+//
+// enum PageState {
+//   previous,
+//   current,
+//   next,
+// }
+//
+// /// 一周的Days的PageView页面
+// class WeekPage extends StatefulWidget {
+//   const WeekPage({
+//     super.key,
+//     required this.selectedDate,
+//     required this.now,
+//     required this.isAutoSelect,
+//     this.onChangedSelectedDate,
+//     this.onChangedPage,
+//   });
+//
+//   final DateTime now;
+//   final DateTime selectedDate;
+//   final bool isAutoSelect;
+//
+//   final Function(DateTime)? onChangedSelectedDate; //选择日期变化的监听
+//   final Function(DateTime date, PageState state)? onChangedPage; //切换日期Page的监听
+//
+//   final double height = 40 + 40 + 10;
+//
+//   @override
+//   State<StatefulWidget> createState() => _WeekPageState();
+// }
+//
+// class _WeekPageState extends State<WeekPage> {
+//   double get height => widget.height;
+//   final int initialPage = 999;
+//   List<int> pageCounts = [0, 1, 2];
+//   int currentPage = 1;
+//   late DateTime _currentPageDate;
+//   late DateTime _slectedDate;
+//
+//   DateTime get now => widget.now;
+//
+//   DateTime get selectedDate => widget.selectedDate;
+//
+//   late PageController _pageController;
+//
+//   @override
+//   void initState() {
+//     super.initState();
+//     _currentPageDate = selectedDate;
+//     _slectedDate = selectedDate;
+//     _pageController = PageController(initialPage: initialPage);
+//   }
+//
+//   @override
+//   void didUpdateWidget(covariant WeekPage oldWidget) {
+//     super.didUpdateWidget(oldWidget);
+//
+//     if (widget.selectedDate != oldWidget.selectedDate) {
+//       setState(() {
+//         _currentPageDate = widget.selectedDate;
+//         _slectedDate = widget.selectedDate;
+//       });
+//
+//       // 计算要滚动到的页面索引
+//       int targetPageIndex = _calculateTargetPageIndex(widget.selectedDate);
+//
+//       // 使用 WidgetsBinding 以确保在构建完成后再跳转页面
+//       WidgetsBinding.instance.addPostFrameCallback((_) {
+//         // 检查目标页面索引是否在有效范围内
+//         Log.d("targetPageIndex:$targetPageIndex pageCounts.length:${pageCounts.length}");
+//         if (targetPageIndex >= 0 && targetPageIndex < pageCounts.length) {
+//           _pageController.jumpToPage(targetPageIndex);
+//         } else {
+//           //超过了索引就刷新数据源?
+//           Log.d("超过了索引就刷新数据源");
+//         }
+//       });
+//     }
+//   }
+//
+//   // 计算要滚动到的页面索引
+//   int _calculateTargetPageIndex(DateTime date) {
+//     // 获取当前周的第一天
+//     DateTime currentFirstDayOfWeek = firstDayOfWeek(now);
+//     // 获取选中日期的周的第一天
+//     DateTime targetFirstDayOfWeek = firstDayOfWeek(date);
+//
+//     // 计算当前日期与目标日期之间的天数差
+//     int differenceInDays = targetFirstDayOfWeek.difference(currentFirstDayOfWeek).inDays + 1;
+//
+//     // 计算目标页面索引
+//     // 每页14天
+//     int targetPageIndex = (differenceInDays / 14).floor(); // 用floor确保向下取整
+//
+//     // 确保目标索引在有效范围内
+//     // targetPageIndex = (targetPageIndex + pageCounts.length) % pageCounts.length;
+//
+//     Log.d("differenceInDays:$differenceInDays targetPageIndex:$targetPageIndex");
+//
+//     return targetPageIndex;
+//   }
+//
+//   @override
+//   Widget build(BuildContext context) {
+//     return Flexible(
+//       child: AnimatedSize(
+//         duration: const Duration(milliseconds: 250),
+//         curve: Curves.easeInOut,
+//         alignment: Alignment.topCenter,
+//         child: SizedBox(
+//           height: height,
+//           child: pageViewBuilder(),
+//         ),
+//       ),
+//     );
+//   }
+//
+//   //PageView的方式展示不同的星期,每周每一个Page
+//   Widget pageViewBuilder() {
+//     return PageView.builder(
+//       itemBuilder: (context, index) {
+//         final idx = _getIndex(index);
+//         return dayTable(idx);
+//       },
+//       onPageChanged: onPageChanged,
+//       controller: _pageController,
+//     );
+//   }
+//
+//   //两周的数据
+//   Widget dayTable(int index) {
+//     int at = pageCounts[index] - 1;
+//     final weekdays = get2Weekdays(now, at);
+//     return DayTableView(
+//       weekdays: weekdays,
+//       onSelect: (date) {
+//         setState(() {
+//           _slectedDate = date;
+//         });
+//         //主动点击之后回调
+//         widget.onChangedSelectedDate?.call(date);
+//       },
+//       selectedDate: _slectedDate,
+//       currentDate: now,
+//     );
+//   }
+//
+//   //是否需要切换页面的时候自动选中
+//   void changeSelectedDate(int value) {
+//     if (_pageState(value) == PageState.next) {
+//       if (widget.isAutoSelect) {
+//         _slectedDate = addDay(selectedDate, 14);
+//         widget.onChangedSelectedDate?.call(_slectedDate);
+//       }
+//     } else {
+//       if (widget.isAutoSelect) {
+//         _slectedDate = subtractDay(selectedDate, 14);
+//         widget.onChangedSelectedDate?.call(_slectedDate);
+//       }
+//     }
+//   }
+//
+//   //当切换页面的时候更新当前页面数据,返回当前页面第一条数据的日期
+//   void updateCurrentPageDate(int value) {
+//     final first = firstDayOfWeek(_currentPageDate);
+//
+//     if (_pageState(value) == PageState.next) {
+//       _currentPageDate = addDay(first, 14);
+//       widget.onChangedPage?.call(_currentPageDate, PageState.next);
+//     } else {
+//       _currentPageDate = subtractDay(first, 14);
+//       widget.onChangedPage?.call(_currentPageDate, PageState.previous);
+//     }
+//   }
+//
+//   void onPageChanged(int value) {
+//     changeSelectedDate(value);
+//     updateCurrentPageDate(value);
+//
+//     int currentIndex = _getIndex(value);
+//     int leftIndex = (currentIndex - 1 < 0) ? pageCounts.length - 1 : currentIndex - 1;
+//     int rightIndex = (currentIndex + 1 > pageCounts.length - 1) ? 0 : currentIndex + 1;
+//
+//     pageCounts[leftIndex] = pageCounts[currentIndex] - 1;
+//     pageCounts[rightIndex] = pageCounts[currentIndex] + 1;
+//
+//     currentPage = pageCounts[currentIndex];
+//   }
+//
+//   int _getIndex(int idx) {
+//     return (idx + 1) % pageCounts.length;
+//   }
+//
+//   PageState _pageState(int idx) {
+//     final prePage = currentPage;
+//     final current = pageCounts[_getIndex(idx)];
+//     return (prePage < current) ? PageState.next : PageState.previous;
+//   }
+// }

+ 38 - 28
packages/cs_widgets/lib/shatter/weekly_calendar/weekly_calendar.dart

@@ -1,25 +1,20 @@
 import 'package:flutter/material.dart';
 import 'package:intl/date_symbol_data_local.dart';
-import 'package:widgets/shatter/weekly_calendar/week_page.dart';
-
-import 'calendar_utils.dart' show getWeekdays;
+import 'package:shared/utils/log_utils.dart';
+import 'calendar_utils.dart';
 import 'day_of_week_view.dart';
+import 'day_table_view.dart';
 
 /// 总入口,整合顶部的Week控件与底部的Days的PageView控件
 class WeeklyCalendar extends StatefulWidget {
   const WeeklyCalendar({
     super.key,
-    this.isAutoSelect = false,
     this.onChangedSelectedDate,
-    this.onChangedPage,
     this.selectedDate,
   });
 
-
-  final DateTime? selectedDate;
-  final bool isAutoSelect;
-  final Function(DateTime)? onChangedSelectedDate;
-  final Function(DateTime date, PageState state)? onChangedPage;
+  final DateTime? selectedDate; //当前选中的日期
+  final Function(DateTime)? onChangedSelectedDate; //选择日期的回调
 
   @override
   State<StatefulWidget> createState() => _WeeklyCalendarState();
@@ -27,15 +22,35 @@ class WeeklyCalendar extends StatefulWidget {
 
 class _WeeklyCalendarState extends State<WeeklyCalendar> {
   final DateTime now = DateTime.now();
-  late DateTime selectedDate;
-  DateTime currentPageDate = DateTime.now();
-
+  DateTime? selectedDate;
+  late List<DateTime> currentDateList;
 
   @override
   void initState() {
-    initializeDateFormatting("en");  //日期国际化指定
+    initializeDateFormatting("en"); //日期国际化指定
     super.initState();
-    selectedDate = widget.selectedDate ?? DateTime.now();
+
+    currentDateList = get2Weekdays(now, 0); //双周的数据
+    selectedDate = widget.selectedDate ?? now; //默认选中的数据
+  }
+
+  @override
+  void didUpdateWidget(covariant WeeklyCalendar oldWidget) {
+    super.didUpdateWidget(oldWidget);
+    if (widget.selectedDate != oldWidget.selectedDate) {
+      //查看当前页面Date数据是否包含选中的 selectedDate
+      bool hasSelected = hasSelectedDate(currentDateList, widget.selectedDate ?? now);
+
+      setState(() {
+        selectedDate = widget.selectedDate;
+
+        if (!hasSelected) {
+          //如果不包含,需要更换数据源
+          Log.d("选中日期不在当前页面,需要更换数据源");
+          currentDateList = get2Weekdays(widget.selectedDate ?? now, 0);
+        }
+      });
+    }
   }
 
   @override
@@ -48,24 +63,19 @@ class _WeeklyCalendarState extends State<WeeklyCalendar> {
 
         const SizedBox(height: 12),
 
-        //底部是每个星期的Days的PageView布局
-        WeekPage(
-          selectedDate: selectedDate,  //默认选中的日期,如果没有填写默认是今天
-          now: now,                    //今天的日期
-          isAutoSelect: widget.isAutoSelect,  //翻页是否自动选中
-          onChangedPage: (date, state) {
-            setState(() {
-              currentPageDate = date;
-            });
-            widget.onChangedPage?.call(date, state);
-          },
-          onChangedSelectedDate: (date) {
+        //底部是当前二周的数据
+        DayTableView(
+          weekdays: currentDateList,
+          onSelect: (date) {
             setState(() {
               selectedDate = date;
             });
+            //主动点击之后回调
             widget.onChangedSelectedDate?.call(date);
           },
-        ),
+          selectedDate: selectedDate ?? now,
+          currentDate: now,
+        )
       ],
     );
   }