Pārlūkot izejas kodu

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

“shanwenxin” 1 nedēļu atpakaļ
vecāks
revīzija
f1c319555f
100 mainītis faili ar 5625 papildinājumiem un 281 dzēšanām
  1. 0 6
      app/lib/main.dart
  2. 6 0
      app/lib/router/component/app_component_service_impl.dart
  3. 1 1
      melos.yaml
  4. 99 0
      packages/cpt_community/lib/components/custom_tabs.dart
  5. 29 0
      packages/cpt_community/lib/components/custom_tabs_state.dart
  6. 55 0
      packages/cpt_community/lib/components/custom_tabs_vm.dart
  7. 25 0
      packages/cpt_community/lib/components/custom_tabs_vm.g.dart
  8. 84 0
      packages/cpt_community/lib/components/newfeed_card_header.dart
  9. 69 0
      packages/cpt_community/lib/components/newsfeed_card_content.dart
  10. 87 0
      packages/cpt_community/lib/components/newsfeed_card_footer.dart
  11. 124 0
      packages/cpt_community/lib/modules/community/community_page.dart
  12. 104 0
      packages/cpt_community/lib/modules/community/community_page1.dart
  13. 37 0
      packages/cpt_community/lib/modules/community/community_state.dart
  14. 50 0
      packages/cpt_community/lib/modules/community/community_vm.dart
  15. 25 0
      packages/cpt_community/lib/modules/community/community_vm.g.dart
  16. 0 34
      packages/cpt_community/lib/modules/community/page/community_page.dart
  17. 34 0
      packages/cpt_community/lib/modules/garagesale/garagesale_page.dart
  18. 0 0
      packages/cpt_community/lib/modules/garagesale/garagesale_repository.dart
  19. 0 0
      packages/cpt_community/lib/modules/garagesale/garagesale_state.dart
  20. 14 14
      packages/cpt_community/lib/modules/community/vm/community_view_model.dart
  21. 25 0
      packages/cpt_community/lib/modules/garagesale/garagesale_vm.g.dart
  22. 177 0
      packages/cpt_community/lib/modules/newsfeed/newsfeed_page.dart
  23. 71 0
      packages/cpt_community/lib/modules/newsfeed/newsfeed_repository.dart
  24. 12 11
      packages/cpt_community/lib/modules/community/vm/community_view_model.g.dart
  25. 63 0
      packages/cpt_community/lib/modules/newsfeed/newsfeed_state.dart
  26. 148 0
      packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.dart
  27. 25 0
      packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.g.dart
  28. 1 1
      packages/cpt_community/lib/router/component/community_component_service.dart
  29. 20 3
      packages/cpt_community/lib/router/page/community_page_router.dart
  30. 41 1
      packages/cpt_community/lib/router/page/community_page_router.gr.dart
  31. 280 0
      packages/cpt_main/lib/modules/demo_page.dart
  32. 130 0
      packages/cpt_main/lib/modules/feedback/feedback_page.dart
  33. 56 0
      packages/cpt_main/lib/modules/feedback/history/feedback_history.dart
  34. 31 0
      packages/cpt_main/lib/modules/feedback/history/feedback_history_state.dart
  35. 131 0
      packages/cpt_main/lib/modules/feedback/history/feedback_history_view_model.dart
  36. 27 0
      packages/cpt_main/lib/modules/feedback/history/feedback_history_view_model.g.dart
  37. 75 0
      packages/cpt_main/lib/modules/feedback/item_feedback.dart
  38. 0 77
      packages/cpt_main/lib/modules/feedback/page/feedback_page.dart
  39. 56 0
      packages/cpt_main/lib/modules/feedback/progress/feedback_progress.dart
  40. 31 0
      packages/cpt_main/lib/modules/feedback/progress/feedback_progress_state.dart
  41. 130 0
      packages/cpt_main/lib/modules/feedback/progress/feedback_progress_view_model.dart
  42. 28 0
      packages/cpt_main/lib/modules/feedback/progress/feedback_progress_view_model.g.dart
  43. 18 0
      packages/cpt_main/lib/modules/feedback/send/feedback_send.dart
  44. 58 0
      packages/cpt_main/lib/modules/feedback/send/feedback_send_large.dart
  45. 55 0
      packages/cpt_main/lib/modules/feedback/send/feedback_send_small.dart
  46. 101 84
      packages/cpt_main/lib/modules/home/home_page.dart
  47. 9 7
      packages/cpt_main/lib/modules/home/home_view_model.dart
  48. 1 1
      packages/cpt_main/lib/modules/home/home_view_model.g.dart
  49. 1 1
      packages/cpt_main/lib/modules/home/item_home_category.dart
  50. 1 1
      packages/cpt_main/lib/modules/home/item_home_last_news.dart
  51. 1 1
      packages/cpt_main/lib/modules/home/item_home_last_trans.dart
  52. 1 1
      packages/cpt_main/lib/modules/home/item_home_manage_guide.dart
  53. 1 1
      packages/cpt_main/lib/modules/home/item_home_property_news.dart
  54. 55 0
      packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_screen.dart
  55. 31 0
      packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_state.dart
  56. 130 0
      packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_view_model.dart
  57. 27 0
      packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_view_model.g.dart
  58. 54 0
      packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_screen.dart
  59. 31 0
      packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_state.dart
  60. 130 0
      packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_view_model.dart
  61. 28 0
      packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_view_model.g.dart
  62. 152 0
      packages/cpt_main/lib/modules/home/latest_news/latest_news_page.dart
  63. 54 0
      packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_screen.dart
  64. 31 0
      packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_state.dart
  65. 131 0
      packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_view_model.dart
  66. 28 0
      packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_view_model.g.dart
  67. 54 0
      packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_screen.dart
  68. 31 0
      packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_state.dart
  69. 130 0
      packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_view_model.dart
  70. 28 0
      packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_view_model.g.dart
  71. 56 0
      packages/cpt_main/lib/modules/home/management_guides/item_management_guide.dart
  72. 84 0
      packages/cpt_main/lib/modules/home/management_guides/management_guides_page.dart
  73. 32 0
      packages/cpt_main/lib/modules/home/management_guides/management_guides_state.dart
  74. 144 0
      packages/cpt_main/lib/modules/home/management_guides/management_guides_view_model.dart
  75. 28 0
      packages/cpt_main/lib/modules/home/management_guides/management_guides_view_model.g.dart
  76. 4 0
      packages/cpt_main/lib/modules/home/management_guides/test_guide_bean.dart
  77. 72 0
      packages/cpt_main/lib/modules/home/property_news/home_property_news_page.dart
  78. 31 0
      packages/cpt_main/lib/modules/home/property_news/home_property_news_state.dart
  79. 130 0
      packages/cpt_main/lib/modules/home/property_news/home_property_news_view_model.dart
  80. 28 0
      packages/cpt_main/lib/modules/home/property_news/home_property_news_view_model.g.dart
  81. 68 0
      packages/cpt_main/lib/modules/home/property_news/item_list_news.dart
  82. 1 1
      packages/cpt_main/lib/modules/main/main_state.dart
  83. 210 28
      packages/cpt_main/lib/modules/me/me_page.dart
  84. 46 0
      packages/cpt_main/lib/modules/me/me_view_model.dart
  85. 25 0
      packages/cpt_main/lib/modules/me/me_view_model.g.dart
  86. 99 0
      packages/cpt_main/lib/modules/notification/item_notification.dart
  87. 26 0
      packages/cpt_main/lib/modules/notification/item_notification_header.dart
  88. 6 0
      packages/cpt_main/lib/modules/notification/notification_group_data.dart
  89. 78 7
      packages/cpt_main/lib/modules/notification/notification_page.dart
  90. 31 0
      packages/cpt_main/lib/modules/notification/notification_state.dart
  91. 160 0
      packages/cpt_main/lib/modules/notification/notification_view_model.dart
  92. 27 0
      packages/cpt_main/lib/modules/notification/notification_view_model.g.dart
  93. 56 0
      packages/cpt_main/lib/modules/visitor/active/visitor_active.dart
  94. 31 0
      packages/cpt_main/lib/modules/visitor/active/visitor_active_state.dart
  95. 133 0
      packages/cpt_main/lib/modules/visitor/active/visitor_active_view_model.dart
  96. 27 0
      packages/cpt_main/lib/modules/visitor/active/visitor_active_view_model.g.dart
  97. 55 0
      packages/cpt_main/lib/modules/visitor/history/visitor_history.dart
  98. 31 0
      packages/cpt_main/lib/modules/visitor/history/visitor_history_state.dart
  99. 133 0
      packages/cpt_main/lib/modules/visitor/history/visitor_history_view_model.dart
  100. 0 0
      packages/cpt_main/lib/modules/visitor/history/visitor_history_view_model.g.dart

+ 0 - 6
app/lib/main.dart

@@ -74,9 +74,6 @@ class MyApp extends HookConsumerWidget {
           noMoreText: 'No more',
           failedText: 'Failed',
           messageText: 'Last updated at %T',
-          textStyle: TextStyle(color: Color(0XFFAECAE5), fontSize: 14),
-          messageStyle: TextStyle(color: Color(0XFFAECAE5), fontSize: 12),
-          iconTheme: IconThemeData(color: Color(0XFFAECAE5)),
           backgroundColor: Colors.transparent,
         );
     EasyRefresh.defaultFooterBuilder = () => const ClassicFooter(
@@ -90,9 +87,6 @@ class MyApp extends HookConsumerWidget {
           showMessage: false,
           triggerOffset: 50,
           iconDimension: 22,
-          textStyle: TextStyle(color: Color(0XFFAECAE5), fontSize: 14),
-          messageStyle: TextStyle(color: Color(0XFFAECAE5), fontSize: 12),
-          iconTheme: IconThemeData(color: Color(0XFFAECAE5)),
           backgroundColor: Colors.transparent,
         );
 

+ 6 - 0
app/lib/router/component/app_component_service_impl.dart

@@ -3,6 +3,7 @@
  */
 import 'package:app/router/page/app_page_router.dart';
 import 'package:auto_route/src/router/controller/routing_controller.dart';
+import 'package:plugin_basic/provider/app_config/app_config_service.dart';
 import 'package:router/componentRouter/app_service.dart';
 
 class AppComponentServiceImpl extends AppService {
@@ -10,4 +11,9 @@ class AppComponentServiceImpl extends AppService {
   RootStackRouter getAppRouter() {
     return appRouter;
   }
+
+  @override
+  bool isDeviceFullScreen() {
+    return AppConfigService.getState().isFullScreenDevice;
+  }
 }

+ 1 - 1
melos.yaml

@@ -48,7 +48,7 @@ scripts:
     description: Run `dart run build_runner build` in auth module
 
   build_runner_community:
-    run: cd "$MELOS_ROOT_PATH/packages/cpt_community" && dart run build_runner build --delete-conflicting-outputs
+    run: cd "$MELOS_ROOT_PATH/packages/cpt_community" && flutter pub run build_runner build --delete-conflicting-outputs
     description: Run `dart run build_runner build` in community module
 
   build_runner_facility:

+ 99 - 0
packages/cpt_community/lib/components/custom_tabs.dart

@@ -0,0 +1,99 @@
+import 'package:cpt_community/components/custom_tabs_state.dart';
+import 'package:cpt_community/components/custom_tabs_state.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/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/my_appbar.dart';
+
+import 'custom_tabs_state.dart';
+import 'custom_tabs_vm.dart';
+
+
+class CustomTabs extends HookConsumerWidget {
+  List tabsList;
+  int activeIndex = 0;
+  Widget? Function(BuildContext)? tabItemBuilder;
+  VoidCallback? onClickAction;
+  CustomTabs({Key? key, required this.tabsList, required this.activeIndex, this.onClickAction, this.tabItemBuilder}) :
+        super(key: key);
+
+  Widget _buildTabItem(BuildContext context, WidgetRef ref, vm, item, index) {
+
+    // 监听 activeIndex 的变化
+    final activeIndex = ref.watch(customTabsVmProvider.select((state) => state.activeIndex));
+
+    return Container(
+        width: MediaQuery.of(context).size.width / vm.state.tabsList.length - 30,
+        height: 43,
+        padding: const EdgeInsets.only(top: 10, bottom: 10, left: 10, right: 10),
+        decoration: index==activeIndex? BoxDecoration(
+          color: index==activeIndex? context.appColors.btnBgDefault: ColorUtils.string2Color("#F2F3F6"),
+          borderRadius: BorderRadius.circular(20),
+          boxShadow: [
+            BoxShadow(
+              color: Colors.grey.withOpacity(0.5),
+              spreadRadius: 1,
+              blurRadius: 5,
+              offset: const Offset(0, 2), // changes position of shadow
+            ),
+          ],
+        ): null,
+        child: Row(
+          children: [
+            Expanded(
+              child: Container(
+                alignment: Alignment.center,
+                child: MyTextView(
+                  item['title'],
+                  fontSize: 16,
+                  textAlign: TextAlign.center,
+                  isFontMedium: true,
+                  textColor: index == activeIndex ? Colors.white :ColorUtils.string2Color("#000000"),
+                ),
+              ),
+            ),
+          ],
+        ),
+    ).onTap((){
+      vm.handlerClickTab(index, item);
+    });
+  }
+
+  List<Widget> _buildTabs(BuildContext context, WidgetRef ref, vm){
+    tabsList = vm.state.tabsList;
+
+    int tabsLength = tabsList.length;
+    return List.generate(tabsLength, (index) {
+      return _buildTabItem(context, ref, vm, tabsList[index], index);
+    });
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(customTabsVmProvider.notifier);
+    // 初始化状态,只在第一次构建时执行
+    if (vm.state.tabsList!.isEmpty) {
+      vm.initPropData(tabsList, activeIndex, tabItemBuilder, onClickAction);
+    }
+
+    return SingleChildScrollView(
+      scrollDirection: Axis.horizontal,
+      physics: const BouncingScrollPhysics(),
+      clipBehavior: Clip.none,
+      child: Row(
+        mainAxisSize: MainAxisSize.max,
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: _buildTabs(context, ref, vm),
+      ).constrained(
+        maxWidth:  MediaQuery.of(context).size.width
+      ),
+    );
+  }
+}

+ 29 - 0
packages/cpt_community/lib/components/custom_tabs_state.dart

@@ -0,0 +1,29 @@
+import 'package:flutter/cupertino.dart';
+
+class CustomTabsState {
+  List? tabsList;
+  int? activeIndex;
+  Widget? Function(BuildContext)? tabItemBuilder;
+  VoidCallback? onClickAction;
+
+  CustomTabsState({
+    this.tabsList,
+    this.activeIndex,
+    this.tabItemBuilder,
+    this.onClickAction,
+  });
+
+  CustomTabsState copyWith({
+    List? tabsList,
+    int? activeIndex,
+    Widget? Function(BuildContext)? tabItemBuilder,
+    VoidCallback? onClickAction,
+  }) {
+    return CustomTabsState(
+      tabsList: tabsList ?? this.tabsList,
+      activeIndex: activeIndex ?? this.activeIndex,
+      tabItemBuilder: tabItemBuilder ?? this.tabItemBuilder,
+      onClickAction: onClickAction ?? this.onClickAction,
+    );
+  }
+}

+ 55 - 0
packages/cpt_community/lib/components/custom_tabs_vm.dart

@@ -0,0 +1,55 @@
+
+import 'package:cpt_community/components/custom_tabs_state.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+
+part 'custom_tabs_vm.g.dart';
+
+@riverpod
+class CustomTabsVm extends _$CustomTabsVm {
+
+  CustomTabsState initState(List tabsList, int activeIndex, tabItemBuilder, onClickAction) {
+    CustomTabsState state = CustomTabsState(
+        tabsList: tabsList ?? [],
+        activeIndex: activeIndex ?? 0,
+        tabItemBuilder:tabItemBuilder,
+        onClickAction: onClickAction
+    );
+
+    return state;
+  }
+
+  @override
+  CustomTabsState build(){
+    CustomTabsState state = initState([], 0, null, null);
+    return state;
+  }
+
+
+  Future<void> initPropData(tabsList, activeIndex,tabItemBuilder, onClickAction) async {
+    CustomTabsState newState = state.copyWith(
+        tabsList: tabsList,
+        activeIndex: activeIndex,
+        tabItemBuilder: tabItemBuilder,
+        onClickAction: onClickAction
+    );
+    state = newState;
+  }
+
+  // 点击tab
+  void handlerClickTab(int index, item){
+    CustomTabsState newState = state.copyWith(
+        activeIndex: index
+    );
+    state = newState;
+
+    print("切换后新的 sate, ${state.activeIndex}");
+
+    // ref.invalidate(customTabsVmProvider);
+  }
+
+}

+ 25 - 0
packages/cpt_community/lib/components/custom_tabs_vm.g.dart

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

+ 84 - 0
packages/cpt_community/lib/components/newfeed_card_header.dart

@@ -0,0 +1,84 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+// 'id':1,
+// 'avator': Assets.communityCamera,
+// 'title': 'William Jefferson',
+// 'isFollow': false,
+// 'content': 'She said YES and our lives changed.Thank you all for coming to my propose today.We hope everyone can ……[More]',
+// 'imageUrls': ['https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg'],
+// 'time': 'June 17,2016 at 7:23 p.m.',
+// 'likeno': 12
+
+class NewsFeedCardHeader extends StatelessWidget {
+  final String title;
+  final String avator;
+  final String time;
+  final VoidCallback? onTap;
+
+  const NewsFeedCardHeader({
+    Key? key,
+    required this.title,
+    required this.avator,
+    required this.time,
+    this.onTap,
+  }) : super(key: key);
+
+
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.symmetric(horizontal: 16),
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyLoadImage(
+            avator,
+            width: 45,
+            height: 45,
+            isCircle: true,
+            fit: BoxFit.cover,
+          ).onTap(() {
+            // 点击头像
+            onTap?.call();
+          }),
+          Expanded(
+            child: Container(
+              padding: const EdgeInsets.only(left:15, right: 40),
+              // color: Colors.red,
+              child: Column(
+                mainAxisAlignment: MainAxisAlignment.start,
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  MyTextView(
+                    title,
+                    isFontMedium: true,
+                    fontSize: 18,
+                    textColor: ColorUtils.string2Color('#000000'),
+                    maxLines: 1,
+                    isTextEllipsis: true,
+                  ),
+                  MyTextView(
+                    time,
+                    isFontRegular: true,
+                    fontSize: 13,
+                    marginTop: 8,
+                    textColor: ColorUtils.string2Color('#767676'),
+                    maxLines: 1,
+                    isTextEllipsis: true,
+                  ),
+                ],
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 69 - 0
packages/cpt_community/lib/components/newsfeed_card_content.dart

@@ -0,0 +1,69 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/my_text_view.dart';
+
+// 'id':1,
+// 'avator': Assets.communityCamera,
+// 'title': 'William Jefferson',
+// 'isFollow': false,
+// 'content': 'She said YES and our lives changed.Thank you all for coming to my propose today.We hope everyone can ……[More]',
+// 'imageUrls': ['https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg'],
+// 'time': 'June 17,2016 at 7:23 p.m.',
+// 'likeno': 12
+
+class NewsFeedCardContent extends StatelessWidget {
+  const NewsFeedCardContent({
+    Key? key,
+    required this.content,
+    this.imageUrls,
+  }) : super(key: key);
+
+  final String content;
+  final List? imageUrls;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.symmetric(horizontal: 16),
+      child: Column(
+        children: [
+          Expanded(
+            child: Container(
+              // color: Colors.red,
+              child: MyTextView(
+                content,
+                textColor: ColorUtils.string2Color('#000000'),
+                fontSize: 15,
+                maxLines: 3,
+                isTextEllipsis: true,
+              ),
+            ),
+          ),
+          const SizedBox(height: 12),
+          // 图片
+          if (imageUrls != null && imageUrls!.isNotEmpty)
+             Container(
+               width: double.infinity,
+               height: 87,
+               child: Row(
+                 mainAxisAlignment: MainAxisAlignment.center,
+                 children: [
+                   for (var item in imageUrls!)
+                     Expanded(
+                       child: Container(
+                         // width: 87,
+                         // height: 87,
+                         // margin: const EdgeInsets.only(right: 30),
+                         margin: const EdgeInsets.only(left: 15,right: 18),
+                         color: ColorUtils.string2Color("#F2F3F6"),
+                       ),
+                     )
+                 ],
+               ),
+             )
+        ]
+      ),
+    );
+  }
+}

+ 87 - 0
packages/cpt_community/lib/components/newsfeed_card_footer.dart

@@ -0,0 +1,87 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+// 'id':1,
+// 'avator': Assets.communityCamera,
+// 'title': 'William Jefferson',
+// 'isFollow': false,
+// 'content': 'She said YES and our lives changed.Thank you all for coming to my propose today.We hope everyone can ……[More]',
+// 'imageUrls': ['https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg'],
+// 'time': 'June 17,2016 at 7:23 p.m.',
+// 'likeno': 12
+
+class NewsFeedCardFooter extends StatelessWidget {
+  final bool isLike;
+  final VoidCallback? onLike;
+  final VoidCallback? onComment;
+  final VoidCallback? onShare;
+
+  const NewsFeedCardFooter({
+    Key? key,
+    required this.isLike,
+    this.onLike,
+    this.onComment,
+    this.onShare
+  })
+  : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      height: 40,
+      width: double.infinity,
+      padding: const EdgeInsets.symmetric(horizontal: 16),
+      // color: Colors.red,
+      child: Expanded(
+        child:  Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Row(
+              children: [
+                const MyAssetImage(Assets.communityLike, width: 16,height: 16,),
+                MyTextView(
+                  'Like',
+                  textColor: ColorUtils.string2Color('#767676'),
+                  fontSize: 14,
+                  isFontRegular: true,
+                  textAlign: TextAlign.left,
+                  marginLeft: 8,
+                ),
+              ],
+            ),
+            Row(
+              children: [
+                const MyAssetImage(Assets.communityComments, width: 16,height: 16,),
+                MyTextView(
+                  'Comments',
+                  textColor: ColorUtils.string2Color('#767676'),
+                  fontSize: 14,
+                  isFontRegular: true,
+                  textAlign: TextAlign.left,
+                  marginLeft: 8,
+                ),
+              ],
+            ),
+            Row(
+              children: [
+                const MyAssetImage(Assets.communityShare, width: 16,height: 16,),
+                MyTextView(
+                  'Share',
+                  textColor: ColorUtils.string2Color('#767676'),
+                  fontSize: 14,
+                  isFontRegular: true,
+                  textAlign: TextAlign.left,
+                  marginLeft: 8,
+                ),
+              ],
+            ),
+          ]
+        ),
+      )
+    );
+  }
+}

+ 124 - 0
packages/cpt_community/lib/modules/community/community_page.dart

@@ -0,0 +1,124 @@
+
+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/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../router/page/community_page_router.dart';
+import 'community_vm.dart';
+
+@RoutePage()
+class CommunityPage extends HookConsumerWidget {
+    const CommunityPage({Key? key}) : super(key: key);
+
+    //启动当前页面
+    static void startInstance({BuildContext? context}) {
+      if (context != null) {
+        context.router.push(const CommunityPageRoute());
+      } else {
+        appRouter.push(const CommunityPageRoute());
+      }
+    }
+
+
+     Widget _buildTopSection(BuildContext context, WidgetRef ref, _vm, tabsRouter) {
+        final topSectionsData = _vm.topSectionsData;
+        final currentTabIdx = tabsRouter.activeIndex;
+        // 监听 curIdx 的变化
+        // final curIdx = ref.watch(communityVmProvider.select((value) => value.curIdx));
+        return Container(
+          color: Colors.white,
+          padding: const EdgeInsets.only(top: 30, bottom: 30),
+          child: Center(
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: List.generate(topSectionsData.length, (index) {
+                final item = topSectionsData[index];
+                return Flexible(
+                  flex: 1,
+                  child: Column(
+                    children: [
+                      Container(
+                        width: MediaQuery.of(context).size.width / topSectionsData.length - 36,
+                        height: 70,
+                        decoration: BoxDecoration(
+                          // color: currentTabIdx == index ? ColorUtils.string2Color('#E6F2FF') : Colors.white,
+                          shape: BoxShape.circle, // 设置为圆形
+                          boxShadow: tabsRouter.activeIndex == index ? [
+                            BoxShadow(
+                              color: context.appColors.tabLightBlueShadow, // 设置阴影颜色
+                              blurRadius: 5, // 设置模糊半径
+                              spreadRadius: 0.05, // 控制阴影扩散
+                              offset: const Offset(0, 4), // 设置阴影偏移量
+                            ),
+                          ] : [],// 未选中时无阴影,
+                        ),
+                        child: MyAssetImage(
+                          item['icon'],
+                          width: MediaQuery.of(context).size.width / topSectionsData.length - 36,
+                          height: 70,
+                        ).onTap(() {
+                            tabsRouter.setActiveIndex(index);
+                          },
+                          type: ClickType.throttle,
+                        ),
+                      ),
+                      SizedBox.fromSize(size: const Size(0, 9)),
+                      Text(
+                        item['title'],
+                        maxLines: 1, // 设置最大行数为2
+                        overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
+                        style: TextStyle(
+                            fontSize: 15.0,
+                            color: currentTabIdx == index ? ColorUtils.string2Color('#4161D0'):Colors.black,
+                            fontWeight: FontWeight.w500
+                        ), // 设置字体大小
+                      ),
+                    ],
+                  ),
+                ).marginOnly(left: 18, right: 18, top: 10, bottom: 10);
+              }),
+            ),
+          ),
+        );
+    }
+
+    @override
+    Widget build(BuildContext context, WidgetRef ref) {
+        final vm = ref.watch(communityVmProvider.notifier);
+        return Scaffold(
+            appBar: MyAppBar.appBar(
+              context,
+              "Community",
+              backgroundColor: context.appColors.whiteBG,
+            ),
+            backgroundColor: context.appColors.backgroundDefault,
+          body: AutoTabsRouter.pageView(
+            routes: const [
+              NewsfeedPageRoute(),
+              GaragesalePageRoute(),
+            ],
+            builder: (context, child, pageController) {
+              final tabsRouter = AutoTabsRouter.of(context);
+              return Column(
+                children: [
+                  _buildTopSection(context, ref, vm, tabsRouter),
+                  Expanded(
+                    child: child,
+                  ),
+                ],
+              );
+            },
+          ),
+        );
+    }
+}

+ 104 - 0
packages/cpt_community/lib/modules/community/community_page1.dart

@@ -0,0 +1,104 @@
+
+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/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+
+import '../../router/page/community_page_router.dart';
+import 'community_vm.dart';
+
+@RoutePage()
+class CommunityPage extends HookConsumerWidget {
+  const CommunityPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const CommunityPageRoute());
+    } else {
+      appRouter.push(const CommunityPageRoute());
+    }
+  }
+
+
+  Widget _buildTopSection(BuildContext context, WidgetRef ref, _vm) {
+    final topSectionsData = _vm.topSectionsData;
+    // 监听 curIdx 的变化
+    final curIdx = ref.watch(communityVmProvider.select((value) => value.curIdx));
+    return Container(
+      color: Colors.white,
+      padding: const EdgeInsets.only(top: 30, bottom: 30),
+      child: Center(
+        child: Row(
+          mainAxisAlignment: MainAxisAlignment.center,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: List.generate(topSectionsData.length, (index) {
+            final item = topSectionsData[index];
+            return Flexible(
+              flex: 1,
+              child: Column(
+                children: [
+                  MyAssetImage(
+                    item['icon'],
+                    width: MediaQuery.of(context).size.width / topSectionsData.length - 36,
+                    height: 70,
+                  ).onTap(
+                        () {
+                      _vm.switchPage(index, context);
+                    },
+                    type: ClickType.throttle,
+                  ),
+                  SizedBox.fromSize(size: const Size(0, 9)),
+                  Text(
+                    item['title'],
+                    maxLines: 1, // 设置最大行数为2
+                    overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
+                    style: TextStyle(
+                        fontSize: 15.0,
+                        color: curIdx == index ? ColorUtils.string2Color('#4161D0'):Colors.black,
+                        fontWeight: FontWeight.w500
+                    ), // 设置字体大小
+                  ),
+                ],
+              ),
+            ).marginOnly(left: 18, right: 18, top: 10, bottom: 10);
+          }),
+        ),
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.watch(communityVmProvider.notifier);
+    return Scaffold(
+        appBar: MyAppBar.appBar(
+          context,
+          "Community",
+          backgroundColor: context.appColors.whiteBG,
+        ),
+        backgroundColor: context.appColors.backgroundDefault,
+        body: Row(
+          children: [
+            Expanded(
+              child: Column(
+                children: [
+                  _buildTopSection(context, ref, vm),
+                  const Expanded(
+                    child: AutoRouter(),
+                  )
+                ],
+              ),
+            )
+          ],
+        )
+    );
+  }
+}

+ 37 - 0
packages/cpt_community/lib/modules/community/community_state.dart

@@ -0,0 +1,37 @@
+import 'package:cs_resources/generated/assets.dart';
+
+import '../garagesale/garagesale_page.dart';
+import '../newsfeed/newsfeed_page.dart';
+
+class CommunityVmState {
+  List<Map<String, dynamic>>? topSectionsData;
+  int? curIdx;
+
+  CommunityVmState({
+    List<Map<String, dynamic>>? topSectionsData,
+    this.curIdx = 0,
+  }) : topSectionsData = topSectionsData?? [
+    {
+      "title": "News Feed",
+      "icon": Assets.communityNesFeed,
+      "pageStartInstanceFn": NewsfeedPage.startInstance,
+      "page": const NewsfeedPage(),
+    },
+    {
+      "title": "Garage Sale",
+      "icon": Assets.communityGarageSale,
+      "pageStartInstanceFn": GaragesalePage.startInstance,
+      "page": const GaragesalePage(),
+    },
+  ];
+
+  CommunityVmState copyWith({
+    List<Map<String, dynamic>>? topSectionsData,
+    int? curIdx = 0,
+  }) {
+    return CommunityVmState(
+      topSectionsData: topSectionsData ?? this.topSectionsData,
+      curIdx: curIdx ?? 0,
+    );
+  }
+}

+ 50 - 0
packages/cpt_community/lib/modules/community/community_vm.dart

@@ -0,0 +1,50 @@
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import 'community_state.dart';
+
+import '../garagesale/garagesale_page.dart';
+import '../newsfeed/newsfeed_page.dart';
+
+part 'community_vm.g.dart';
+
+@riverpod
+class CommunityVm extends _$CommunityVm {
+  get topSectionsData => state.topSectionsData;
+
+  CommunityVmState initState() {
+    return CommunityVmState();
+  }
+
+  @override
+  CommunityVmState build(){
+    final state = initState();
+    Log.d("--------------------------build---------------------");
+
+    return state;
+  }
+
+  // 页面切换
+  switchPage(int index,BuildContext? context, [bool? isFirstInitSwitch] ){
+    if(state.curIdx != index){
+      state = state.copyWith(curIdx: index);
+      final List<Map<String, dynamic>>? topSectionsData = state.topSectionsData;
+      // Log.d("当前页面${topSectionsData?[index]['pageStartInstanceFn']}");
+      final pageStartInstanceFn = topSectionsData?[index]['pageStartInstanceFn'] as Function({BuildContext? context});
+      pageStartInstanceFn(context:context);
+    }else {
+      if(isFirstInitSwitch??false){
+        final List<Map<String, dynamic>>? topSectionsData = state.topSectionsData;
+        // Log.d("当前页面${topSectionsData?[index]['pageStartInstanceFn']}");
+        final pageStartInstanceFn = topSectionsData?[index]['pageStartInstanceFn'] as Function({BuildContext? context});
+        pageStartInstanceFn(context:context);
+      }
+    }
+  }
+
+}
+

+ 25 - 0
packages/cpt_community/lib/modules/community/community_vm.g.dart

@@ -0,0 +1,25 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'community_vm.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$communityVmHash() => r'0ab443b891a6d85cdaea249f8f2e7e3f9842e8c8';
+
+/// See also [CommunityVm].
+@ProviderFor(CommunityVm)
+final communityVmProvider =
+    AutoDisposeNotifierProvider<CommunityVm, CommunityVmState>.internal(
+  CommunityVm.new,
+  name: r'communityVmProvider',
+  debugGetCreateSourceHash:
+      const bool.fromEnvironment('dart.vm.product') ? null : _$communityVmHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$CommunityVm = AutoDisposeNotifier<CommunityVmState>;
+// 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 - 34
packages/cpt_community/lib/modules/community/page/community_page.dart

@@ -1,34 +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/community_page_router.dart';
-import '../vm/community_view_model.dart';
-
-@RoutePage()
-class CommunityPage extends HookConsumerWidget {
-  const CommunityPage({Key? key}) : super(key: key);
-
-  //启动当前页面
-  static void startInstance({BuildContext? context}) {
-    if (context != null) {
-      context.router.push(const CommunityPageRoute());
-    } else {
-      appRouter.push(const CommunityPageRoute());
-    }
-  }
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    final _viewModel = ref.read(communityViewModelProvider.notifier);
-
-    return Scaffold(
-      appBar: AppBar(title: Text("社区")),
-      body: Center(
-        child: Text("社区主页面"),
-      ),
-    );
-  }
-}

+ 34 - 0
packages/cpt_community/lib/modules/garagesale/garagesale_page.dart

@@ -0,0 +1,34 @@
+
+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/community_page_router.dart';
+import 'garagesale_vm.dart';
+
+@RoutePage()
+class GaragesalePage extends HookConsumerWidget {
+  const GaragesalePage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const GaragesalePageRoute());
+    } else {
+      appRouter.push(const GaragesalePageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final _viewModel = ref.read(garagesaleVmProvider.notifier);
+
+    return Scaffold(
+      // appBar: AppBar(title: Text("社区")),
+      body: Center(
+        child: Text("garage sale"),
+      ),
+    );
+  }
+}

+ 0 - 0
packages/cpt_community/lib/modules/garagesale/garagesale_repository.dart


+ 0 - 0
packages/cpt_community/lib/modules/garagesale/garagesale_state.dart


+ 14 - 14
packages/cpt_community/lib/modules/community/vm/community_view_model.dart

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

+ 25 - 0
packages/cpt_community/lib/modules/garagesale/garagesale_vm.g.dart

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

+ 177 - 0
packages/cpt_community/lib/modules/newsfeed/newsfeed_page.dart

@@ -0,0 +1,177 @@
+
+import 'package:cpt_community/components/custom_tabs.dart';
+import 'package:cpt_community/components/newsfeed_card_content.dart';
+import 'package:cpt_community/components/newsfeed_card_footer.dart';
+import 'package:cs_resources/generated/assets.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/color_utils.dart';
+import 'package:shared/utils/log_utils.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';
+
+import '../../components/newfeed_card_header.dart';
+import '../../router/page/community_page_router.dart';
+import 'newsfeed_vm.dart';
+
+@RoutePage()
+class NewsfeedPage extends HookConsumerWidget {
+  const NewsfeedPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const NewsfeedPageRoute());
+    } else {
+      appRouter.push(const NewsfeedPageRoute());
+    }
+  }
+
+  Widget _buildTabsSection(BuildContext context, WidgetRef ref, vm){
+    return Container(
+      width: double.infinity,
+      padding: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
+      child: CustomTabs(tabsList: vm.state.tabsList, activeIndex: vm.state.activeIndex),
+    );
+  }
+
+  Widget _buildPostSection(BuildContext context, WidgetRef ref, vm){
+    return Container(
+      height: 65.5,
+      width: double.infinity,
+      padding: const EdgeInsets.only(left: 20, right: 20),
+      color: Colors.white,
+      child: Row(
+        children: [
+          const MyAssetImage(Assets.communityNesFeed, width: 45,height: 45,),
+          Expanded(
+            child: Container(
+              // height: 65.5,
+              // color: Colors.blue,
+              child: MyTextView(
+                "What’s on your mind?",
+                textColor: ColorUtils.string2Color('#000000'),
+                fontSize: 15,
+                marginLeft: 15,
+                alignment: Alignment.centerLeft,
+                textAlign: TextAlign.left,
+                backgroundColor: ColorUtils.string2Color('#ffffff'),
+                maxLines: 1,
+                isFontMedium: true,
+              ),
+            ),
+          ),
+          const MyAssetImage(
+            Assets.communityCamera,
+            width: 21,
+            height: 16.5,
+          ).onTap(() {
+            // 点击 发布的按钮
+            vm.handlerGotoPost();
+          }),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildNewsItem(BuildContext context, WidgetRef ref, item, vm){
+    print("1111111${item}");
+    return Container(
+      width: double.infinity,
+      // padding: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
+        color: Colors.yellow,
+      child: Container(
+        margin: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
+        color: Colors.white,
+        padding: const EdgeInsets.only(left: 15, right: 15,top: 17,bottom: 17),
+        height: 280,
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            // 卡片头部(头像 标题 时间)
+            NewsFeedCardHeader(
+              title: item['title'],
+              avator: item['avator'],
+              time: item['time'],
+            ),
+            const SizedBox(height: 15),
+            // 卡片中间 (文字和图片)
+            Expanded(
+              child: NewsFeedCardContent(
+                content: item['content'],
+                imageUrls: item['imageUrls'],
+              ),
+            ),
+            const SizedBox(height: 26),
+            // // 卡片底部 (点赞 评论 分享)
+            NewsFeedCardFooter(
+              isLike: item['isLike'],
+            ),
+          ]
+        ),
+      )
+    );
+  }
+
+  Widget _buildNesFeedList(BuildContext context, WidgetRef ref, vm){
+    // return Container(
+    //   height: 100,
+    //   color: Colors.blue,
+    // );
+    // List items = List.generate(20, (index) => "Item $index");
+    // List items = _vm.state.list.fromMap();
+    final itemList = vm.state.list?? [];
+    if(itemList.isEmpty){
+      return const Center(child: Text('No Data'));
+    }else {
+      List itemsList = vm.state.list.toList();
+      return ListView.builder(
+        itemCount: itemsList.length,
+        itemBuilder: (context, index) {
+          return _buildNewsItem(context, ref, itemsList[index], vm);
+        },
+      );
+    }
+  }
+
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(newsfeedVmProvider.notifier);
+
+    return Scaffold(
+      backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+      body: Column(
+          children: [
+            _buildTabsSection(context, ref, vm),
+
+            _buildPostSection(context, ref, vm),
+
+            // Expanded(
+            //   child: EasyRefresh(
+            //     // 上拉加载
+            //     onLoad: () async{
+            //       Log.d("----onLoad");
+            //       vm.onLoadData();
+            //     },
+            //     // 下拉刷新
+            //     onRefresh: () async{
+            //       Log.d("----onRefresh");
+            //       vm.refreshListData();
+            //     },
+            //     child: _buildNesFeedList(context, ref, vm),
+            //   ),
+            // )
+            Expanded(
+              child: _buildNesFeedList(context, ref, vm),
+            )
+          ],
+      ),
+    );
+  }
+}

+ 71 - 0
packages/cpt_community/lib/modules/newsfeed/newsfeed_repository.dart

@@ -0,0 +1,71 @@
+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 'newsfeed_state.dart';
+
+part 'newsfeed_repository.g.dart';
+
+@Riverpod(keepAlive: true)
+NewsfeedRepository newsfeedRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return NewsfeedRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class NewsfeedRepository {
+  DioEngine dioEngine;
+
+  NewsfeedRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchNewsfeedList(
+      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 = NewsfeedState.fromMap(json!);
+      //重新赋值data或list
+      return result.convert<NewsfeedState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 12 - 11
packages/cpt_community/lib/modules/community/vm/community_view_model.g.dart

@@ -1,27 +1,28 @@
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
-part of 'community_view_model.dart';
+part of 'newsfeed_repository.dart';
 
 // **************************************************************************
 // RiverpodGenerator
 // **************************************************************************
 
-String _$communityViewModelHash() =>
-    r'3902087cb4011dabd629a95c51d23b3081dd5f80';
+String _$newsfeedRepositoryHash() =>
+    r'79d5132feb0bc631d47ec659702f854189feec5b';
 
-/// See also [CommunityViewModel].
-@ProviderFor(CommunityViewModel)
-final communityViewModelProvider =
-    AutoDisposeNotifierProvider<CommunityViewModel, void>.internal(
-  CommunityViewModel.new,
-  name: r'communityViewModelProvider',
+/// See also [newsfeedRepository].
+@ProviderFor(newsfeedRepository)
+final newsfeedRepositoryProvider = Provider<NewsfeedRepository>.internal(
+  newsfeedRepository,
+  name: r'newsfeedRepositoryProvider',
   debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
       ? null
-      : _$communityViewModelHash,
+      : _$newsfeedRepositoryHash,
   dependencies: null,
   allTransitiveDependencies: null,
 );
 
-typedef _$CommunityViewModel = AutoDisposeNotifier<void>;
+@Deprecated('Will be removed in 3.0. Use Ref instead')
+// ignore: unused_element
+typedef NewsfeedRepositoryRef = ProviderRef<NewsfeedRepository>;
 // 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

+ 63 - 0
packages/cpt_community/lib/modules/newsfeed/newsfeed_state.dart

@@ -0,0 +1,63 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:shared/utils/color_utils.dart';
+
+class NewsfeedState {
+  int? curPage;
+  int? pageSize;
+  int? filterCount;
+  int? activeIndex = 0;
+  List tabsList = [];
+  List? list = [];
+
+
+
+  NewsfeedState copyWith({
+    int? curPage,
+    int? pageSize,
+    int? filterCount,
+    int? activeIndex,
+    List? tabsList,
+    List? list,
+  }) {
+    return NewsfeedState(
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      filterCount: filterCount ?? this.filterCount,
+      activeIndex: activeIndex ?? this.activeIndex,
+      tabsList: tabsList ?? this.tabsList,
+      list: list ?? this.list,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'curPage': this.curPage,
+      'pageSize': this.pageSize,
+      'filterCount': this.filterCount,
+      'activeIndex': this.activeIndex,
+      'tabsList': this.tabsList,
+      'list': this.list,
+    };
+  }
+
+  factory NewsfeedState.fromMap(Map<String, dynamic> map) {
+    return NewsfeedState(
+      curPage: map['curPage'] as int,
+      pageSize: map['pageSize'] as int,
+      filterCount: map['filterCount'] as int,
+      activeIndex: map['activeIndex'] as int,
+      tabsList: map['tabsList'] as List,
+      list: map['list'] as List,
+    );
+  }
+
+  NewsfeedState({
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    this.activeIndex,
+    required this.tabsList,
+    this.list,
+  });
+}

+ 148 - 0
packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.dart

@@ -0,0 +1,148 @@
+
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import 'newsfeed_state.dart';
+import 'newsfeed_repository.dart';
+
+part 'newsfeed_vm.g.dart';
+
+@riverpod
+class NewsfeedVm extends _$NewsfeedVm {
+  late NewsfeedRepository newsfeedRepository;
+  NewsfeedState initState() {
+    return NewsfeedState(
+      activeIndex: 0,
+      tabsList: [
+        {
+          'title': 'News',
+          'icon': null,
+          'activeTitleColor': Colors.white,
+          'activeTitleFontSize': 16,
+          'activeTitleBackgroundColor': ColorUtils.string2Color("#4161D0"),
+        },
+        {
+          'title': 'Following',
+          'icon': null,
+          'activeTitleColor': Colors.white,
+          'activeTitleFontSize': 16,
+          'activeTitleBackgroundColor': ColorUtils.string2Color("#4161D0"),
+        },
+        {
+          'title': 'For You',
+          'icon': null,
+          'activeTitleColor': Colors.white,
+          'activeTitleFontSize': 16,
+          'activeTitleBackgroundColor': ColorUtils.string2Color("#4161D0"),
+        }
+      ],
+      list: [
+          {
+          'id':1,
+          'avator': Assets.communityCamera,
+          'title': 'William Jefferson',
+          'isFollow': false,
+          'content': 'She said YES and our lives changed.Thank you all for coming to my propose today.We hope everyone can ……[More]',
+          'imageUrls': ['https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg','https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg'],
+          'time': 'June 17,2016 at 7:23 p.m.',
+            'isLike': true,
+          'likeno': 12
+          },
+          {
+            'id':2,
+            'avator': Assets.communityCamera,
+            'title': 'William fdsaf的飞洒发生的',
+            'isFollow': true,
+            'content': 'She said YES and our lives changed.Thank you all for coming to my propose today.We hope everyone can ……[More]',
+            'imageUrls': [],
+            'time': 'June 17,2016 at 7:23 p.m.',
+            'isLike': true,
+            'likeno': 12
+          },
+          {
+            'id':3,
+            'avator': Assets.communityCamera,
+            'title': 'Fsjfkds  dfsk',
+            'isFollow': false,
+            'content': 'She said YES and our lives changed.Thank you all for coming to my propose today.We hope everyone can ……[More]',
+            'imageUrls': [],
+            'time': 'June 17,2016 at 7:23 p.m.',
+            'isLike': false,
+            'likeno': 12
+          },
+      ]
+    );
+  }
+  @override
+  NewsfeedState build(){
+    // 引入数据仓库
+    newsfeedRepository = ref.read(newsfeedRepositoryProvider);
+    // 初始化状态
+    NewsfeedState state = initState();
+    return state;
+  }
+
+  // 上拉加载
+  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();
+  }
+
+  // 获取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 newsfeedRepository.fetchNewsfeedList(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(newsfeedVmProvider);
+    getListData();
+
+  }
+
+
+
+  // 点击发布的按钮 跳转到发布的页面
+  void handlerGotoPost(){
+
+  }
+}

+ 25 - 0
packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.g.dart

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

+ 1 - 1
packages/cpt_community/lib/router/component/community_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/community/page/community_page.dart';
+import '../../modules/community/community_page.dart';
 
 part 'community_component_service.g.dart';
 

+ 20 - 3
packages/cpt_community/lib/router/page/community_page_router.dart

@@ -3,8 +3,9 @@ import 'package:flutter/material.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:router/path/router_path.dart';
 
-import '../../modules/community/page/community_page.dart';
-
+import '../../modules/community/community_page.dart';
+import '../../modules/newsfeed/newsfeed_page.dart';
+import '../../modules/garagesale/garagesale_page.dart';
 
 part 'community_page_router.gr.dart';
 
@@ -16,6 +17,22 @@ class CommunityPageRouter extends _$CommunityPageRouter {
   @override
   List<AutoRoute> get routes => [
 
-    CustomRoute(page: CommunityPageRoute.page, path: RouterPath.community, transitionsBuilder: applySlideTransition),
+    CustomRoute(
+        page: CommunityPageRoute.page,
+        path: RouterPath.community,
+        transitionsBuilder: applySlideTransition,
+        children: [
+          CustomRoute(
+              page: NewsfeedPageRoute.page,
+              path: RouterPath.newsFeed,
+              transitionsBuilder: applySlideTransition,
+          ),
+          CustomRoute(
+            page: GaragesalePageRoute.page,
+            path: RouterPath.garageSale,
+            transitionsBuilder: applySlideTransition,
+          ),
+        ]
+    ),
   ];
 }

+ 41 - 1
packages/cpt_community/lib/router/page/community_page_router.gr.dart

@@ -20,7 +20,19 @@ abstract class _$CommunityPageRouter extends RootStackRouter {
         routeData: routeData,
         child: const CommunityPage(),
       );
-    }
+    },
+    GaragesalePageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const GaragesalePage(),
+      );
+    },
+    NewsfeedPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const NewsfeedPage(),
+      );
+    },
   };
 }
 
@@ -37,3 +49,31 @@ class CommunityPageRoute extends PageRouteInfo<void> {
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }
+
+/// generated route for
+/// [GaragesalePage]
+class GaragesalePageRoute extends PageRouteInfo<void> {
+  const GaragesalePageRoute({List<PageRouteInfo>? children})
+      : super(
+          GaragesalePageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'GaragesalePageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [NewsfeedPage]
+class NewsfeedPageRoute extends PageRouteInfo<void> {
+  const NewsfeedPageRoute({List<PageRouteInfo>? children})
+      : super(
+          NewsfeedPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'NewsfeedPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}

+ 280 - 0
packages/cpt_main/lib/modules/demo_page.dart

@@ -0,0 +1,280 @@
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:cs_resources/theme/theme_config.dart';
+import 'package:cs_resources/theme/theme_notifier.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_basic/basic_export.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
+import 'package:plugin_platform/engine/cache/local_cache_manager.dart';
+import 'package:plugin_platform/engine/dialog/dialog_engine.dart';
+import 'package:plugin_platform/engine/directory/directory_util.dart';
+import 'package:plugin_platform/engine/image/image_preview.dart';
+import 'package:plugin_platform/engine/media/image_picker_utils.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/engine/sp/sp_util.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/dialog/app_default_dialog.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/picker/date_picker_util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+import 'package:plugin_platform/platform_export.dart';
+
+
+class DemoPage extends HookConsumerWidget {
+  const DemoPage({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final _userService = UserConfigService.getInstance(ref: ref);
+    final _userConfig = UserConfigService.getState(ref: ref);
+    Log.d("VisitorPage - build 了");
+
+    return Scaffold(
+      appBar: AppBar(title: Text("Visitor"),systemOverlayStyle: ThemeConfig.getSystemUiOverlayStyleByTheme(context)),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: Center(
+        child: Column(
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                Text("当前的用户:${_userConfig.userName}"),
+                ElevatedButton(
+                  onPressed: () {
+                    _userService.setUserInfo("张三");
+                  },
+                  child: Text(
+                    '修改用户信息',
+                  ),
+                ),
+              ],
+            ).marginOnly(top: 10),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                ElevatedButton(
+                  onPressed: () {
+                   // fetchServerTime();
+                  },
+                  child: Text('网络请求'),
+                ),
+                ElevatedButton(
+                  onPressed: () {
+                    ToastEngine.show("这是一个吐司气泡");
+                  },
+                  child: Text('吐司/气泡'),
+                ),
+                ElevatedButton(
+                  onPressed: () async {
+                    NotifyEngine.showSuccess("操作成功");
+                    await Future.delayed(Duration(seconds: 3));
+                    NotifyEngine.showFailure("操作失败");
+                    await Future.delayed(Duration(seconds: 3));
+                    NotifyEngine.showError("操作错误");
+                  },
+                  child: Text('成功/失败通知'),
+                ),
+              ],
+            ).marginOnly(top: 10),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                ElevatedButton(
+                  onPressed: () {
+                    DialogEngine.show(
+                        widget: AppDefaultDialog(
+                          //这种布局自己自定义去
+                          title: "提示",
+                          message: "默认的弹窗,自定义的弹窗自己画去",
+                          confirmAction: () {
+                            ToastEngine.show("点击了确定");
+                          },
+                        ));
+                  },
+                  child: Text('弹窗'),
+                ),
+                ElevatedButton(
+                  onPressed: () {
+                    DateTime dateTime = DateTime.now();
+                    DatePickerUtil.showCupertinoDatePicker(
+                      mode: CupertinoDatePickerMode.date,
+                      selectedDateTime: dateTime,
+                      onDateTimeChanged: (date) {
+                        dateTime = date;
+                      },
+                      title: "选择日期",
+                    );
+                  },
+                  child: Text('时间选择'),
+                ),
+                ElevatedButton(
+                  onPressed: () {
+                    OptionPickerUtil.showCupertinoOptionPicker(
+                      items: ["前天", "昨天", "今天", "明天", "后天"],
+                      initialSelectIndex: 0,
+                      onPickerChanged: (_, index) {
+                        ToastEngine.show("选中的索引为:$index");
+                      },
+                    );
+                  },
+                  child: Text('条件选择'),
+                ),
+              ],
+            ).marginOnly(top: 10),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                ElevatedButton(
+                  onPressed: () {
+                    ImagePickerUtils().show(context, (filePath) {
+                      ToastEngine.show("图片的路径为:$filePath");
+                    });
+                  },
+                  child: Text('相册/相册'),
+                ),
+                ElevatedButton(
+                  onPressed: () async {
+                    final PermissionStatus permissionStatus = await Permission.phone.request();
+                    if (permissionStatus.isGranted) {
+                      final Uri launchUri = Uri(
+                        scheme: 'tel',
+                        path: "+8618571458165",
+                      );
+                      await launchUrl(launchUri);
+                    } else {
+                      // 权限被拒绝
+                      ToastEngine.show('Phone call permission denied');
+                    }
+                  },
+                  child: Text('App动态权限'),
+                ),
+              ],
+            ).marginOnly(top: 10),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                ElevatedButton(
+                  onPressed: () async {
+                    final tempPath = DirectoryUtil.getTempPath();
+                    final docPath = DirectoryUtil.getAppDocPath();
+                    final appSupportPath = DirectoryUtil.getAppSupportPath();
+                    final storagePath = DirectoryUtil.getStoragePath(); //只能拿沙盒路径,外置SD卡是拿不到的
+                    final cacheSize = await DirectoryUtil.getAppCacheSize();
+
+                    Log.d("沙盒路径 - tempPath:$tempPath docPath:$docPath appSupportPath:$appSupportPath storagePath:$storagePath "
+                        "cacheSize:$cacheSize");
+                  },
+                  child: Text('沙盒路径'),
+                ),
+                ElevatedButton(
+                  onPressed: () async {
+                    //Key-Value的重要信息持久化缓存(只存小东西如配置,token)
+                    await SPUtil.putBool("isVip", true);
+                    final isVip = SPUtil.getBool("isVip", defValue: false);
+                    Log.d("存入并取出SP的值 - isVip:$isVip");
+
+                    //沙盒缓存文件缓存(可存入对象,大文本,Json,网络请求数据)
+                    await localCache.put("name", "李四", expiry: const Duration(seconds: 10));
+                    await localCache.put("age", 28, expiry: const Duration(seconds: 10));
+                    await localCache.put("gender", 1);
+                    await localCache.put("skills", ["游泳", "跑步", "编程"]);
+                    await localCache.put("json", {"code": "200", "msg": "Success", "data": 2});
+
+                    String? name = await localCache.get("name");
+                    int? age = await localCache.get("age");
+                    int? gender = await localCache.get("gender");
+                    List<String>? skills = await localCache.get("skills");
+                    Map<String, dynamic>? json = await localCache.get("json");
+                    Log.d("获取缓存name:$name");
+                    Log.d("获取缓存age:$age");
+                    Log.d("获取缓存gender:$gender");
+                    Log.d("获取缓存skills:$skills");
+                    Log.d("获取缓存json:$json");
+                  },
+                  child: Text('缓存用法'),
+                ),
+                ElevatedButton(
+                  onPressed: () {},
+                  child: Text('图片预览'),
+                ),
+              ],
+            ).marginOnly(top: 10),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                ElevatedButton(
+                  onPressed: () {},
+                  child: Text('图片加载'),
+                ),
+                Hero(
+                    tag: '112cc8a34e13',
+                    child: MyLoadImage("https://pic.quanjing.com/cz/8s/QJ8856274343.jpg@%21794ws", width: 80, height: 80),
+                ),
+                ElevatedButton(
+                  onPressed: () {
+                    //单图预览,支持hero
+                    ImagePreviewEngine.singleImagePreview(context, "https://pic.quanjing.com/cz/8s/QJ8856274343.jpg@%21794ws", heroTag: '112cc8a34e13');
+                    //多图预览,支持hero
+                    // ImagePreviewEngine.multipleImagePreview(context, "https://pic.quanjing.com/cz/8s/QJ8856274343.jpg@%21794ws");
+                  },
+                  child: Text('图片预览'),
+                ),
+              ],
+            ).marginOnly(top: 10),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                ElevatedButton(
+                  onPressed: () {
+                    ref.read(themeProvider.notifier).toggleTheme();
+                  },
+                  child: Text('手动切换主题'),
+                  style: ButtonStyle(
+                    backgroundColor: WidgetStateProperty.all<Color>(context.appColors.btnBgDefault),
+                    // 设置按钮的背景颜色
+                    foregroundColor: WidgetStateProperty.all<Color>(Colors.white),
+                    // 设置按钮文字的颜色
+                    shadowColor: WidgetStateProperty.all<Color>(context.appColors.btnBgDefault),
+                    // 按钮阴影颜色
+                    elevation: WidgetStateProperty.all<double>(5),
+                    // 按钮阴影的高度
+                    shape: WidgetStateProperty.all<RoundedRectangleBorder>(
+                      RoundedRectangleBorder(
+                        borderRadius: BorderRadius.circular(30), // 圆角边框
+                      ),
+                    ),
+                  ),
+                ),
+                ElevatedButton(
+                  onPressed: () {
+                    ref.read(themeProvider.notifier).followSystemTheme();
+                  },
+                  child: Text('跟随系统主题'),
+                  style: ButtonStyle(
+                    backgroundColor: WidgetStateProperty.all<Color>(context.appColors.btnBgDefault),
+                    // 设置按钮的背景颜色
+                    foregroundColor: WidgetStateProperty.all<Color>(Colors.white),
+                    // 设置按钮文字的颜色
+                    shadowColor: WidgetStateProperty.all<Color>(context.appColors.btnBgDefault),
+                    // 按钮阴影颜色
+                    elevation: WidgetStateProperty.all<double>(5),
+                    // 按钮阴影的高度
+                    shape: WidgetStateProperty.all<RoundedRectangleBorder>(
+                      RoundedRectangleBorder(
+                        borderRadius: BorderRadius.circular(30), // 圆角边框
+                      ),
+                    ),
+                  ),
+                ),
+              ],
+            ).marginOnly(top: 10),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 130 - 0
packages/cpt_main/lib/modules/feedback/feedback_page.dart

@@ -0,0 +1,130 @@
+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:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+import '../../router/page/main_page_router.dart';
+
+@RoutePage()
+class FeedbackPage extends StatelessWidget {
+  const FeedbackPage({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        S.current.feedback,
+        showBackButton: false,
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      backgroundColor: context.appColors.backgroundDark,
+      body: AutoTabsRouter.pageView(
+        routes: const [
+          FeedbackSendPageRoute(),
+          FeedbackProgressPageRoute(),
+          FeedbackHistoryPageRoute(),
+        ],
+        builder: (context, child, pageController) {
+          final tabsRouter = AutoTabsRouter.of(context);
+
+          return Column(
+            children: [
+              Container(
+                color: context.appColors.whiteBG,
+                height: 120,
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceAround,
+                  children: [
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainFeedbackSend,
+                      45,
+                      51.5,
+                      S.current.sent,
+                      tabsRouter.activeIndex == 0,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(0);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainFeedbackInProgress,
+                      48,
+                      46.5,
+                      S.current.in_progress,
+                      tabsRouter.activeIndex == 1,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(1);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainFeedbackHistory,
+                      38,
+                      45.5,
+                      S.current.history,
+                      tabsRouter.activeIndex == 2,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(2);
+                      },
+                    ),
+                  ],
+                ),
+              ),
+              Expanded(
+                child: child,
+              ),
+            ],
+          );
+        },
+      ),
+    );
+  }
+
+  //顶部的Tab布局
+  Widget _buildFeedbackCategory(BuildContext context, String iconPath, double iconWidth, double iconHeight, String title, bool isSelected) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.center,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: <Widget>[
+        Container(
+          width: 70,
+          height: 70,
+          decoration: BoxDecoration(
+            color: context.appColors.lightBlueBg, // 设置圆形背景颜色
+            shape: BoxShape.circle, // 设置为圆形
+            boxShadow: isSelected
+                ? [
+                    BoxShadow(
+                      color: context.appColors.tabLightBlueShadow, // 设置阴影颜色
+                      blurRadius: 5, // 设置模糊半径
+                      spreadRadius: 0.05, // 控制阴影扩散
+                      offset: const Offset(0, 4), // 设置阴影偏移量
+                    ),
+                  ]
+                : [], // 未选中时无阴影,
+          ),
+          child: Center(
+            child: MyAssetImage(iconPath, width: iconWidth, height: iconHeight),
+          ),
+        ),
+        const SizedBox(height: 7),
+        MyTextView(
+          title,
+          fontSize: 15,
+          isFontMedium: true,
+          textColor: isSelected ? context.appColors.tabTextSelectedDefault : context.appColors.tabTextUnSelectedDefault,
+        ),
+      ],
+    );
+  }
+}

+ 56 - 0
packages/cpt_main/lib/modules/feedback/history/feedback_history.dart

@@ -0,0 +1,56 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../item_feedback.dart';
+import 'feedback_history_view_model.dart';
+
+
+@RoutePage()
+class FeedbackHistoryScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(feedbackHistoryViewModelProvider.notifier);
+    final state = ref.watch(feedbackHistoryViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+        Log.d("FeedbackHistoryScreen 组件卸载时执行");
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                    return FeedbackItem(index: index, item: state.datas[index]);
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/feedback/history/feedback_history_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class FeedbackHistoryState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  FeedbackHistoryState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  FeedbackHistoryState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return FeedbackHistoryState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 131 - 0
packages/cpt_main/lib/modules/feedback/history/feedback_history_view_model.dart

@@ -0,0 +1,131 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'feedback_history_state.dart';
+
+part 'feedback_history_view_model.g.dart';
+
+@riverpod
+class FeedbackHistoryViewModel extends _$FeedbackHistoryViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  FeedbackHistoryState build() {
+    final state = FeedbackHistoryState(datas: []);
+    return state;
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 27 - 0
packages/cpt_main/lib/modules/feedback/history/feedback_history_view_model.g.dart

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

+ 75 - 0
packages/cpt_main/lib/modules/feedback/item_feedback.dart

@@ -0,0 +1,75 @@
+import 'package:cpt_main/modules/demo_page.dart';
+import 'package:cs_resources/generated/assets.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';
+
+class FeedbackItem extends StatelessWidget {
+  final int index;
+  final String item;
+
+  const FeedbackItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
+      padding: const EdgeInsets.symmetric(vertical: 19, horizontal: 18.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: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Row(
+            children: [
+              const MyAssetImage(Assets.mainFeedbackItemIcon, width: 42.5, height: 44),
+              Column(
+                children: [
+
+                  MyTextView(
+                    "Exchange old houses for new ones",
+                    fontSize: 16,
+                    textColor: context.appColors.textBlack,
+                    isFontMedium: true,
+                  ),
+
+                  MyTextView(
+                    "Why are there no implementation rules and application methods for something",
+                    fontSize: 14,
+                    marginTop: 5,
+                    textColor: context.appColors.textBlack,
+                    isFontRegular: true,
+                  ),
+                ],
+              ).expanded(),
+            ],
+          ),
+
+          //备注
+          MyTextView(
+            "18 Sep 2024 18:00  |  Security  |  In Progress",
+            fontSize: 12,
+            marginTop: 10,
+            textColor: context.appColors.textDarkGray,
+            isFontRegular: true,
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 0 - 77
packages/cpt_main/lib/modules/feedback/page/feedback_page.dart

@@ -1,77 +0,0 @@
-import 'package:cs_resources/generated/assets.dart';
-import 'package:flutter/material.dart';
-import 'package:auto_route/auto_route.dart';
-import 'package:shared/utils/ext_dart.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_load_image.dart';
-import 'package:widgets/my_text_view.dart';
-import 'package:widgets/shatter/custom_check_box.dart';
-import 'package:widgets/shatter/custom_radio_check.dart';
-
-@RoutePage()
-class FeedbackPage extends StatelessWidget {
-  const FeedbackPage({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    Log.d("FeedbackPage - build 了");
-
-    return Scaffold(
-      appBar: MyAppBar.appBar(context, "自定义Appbar",backgroundColor: context.theme.primaryColorDark),
-      body: Center(
-        child: Column(
-          mainAxisSize: MainAxisSize.max,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            Text("文本使用").marginOnly(top: 10),
-            MyTextView(
-              "推荐使用统一方案管理",
-              textColor: Colors.black,
-              isFontMedium: true,
-              fontSize: 15,
-            ),
-            Text("图片的使用").marginOnly(top: 10),
-            Row(
-              mainAxisSize: MainAxisSize.max,
-              mainAxisAlignment: MainAxisAlignment.center,
-              children: [
-                MyAssetImage(Assets.baseServicePageNoData, width: 80, height: 80),
-                MyLoadImage("https://pic.quanjing.com/cz/8s/QJ8856274343.jpg@%21794ws", width: 80, height: 80),
-              ],
-            ),
-            Text("Check/Radio 单选/多选").marginOnly(top: 10),
-            //真实开发肯定是后台配置,就算写死的也应该在State中定义状态
-            //多选
-            CustomCheckBox(
-              options: ["中文", "英文", "法语"],
-              onOptionsSelected: (selected) {
-                Log.d("当前选中的索引:$selected");
-              },
-              selectedOptions: ["中文", "英文"],
-              textColor: Colors.black,
-            ).marginOnly(left: 15, right: 15, top: 10),
-
-            //单选
-            CustomRadioCheck(
-              options: ["是", "否"],
-              onOptionSelected: (index, text) {
-                Log.d("当前选中的索引:$index");
-              },
-              textColor: Colors.black,
-              selectedPosition: 1,
-            ).marginOnly(left: 15, right: 15, top: 10),
-
-
-            ElevatedButton(
-              onPressed: () {},
-              child: Text('Loading页面状态'),
-            ).marginOnly(top: 10),
-
-          ],
-        ),
-      ),
-    );
-  }
-}

+ 56 - 0
packages/cpt_main/lib/modules/feedback/progress/feedback_progress.dart

@@ -0,0 +1,56 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../item_feedback.dart';
+import 'feedback_progress_view_model.dart';
+
+
+@RoutePage()
+class FeedbackProgressScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(feedbackProgressViewModelProvider.notifier);
+    final state = ref.watch(feedbackProgressViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+        Log.d("FeedbackProgressScreen 组件卸载时执行");
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                    return FeedbackItem(index: index, item: state.datas[index]);
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/feedback/progress/feedback_progress_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class FeedbackProgressState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  FeedbackProgressState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  FeedbackProgressState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return FeedbackProgressState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 130 - 0
packages/cpt_main/lib/modules/feedback/progress/feedback_progress_view_model.dart

@@ -0,0 +1,130 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'feedback_progress_state.dart';
+
+part 'feedback_progress_view_model.g.dart';
+
+@riverpod
+class FeedbackProgressViewModel extends _$FeedbackProgressViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  FeedbackProgressState build() {
+    return FeedbackProgressState(datas: []);
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 28 - 0
packages/cpt_main/lib/modules/feedback/progress/feedback_progress_view_model.g.dart

@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'feedback_progress_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$feedbackProgressViewModelHash() =>
+    r'0753e433b0a575a262661e6b99030d250b69d0d0';
+
+/// See also [FeedbackProgressViewModel].
+@ProviderFor(FeedbackProgressViewModel)
+final feedbackProgressViewModelProvider = AutoDisposeNotifierProvider<
+    FeedbackProgressViewModel, FeedbackProgressState>.internal(
+  FeedbackProgressViewModel.new,
+  name: r'feedbackProgressViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$feedbackProgressViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$FeedbackProgressViewModel
+    = AutoDisposeNotifier<FeedbackProgressState>;
+// 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

+ 18 - 0
packages/cpt_main/lib/modules/feedback/send/feedback_send.dart

@@ -0,0 +1,18 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/material.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:widgets/responsive_widget.dart';
+import 'feedback_send_large.dart';
+import 'feedback_send_small.dart';
+
+@RoutePage()
+class FeedbackSendScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+
+    return ResponsiveWidget(
+      smallScreen: FeedbackSendSmall(),
+      smallFullScreen: FeedbackSendLarge(),
+    );
+  }
+}

+ 58 - 0
packages/cpt_main/lib/modules/feedback/send/feedback_send_large.dart

@@ -0,0 +1,58 @@
+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:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+class FeedbackSendLarge extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+
+    return Container(
+      padding: const EdgeInsets.symmetric(horizontal: 38),
+      width: double.infinity,
+      height: double.infinity,
+      child: Center(
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            const MyAssetImage(Assets.mainFeedbackSendImg, width: 237.5, height: 177).marginOnly(top: 15, bottom: 26),
+            MyTextView(
+              S.current.feedback_msg_1,
+              fontSize: 17,
+              textAlign: TextAlign.center,
+              isFontBold: true,
+              textColor: context.appColors.textBlack,
+            ),
+            MyTextView(
+              S.current.feedback_msg_2,
+              fontSize: 15,
+              marginTop: 12,
+              textAlign: TextAlign.center,
+              isFontMedium: true,
+              textColor: context.appColors.textBlack,
+            ),
+            MyButton(
+              onPressed: () {
+                ToastEngine.show("去填写表单");
+              },
+              text: S.current.create_new_feedback,
+              textColor: Colors.white,
+              disabledTextColor: Colors.white,
+              backgroundColor: context.appColors.btnBgDefault,
+              fontWeight: FontWeight.w500,
+              type: ClickType.throttle,
+              minHeight: 50,
+              radius: 5,
+            ).marginOnly(top: 20, bottom: 30),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 55 - 0
packages/cpt_main/lib/modules/feedback/send/feedback_send_small.dart

@@ -0,0 +1,55 @@
+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:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+class FeedbackSendSmall extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return SingleChildScrollView(
+      scrollDirection: Axis.vertical,
+      physics: const BouncingScrollPhysics(),
+      child: Container(
+        margin: const EdgeInsets.symmetric(horizontal: 38),
+        width: double.infinity,
+        child: Column(mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [
+          const MyAssetImage(Assets.mainFeedbackSendImg, width: 237.5, height: 177).marginOnly(top: 15, bottom: 26),
+          MyTextView(
+            S.current.feedback_msg_1,
+            fontSize: 17,
+            textAlign: TextAlign.center,
+            isFontBold: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.feedback_msg_2,
+            fontSize: 15,
+            marginTop: 12,
+            textAlign: TextAlign.center,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyButton(
+            onPressed: () {
+              ToastEngine.show("去填写表单");
+            },
+            text: S.current.create_new_feedback,
+            textColor: Colors.white,
+            disabledTextColor: Colors.white,
+            backgroundColor: context.appColors.btnBgDefault,
+            fontWeight: FontWeight.w500,
+            type: ClickType.throttle,
+            minHeight: 50,
+            radius: 5,
+          ).marginOnly(top: 20, bottom: 30),
+        ]),
+      ),
+    );
+    ;
+  }
+}

+ 101 - 84
packages/cpt_main/lib/modules/home/home_page.dart

@@ -6,6 +6,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter/src/widgets/framework.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:auto_route/auto_route.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:router/componentRouter/community_service.dart';
+import 'package:router/componentRouter/component_service_manager.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_load_image.dart';
@@ -29,38 +32,46 @@ class HomePage extends HookConsumerWidget {
 
     return Scaffold(
       appBar: MyAppBar.appBar(context, "Good Afternoon,Mike",
+          backIconPath: Assets.mainTabMeSelected,
+          backIconWidth: 18.5,
+          backIconHeight: 20,
+          showBackButton: true,
           backgroundColor: context.appColors.whiteBG,
+          backCallback: (){
+          ToastEngine.show("测试去登录页面");
+          ComponentServiceManager().authService.startLoginPage();
+          },
           actions: [
             Center(
-                child: Stack(
-                  clipBehavior: Clip.none, // 不裁剪超出边界的内容
-                  alignment: Alignment.topLeft,
-                  children: <Widget>[
-                    // 通知图标
-                    const MyAssetImage(Assets.mainHomeNotificationIcon, width: 19, height: 20),
+                    child: Stack(
+              clipBehavior: Clip.none, // 不裁剪超出边界的内容
+              alignment: Alignment.topLeft,
+              children: <Widget>[
+                // 通知图标
+                const MyAssetImage(Assets.mainHomeNotificationIcon, width: 19, height: 20),
 
-                    //未读消息
-                    Positioned(
-                      left: 0,
-                      top: 0,
-                      child: Transform.translate(
-                        offset: const Offset(-10, -5),
-                        child: MyTextView(
-                          "99",
-                          boxWidth: 20.0,
-                          textColor: Colors.white,
-                          fontSize: 10,
-                          isFontLight: true,
-                          backgroundColor: context.appColors.redDefault,
-                          cornerRadius: 8,
-                          paddingTop: 2,
-                          paddingBottom: 2,
-                          textAlign: TextAlign.center,
-                        ),
-                      ),
+                //未读消息
+                Positioned(
+                  left: 0,
+                  top: 0,
+                  child: Transform.translate(
+                    offset: const Offset(-10, -5),
+                    child: MyTextView(
+                      "99",
+                      boxWidth: 20.0,
+                      textColor: Colors.white,
+                      fontSize: 10,
+                      isFontLight: true,
+                      backgroundColor: context.appColors.redDefault,
+                      cornerRadius: 8,
+                      paddingTop: 2,
+                      paddingBottom: 2,
+                      textAlign: TextAlign.center,
                     ),
-                  ],
-                ).onTap(viewModel.gotoNotificationPage))
+                  ),
+                ),
+              ],
+            ).onTap(viewModel.gotoNotificationPage))
                 .marginOnly(right: 15),
           ],
           showBottomDivider: true),
@@ -165,7 +176,13 @@ class HomePage extends HookConsumerWidget {
                       textColor: context.appColors.textBlack,
                       fontSize: 15,
                       isFontMedium: true,
-                    ).paddingOnly(left: 13, right: 13).expanded(),
+                    ).paddingOnly(left: 13, right: 4).expanded(),
+                    MyTextView(
+                      "9568",
+                      textColor: context.appColors.textBlack,
+                      fontSize: 15,
+                      isFontBold: true,
+                    ).paddingOnly(left: 1, right: 4),
                     const MyAssetImage(Assets.mainHomeMoreIcon, width: 6, height: 8.5).marginOnly(right: 15),
                   ],
                 ).onTap(viewModel.gotoRewardsPage).expanded(),
@@ -193,12 +210,12 @@ class HomePage extends HookConsumerWidget {
     return SliverGrid(
       gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
         crossAxisCount: 3, // 三列
-        mainAxisSpacing: 14.0, // 主轴(上下)的间距
+        mainAxisSpacing: 10.0, // 主轴(上下)的间距
         crossAxisSpacing: 0.0, // 交叉轴(左右)的间距
-        childAspectRatio: 9 / 7, // 子组件的宽高比
+        childAspectRatio: 9 / 8, // 子组件的宽高比
       ),
       delegate: SliverChildBuilderDelegate(
-            (BuildContext context, int index) {
+        (BuildContext context, int index) {
           return HomeCategoryItem(
             category: state.homeCategory[index],
           ).onTap(() {
@@ -231,32 +248,32 @@ class HomePage extends HookConsumerWidget {
 
     return SliverToBoxAdapter(
         child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          mainAxisAlignment: MainAxisAlignment.start,
-          children: [
-            MyTextView(
-              S.current.latest_news,
-              fontSize: 16,
-              marginTop: 14,
-              marginBottom: 14,
-              isFontMedium: true,
-              onClick: viewModel.gotoLastNewsPage,
-              textColor: context.appColors.textPrimary,
-            ),
-            SingleChildScrollView(
-              scrollDirection: Axis.horizontal,
-              physics: const BouncingScrollPhysics(),
-              clipBehavior: Clip.none,
-              child: Row(
-                children: List.generate(state.lastNews.length, (index) {
-                  return LastNewsItem(
-                    lastNews: state.lastNews[index],
-                  );
-                }),
-              ),
-            )
-          ],
-        ).paddingOnly(left: 15, right: 15));
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        MyTextView(
+          S.current.latest_news,
+          fontSize: 16,
+          marginTop: 14,
+          marginBottom: 14,
+          isFontMedium: true,
+          onClick: viewModel.gotoLastNewsPage,
+          textColor: context.appColors.textPrimary,
+        ),
+        SingleChildScrollView(
+          scrollDirection: Axis.horizontal,
+          physics: const BouncingScrollPhysics(),
+          clipBehavior: Clip.none,
+          child: Row(
+            children: List.generate(state.lastNews.length, (index) {
+              return LastNewsItem(
+                lastNews: state.lastNews[index],
+              );
+            }),
+          ),
+        )
+      ],
+    ).paddingOnly(left: 15, right: 15));
   }
 
   //最新的交易列表
@@ -280,7 +297,7 @@ class HomePage extends HookConsumerWidget {
           padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
           sliver: SliverList(
             delegate: SliverChildBuilderDelegate(
-                  (BuildContext context, int index) {
+              (BuildContext context, int index) {
                 return Padding(
                   padding: const EdgeInsets.symmetric(vertical: 10),
                   child: LastTransItem(
@@ -335,31 +352,31 @@ class HomePage extends HookConsumerWidget {
 
     return SliverToBoxAdapter(
         child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          mainAxisAlignment: MainAxisAlignment.start,
-          children: [
-            MyTextView(
-              S.current.strata_management_guides,
-              fontSize: 16,
-              marginTop: 14,
-              marginBottom: 14,
-              onClick: viewModel.gotoManageGuidePage,
-              isFontMedium: true,
-              textColor: context.appColors.textPrimary,
-            ),
-            SingleChildScrollView(
-              scrollDirection: Axis.horizontal,
-              physics: const BouncingScrollPhysics(),
-              clipBehavior: Clip.none,
-              child: Row(
-                children: List.generate(state.manage_guide.length, (index) {
-                  return ManageGuideItem(
-                    manageGuide: state.manage_guide[index],
-                  );
-                }),
-              ),
-            )
-          ],
-        ).paddingOnly(left: 15, right: 15));
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        MyTextView(
+          S.current.strata_management_guides,
+          fontSize: 16,
+          marginTop: 14,
+          marginBottom: 14,
+          onClick: viewModel.gotoManageGuidePage,
+          isFontMedium: true,
+          textColor: context.appColors.textPrimary,
+        ),
+        SingleChildScrollView(
+          scrollDirection: Axis.horizontal,
+          physics: const BouncingScrollPhysics(),
+          clipBehavior: Clip.none,
+          child: Row(
+            children: List.generate(state.manage_guide.length, (index) {
+              return ManageGuideItem(
+                manageGuide: state.manage_guide[index],
+              );
+            }),
+          ),
+        )
+      ],
+    ).paddingOnly(left: 15, right: 15));
   }
 }

+ 9 - 7
packages/cpt_main/lib/modules/home/home_view_model.dart

@@ -1,3 +1,4 @@
+import 'package:cpt_main/modules/home/property_news/home_property_news_page.dart';
 import 'package:cpt_main/modules/notification/notification_page.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -5,6 +6,8 @@ import 'package:router/componentRouter/community_service.dart';
 import 'package:router/componentRouter/component_service_manager.dart';
 
 import 'home_state.dart';
+import 'latest_news/latest_news_page.dart';
+import 'management_guides/management_guides_page.dart';
 
 part 'home_view_model.g.dart';
 
@@ -58,16 +61,15 @@ class HomeViewModel extends _$HomeViewModel {
     ComponentServiceManager().rewardsService.startRewardsPage();
   }
 
-  void gotoLastNewsPage(){
-    ToastEngine.show("去最近新闻的页面");
+  void gotoLastNewsPage() {
+    LatestNewsPage.startInstance();
   }
 
-  void gotoPropertyNewsPage(){
-    ToastEngine.show("去房产新闻的页面");
+  void gotoPropertyNewsPage() {
+    HomePropertyNewsPage.startInstance();
   }
 
-  void gotoManageGuidePage(){
-    ToastEngine.show("去管理员指引的页面");
+  void gotoManageGuidePage() {
+    ManagementGuidesPage.startInstance();
   }
-
 }

+ 1 - 1
packages/cpt_main/lib/modules/home/home_view_model.g.dart

@@ -6,7 +6,7 @@ part of 'home_view_model.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$homeViewModelHash() => r'9b4974389335a1d56e6b345f83e7c626e3ba0d28';
+String _$homeViewModelHash() => r'9ad38aa4741b3216454b6652963eb10af930f3d8';
 
 /// See also [HomeViewModel].
 @ProviderFor(HomeViewModel)

+ 1 - 1
packages/cpt_main/lib/modules/home/item_home_category.dart

@@ -1,4 +1,4 @@
-import 'package:cpt_main/modules/feedback/page/feedback_page.dart';
+import 'package:cpt_main/modules/feedback/feedback_page.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:widgets/my_load_image.dart';

+ 1 - 1
packages/cpt_main/lib/modules/home/item_home_last_news.dart

@@ -1,4 +1,4 @@
-import 'package:cpt_main/modules/feedback/page/feedback_page.dart';
+import 'package:cpt_main/modules/feedback/feedback_page.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:widgets/ext/ex_widget.dart';

+ 1 - 1
packages/cpt_main/lib/modules/home/item_home_last_trans.dart

@@ -1,4 +1,4 @@
-import 'package:cpt_main/modules/feedback/page/feedback_page.dart';
+import 'package:cpt_main/modules/feedback/feedback_page.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:shared/utils/util.dart';

+ 1 - 1
packages/cpt_main/lib/modules/home/item_home_manage_guide.dart

@@ -1,4 +1,4 @@
-import 'package:cpt_main/modules/feedback/page/feedback_page.dart';
+import 'package:cpt_main/modules/feedback/feedback_page.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:widgets/ext/ex_widget.dart';

+ 1 - 1
packages/cpt_main/lib/modules/home/item_home_property_news.dart

@@ -1,4 +1,4 @@
-import 'package:cpt_main/modules/feedback/page/feedback_page.dart';
+import 'package:cpt_main/modules/feedback/feedback_page.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:shared/utils/util.dart';

+ 55 - 0
packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_screen.dart

@@ -0,0 +1,55 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:cpt_main/modules/home/property_news/item_list_news.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_info_view_model.dart';
+
+
+@RoutePage()
+class LatestNewsInfoScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(latestNewsInfoViewModelProvider.notifier);
+    final state = ref.watch(latestNewsInfoViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                    return ListNewsItem(index: index, item: state.datas[index]);
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class LatestNewsInfoState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  LatestNewsInfoState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  LatestNewsInfoState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return LatestNewsInfoState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 130 - 0
packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_view_model.dart

@@ -0,0 +1,130 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_info_state.dart';
+
+part 'latest_news_info_view_model.g.dart';
+
+@riverpod
+class LatestNewsInfoViewModel extends _$LatestNewsInfoViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  LatestNewsInfoState build() {
+    return LatestNewsInfoState(datas: []);
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 27 - 0
packages/cpt_main/lib/modules/home/latest_news/info/latest_news_info_view_model.g.dart

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

+ 54 - 0
packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_screen.dart

@@ -0,0 +1,54 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:cpt_main/modules/home/property_news/item_list_news.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_internal_view_model.dart';
+
+
+@RoutePage()
+class LatestNewsInternalScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(latestNewsInternalViewModelProvider.notifier);
+    final state = ref.watch(latestNewsInternalViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                    return ListNewsItem(index: index, item: state.datas[index]);
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class LatestNewsInternalState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  LatestNewsInternalState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  LatestNewsInternalState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return LatestNewsInternalState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 130 - 0
packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_view_model.dart

@@ -0,0 +1,130 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_internal_state.dart';
+
+part 'latest_news_internal_view_model.g.dart';
+
+@riverpod
+class LatestNewsInternalViewModel extends _$LatestNewsInternalViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  LatestNewsInternalState build() {
+    return LatestNewsInternalState(datas: []);
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 28 - 0
packages/cpt_main/lib/modules/home/latest_news/internal/latest_news_internal_view_model.g.dart

@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'latest_news_internal_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$latestNewsInternalViewModelHash() =>
+    r'109c11826358639b41d979660e1528e63a002be8';
+
+/// See also [LatestNewsInternalViewModel].
+@ProviderFor(LatestNewsInternalViewModel)
+final latestNewsInternalViewModelProvider = AutoDisposeNotifierProvider<
+    LatestNewsInternalViewModel, LatestNewsInternalState>.internal(
+  LatestNewsInternalViewModel.new,
+  name: r'latestNewsInternalViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$latestNewsInternalViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$LatestNewsInternalViewModel
+    = AutoDisposeNotifier<LatestNewsInternalState>;
+// 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

+ 152 - 0
packages/cpt_main/lib/modules/home/latest_news/latest_news_page.dart

@@ -0,0 +1,152 @@
+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:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+import '../../../router/page/main_page_router.dart';
+
+@RoutePage()
+class LatestNewsPage extends StatelessWidget {
+  const LatestNewsPage({Key? key}) : super(key: key);
+
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const LatestNewsPageRoute());
+    } else {
+      appRouter.push(const LatestNewsPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        S.current.latest_news,
+        showBackButton: false,
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      backgroundColor: context.appColors.backgroundDark,
+      body: AutoTabsRouter.pageView(
+        routes: const [
+          LatestNewsPropertyPageRoute(),
+          LatestNewsInternalPageRoute(),
+          LatestNewsInfoPageRoute(),
+          LatestNewsPublishPageRoute(),
+        ],
+        builder: (context, child, pageController) {
+          final tabsRouter = AutoTabsRouter.of(context);
+
+          return Column(
+            children: [
+              Container(
+                color: context.appColors.whiteBG,
+                height: 120,
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceAround,
+                  children: [
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainLatestProperty,
+                      53.5,
+                      47,
+                      S.current.property,
+                      tabsRouter.activeIndex == 0,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(0);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainLatestInternal,
+                      38.5,
+                      45.5,
+                      S.current.internal,
+                      tabsRouter.activeIndex == 1,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(1);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainLatestInfo,
+                      45,
+                      47.5,
+                      S.current.info,
+                      tabsRouter.activeIndex == 2,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(2);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainLatestPublish,
+                      44,
+                      47,
+                      S.current.publish,
+                      tabsRouter.activeIndex == 3,
+                    ).onTap(
+                          () {
+                        tabsRouter.setActiveIndex(3);
+                      },
+                    ),
+                  ],
+                ),
+              ),
+              Expanded(
+                child: child,
+              ),
+            ],
+          );
+        },
+      ),
+    );
+  }
+
+  //顶部的Tab布局
+  Widget _buildFeedbackCategory(BuildContext context, String iconPath, double iconWidth, double iconHeight, String title, bool isSelected) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.center,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: <Widget>[
+        Container(
+          width: 70,
+          height: 70,
+          decoration: BoxDecoration(
+            color: context.appColors.lightBlueBg, // 设置圆形背景颜色
+            shape: BoxShape.circle, // 设置为圆形
+            boxShadow: isSelected
+                ? [
+                    BoxShadow(
+                      color: context.appColors.tabLightBlueShadow, // 设置阴影颜色
+                      blurRadius: 5, // 设置模糊半径
+                      spreadRadius: 0.05, // 控制阴影扩散
+                      offset: const Offset(0, 4), // 设置阴影偏移量
+                    ),
+                  ]
+                : [], // 未选中时无阴影,
+          ),
+          child: Center(
+            child: MyAssetImage(iconPath, width: iconWidth, height: iconHeight),
+          ),
+        ),
+        const SizedBox(height: 7),
+        MyTextView(
+          title,
+          fontSize: 15,
+          isFontMedium: true,
+          textColor: isSelected ? context.appColors.tabTextSelectedDefault : context.appColors.tabTextUnSelectedDefault,
+        ),
+      ],
+    );
+  }
+}

+ 54 - 0
packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_screen.dart

@@ -0,0 +1,54 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:cpt_main/modules/home/property_news/item_list_news.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_property_view_model.dart';
+
+
+@RoutePage()
+class LatestNewsPropertyScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(latestNewsPropertyViewModelProvider.notifier);
+    final state = ref.watch(latestNewsPropertyViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                    return ListNewsItem(index: index, item: state.datas[index]);
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class LatestNewsPropertyState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  LatestNewsPropertyState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  LatestNewsPropertyState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return LatestNewsPropertyState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 131 - 0
packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_view_model.dart

@@ -0,0 +1,131 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_property_state.dart';
+
+part 'latest_news_property_view_model.g.dart';
+
+@riverpod
+class LatestNewsPropertyViewModel extends _$LatestNewsPropertyViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  LatestNewsPropertyState build() {
+    final state = LatestNewsPropertyState(datas: []);
+    return state;
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 28 - 0
packages/cpt_main/lib/modules/home/latest_news/property/latest_news_property_view_model.g.dart

@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'latest_news_property_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$latestNewsPropertyViewModelHash() =>
+    r'4c01555638d9c2819e0bd77ffb044a9bf9ff2b1f';
+
+/// See also [LatestNewsPropertyViewModel].
+@ProviderFor(LatestNewsPropertyViewModel)
+final latestNewsPropertyViewModelProvider = AutoDisposeNotifierProvider<
+    LatestNewsPropertyViewModel, LatestNewsPropertyState>.internal(
+  LatestNewsPropertyViewModel.new,
+  name: r'latestNewsPropertyViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$latestNewsPropertyViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$LatestNewsPropertyViewModel
+    = AutoDisposeNotifier<LatestNewsPropertyState>;
+// 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

+ 54 - 0
packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_screen.dart

@@ -0,0 +1,54 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:cpt_main/modules/home/property_news/item_list_news.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_publish_view_model.dart';
+
+
+@RoutePage()
+class LatestNewsPublishScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(latestNewsPublishViewModelProvider.notifier);
+    final state = ref.watch(latestNewsPublishViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                    return ListNewsItem(index: index, item: state.datas[index]);
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class LatestNewsPublishState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  LatestNewsPublishState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  LatestNewsPublishState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return LatestNewsPublishState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 130 - 0
packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_view_model.dart

@@ -0,0 +1,130 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'latest_news_publish_state.dart';
+
+part 'latest_news_publish_view_model.g.dart';
+
+@riverpod
+class LatestNewsPublishViewModel extends _$LatestNewsPublishViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  LatestNewsPublishState build() {
+    return LatestNewsPublishState(datas: []);
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 28 - 0
packages/cpt_main/lib/modules/home/latest_news/publish/latest_news_publish_view_model.g.dart

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

+ 56 - 0
packages/cpt_main/lib/modules/home/management_guides/item_management_guide.dart

@@ -0,0 +1,56 @@
+import 'package:cpt_main/modules/feedback/feedback_page.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+class ManagementGuideItem extends StatelessWidget {
+  final String? iconImage;
+  final String? title;
+
+  ManagementGuideItem({
+    this.iconImage,
+    this.title,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      decoration: BoxDecoration(
+        color: context.appColors.lightBlueBg,
+        borderRadius: BorderRadius.circular(5.0), // 5个圆角
+        boxShadow: [
+          BoxShadow(
+            color: const Color(0xFF656565).withOpacity(0.1), // 阴影颜色,并且设置透明度
+            offset: const Offset(0, 1.5), // 阴影的偏移量
+            blurRadius: 2.5, // 模糊半径
+            spreadRadius: 1.5, // 扩散半径
+          ),
+        ],
+      ),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.start,
+        children: [
+          AspectRatio(
+            aspectRatio: 165 / 108, // 设置宽高比例为 165:108
+            child: MyAssetImage(
+              iconImage ?? "-",
+              width: double.infinity,
+              height: double.infinity,
+            ),
+          ),
+          MyTextView(
+            title ?? "-",
+            marginLeft: 9,
+            marginTop: 15,
+            maxLines: 2,
+            fontSize: 15,
+            isFontMedium: true,
+            textColor: context.appColors.tabTextUnSelectedPrimary,
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 84 - 0
packages/cpt_main/lib/modules/home/management_guides/management_guides_page.dart

@@ -0,0 +1,84 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:cpt_main/router/page/main_page_router.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.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/load_state_layout.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'item_management_guide.dart';
+import 'management_guides_view_model.dart';
+
+@RoutePage()
+class ManagementGuidesPage extends HookConsumerWidget {
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const ManagementGuidesPageRoute());
+    } else {
+      appRouter.push(const ManagementGuidesPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(managementGuidesViewModelProvider.notifier);
+    final state = ref.watch(managementGuidesViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, S.current.strata_management_guides, backgroundColor: context.appColors.whiteBG),
+      backgroundColor: context.appColors.backgroundDefault,
+      body: Container(
+        width: double.infinity,
+        height: double.infinity,
+        child: EasyRefresh(
+          controller: viewModel.refreshController,
+          onRefresh: viewModel.onRefresh,
+          onLoad: viewModel.loadMore,
+          child: LoadStateLayout(
+            state: state.loadingState,
+            errorMessage: state.errorMessage,
+            errorRetry: () {
+              viewModel.retryRequest();
+            },
+            successSliverWidget: [
+              SliverPadding(
+                padding: const EdgeInsets.symmetric(horizontal: 15.0,vertical: 7), // 设置四周的间距
+                sliver: SliverGrid(
+                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
+                    crossAxisCount: 2, // 两列
+                    mainAxisSpacing: 10.0, // 主轴(上下)的间距
+                    crossAxisSpacing: 15.0, // 交叉轴(左右)的间距
+                    childAspectRatio: 165 / 181, // 子组件的宽高比
+                  ),
+                  delegate: SliverChildBuilderDelegate(
+                        (BuildContext context, int index) {
+                      return ManagementGuideItem(
+                        iconImage: state.datas[index].iconImage,
+                        title: state.datas[index].title,
+                      ); // 生成每个网格项
+                    },
+                    childCount: state.datas.length, // 总共的网格项数
+                  ),
+                ),
+              )
+            ],
+          ),
+        ).marginOnly(top: 10, bottom: 5),
+      ),
+    );
+  }
+}

+ 32 - 0
packages/cpt_main/lib/modules/home/management_guides/management_guides_state.dart

@@ -0,0 +1,32 @@
+import 'package:cpt_main/modules/home/management_guides/test_guide_bean.dart';
+import 'package:widgets/load_state_layout.dart';
+
+class ManagementGuidesState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<TestGuideBean> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  ManagementGuidesState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  ManagementGuidesState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<TestGuideBean>? datas,
+  }) {
+    return ManagementGuidesState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 144 - 0
packages/cpt_main/lib/modules/home/management_guides/management_guides_view_model.dart

@@ -0,0 +1,144 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'management_guides_state.dart';
+import 'test_guide_bean.dart';
+
+part 'management_guides_view_model.g.dart';
+
+@riverpod
+class ManagementGuidesViewModel extends _$ManagementGuidesViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
+  );
+
+  @override
+  ManagementGuidesState build() {
+    return ManagementGuidesState(datas: []);
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<TestGuideBean> list = [
+      TestGuideBean()
+        ..iconImage = Assets.mainIntroductionGuide
+        ..title = S.current.introduction_to_info_pack,
+
+      TestGuideBean()
+        ..iconImage = Assets.mainRolesGuide
+        ..title = S.current.your_roles_responsibilities,
+
+      TestGuideBean()
+        ..iconImage = Assets.mainPropertyGuide
+        ..title = S.current.property_guide,
+    ];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 28 - 0
packages/cpt_main/lib/modules/home/management_guides/management_guides_view_model.g.dart

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

+ 4 - 0
packages/cpt_main/lib/modules/home/management_guides/test_guide_bean.dart

@@ -0,0 +1,4 @@
+class TestGuideBean{
+  String? iconImage;
+  String? title;
+}

+ 72 - 0
packages/cpt_main/lib/modules/home/property_news/home_property_news_page.dart

@@ -0,0 +1,72 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:cpt_main/router/page/main_page_router.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.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/load_state_layout.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'item_list_news.dart';
+import 'home_property_news_view_model.dart';
+
+@RoutePage()
+class HomePropertyNewsPage extends HookConsumerWidget {
+
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const HomePropertyNewsPageRoute());
+    } else {
+      appRouter.push(const HomePropertyNewsPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(homePropertyNewsViewModelProvider.notifier);
+    final state = ref.watch(homePropertyNewsViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, S.current.property_news, backgroundColor: context.appColors.whiteBG),
+      backgroundColor: context.appColors.backgroundDark,
+      body: Container(
+        width: double.infinity,
+        height: double.infinity,
+        child: EasyRefresh(
+          controller: viewModel.refreshController,
+          onRefresh: viewModel.onRefresh,
+          onLoad: viewModel.loadMore,
+          child: LoadStateLayout(
+            state: state.loadingState,
+            errorMessage: state.errorMessage,
+            errorRetry: () {
+              viewModel.retryRequest();
+            },
+            successSliverWidget: [
+              SliverList(
+                  delegate: SliverChildBuilderDelegate(
+                (context, index) {
+                  return ListNewsItem(index: index, item: state.datas[index]);
+                },
+                childCount: state.datas.length,
+              ))
+            ],
+          ),
+        ).marginOnly(top: 10, bottom: 5),
+      ),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/home/property_news/home_property_news_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class HomePropertyNewsState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  HomePropertyNewsState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  HomePropertyNewsState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return HomePropertyNewsState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 130 - 0
packages/cpt_main/lib/modules/home/property_news/home_property_news_view_model.dart

@@ -0,0 +1,130 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'home_property_news_state.dart';
+
+part 'home_property_news_view_model.g.dart';
+
+@riverpod
+class HomePropertyNewsViewModel extends _$HomePropertyNewsViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  HomePropertyNewsState build() {
+    return HomePropertyNewsState(datas: []);
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 28 - 0
packages/cpt_main/lib/modules/home/property_news/home_property_news_view_model.g.dart

@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'home_property_news_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$homePropertyNewsViewModelHash() =>
+    r'9df28d33819329f1677174f3360970b126cf5f49';
+
+/// See also [HomePropertyNewsViewModel].
+@ProviderFor(HomePropertyNewsViewModel)
+final homePropertyNewsViewModelProvider = AutoDisposeNotifierProvider<
+    HomePropertyNewsViewModel, HomePropertyNewsState>.internal(
+  HomePropertyNewsViewModel.new,
+  name: r'homePropertyNewsViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$homePropertyNewsViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$HomePropertyNewsViewModel
+    = AutoDisposeNotifier<HomePropertyNewsState>;
+// 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

+ 68 - 0
packages/cpt_main/lib/modules/home/property_news/item_list_news.dart

@@ -0,0 +1,68 @@
+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';
+
+///  首页新闻News 的Item
+class ListNewsItem extends StatelessWidget {
+  final int index;
+  final String item;
+
+  const ListNewsItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      height: 117.5,
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 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: Row(
+        mainAxisSize: MainAxisSize.max,
+        children: [
+          MyLoadImage(
+            "https://pic.rmb.bdstatic.com/bjh/news/e991d703e32e11c2414ca1298410cc3a8789.jpeg",
+            width: 100,
+            height: 117.5,
+          ).marginOnly(right: 18),
+          Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              MyTextView(
+                "On Monday, the real estate market stopped falling and stabilized, and a devices",
+                marginTop: 12,
+                fontSize: 16,
+                maxLines: 3,
+                textColor: context.appColors.textBlack,
+                isFontMedium: true,
+              ).expanded(),
+              MyTextView(
+                "Monday 14 0ct 2024",
+                fontSize: 12,
+                marginBottom: 12,
+                marginTop: 12,
+                textColor: context.appColors.textBlack,
+                isFontRegular: true,
+              ),
+            ],
+          ).expanded(),
+        ],
+      ),
+    );
+  }
+}

+ 1 - 1
packages/cpt_main/lib/modules/main/main_state.dart

@@ -1,4 +1,4 @@
-import 'package:cpt_main/modules/feedback/page/feedback_page.dart';
+import 'package:cpt_main/modules/feedback/feedback_page.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:flutter/material.dart';

+ 210 - 28
packages/cpt_main/lib/modules/me/me_page.dart

@@ -1,41 +1,223 @@
+import 'package:cpt_main/modules/demo_page.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:cs_resources/theme/theme_config.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
-import 'package:plugin_basic/modules/global_web_page.dart';
-import 'package:plugin_basic/provider/user_config/user_config_service.dart';
-import 'package:router/componentRouter/component_service_manager.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/shatter/setting_item_container.dart';
+
+import 'me_view_model.dart';
 
 @RoutePage()
-class MePage extends StatelessWidget {
+class MePage extends HookConsumerWidget {
   const MePage({Key? key}) : super(key: key);
 
   @override
-  Widget build(BuildContext context) {
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(meViewModelProvider.notifier);
+
     return Scaffold(
-      appBar: AppBar(title: Text("Me")),
-      body:Center(
-        child: Column(
-          children: [
-            ElevatedButton(
-              onPressed: () {
-                UserConfigService.getInstance().setUserInfo("李四");
-              },
-              child: const Text('跨页面修改用户信息'),
-            ),
-            ElevatedButton(
-              onPressed: () {
-               ComponentServiceManager().profileService.startEditProfilePage(context: context);
-              },
-              child: const Text('Go to Edit Profile Page'),
-            ),
-            ElevatedButton(
-              onPressed: () {
-               GlobalWebPage.startInstance(context: context, title: "baidu", url: "https://www.baidu.com");
-              },
-              child: const Text('Go to Global Web Page'),
-            ),
-          ],
+      appBar: MyAppBar.appBar(
+        context,
+        "",
+        showBackButton: false,
+        backgroundColor: context.appColors.btnBgDefault,
+        systemUiOverlayStyle: ThemeConfig.systemUiOverlayStyleLightThemeWhite,
+      ),
+      backgroundColor: context.appColors.backgroundDark,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: SizedBox(
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              //顶部信息
+              _buildTopProfile(context, ref),
+
+              //关注与粉丝
+              _buildFollower(context, ref),
+
+              //我的发布
+              SettingItemContainer(
+                title: S.current.my_post,
+                iconPath: Assets.mainMeMyPostIcon,
+                isShowMoreIcon: true,
+                rightWidget: MyTextView(
+                  "265",
+                  textColor: context.appColors.textPrimary,
+                  fontSize: 20,
+                  isFontMedium: true,
+                ),
+              ).onTap(viewModel.gotoMyPostPage).marginOnly(top: 10),
+
+              //家庭
+              SettingItemContainer(
+                title: S.current.household,
+                iconPath: Assets.mainMeHouseholdIcon,
+                isShowMoreIcon: true,
+                rightWidget: MyTextView(
+                  "2",
+                  textColor: context.appColors.textPrimary,
+                  fontSize: 20,
+                  isFontMedium: true,
+                ),
+              ).onTap(viewModel.gotoMyHouseholdPage),
+
+              //房产
+              SettingItemContainer(
+                title: S.current.estate,
+                iconPath: Assets.mainMeEstateIcon,
+                isShowMoreIcon: true,
+                rightWidget: MyTextView(
+                  "2",
+                  textColor: context.appColors.textPrimary,
+                  fontSize: 20,
+                  isFontMedium: true,
+                ),
+              ).onTap(viewModel.gotoMyEstatePage),
+
+              //设置
+              SettingItemContainer(
+                title: S.current.settings,
+                iconPath: Assets.mainMeSettingIcon,
+                isShowMoreIcon: true,
+              ).onTap(viewModel.gotoSettingPage),
+
+            ],
+          ),
         ),
       ),
     );
   }
+
+  //编辑顶部的关注与粉丝数量
+  Widget _buildFollower(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(meViewModelProvider.notifier);
+    return Container(
+      color: context.appColors.whiteSecondBG,
+      width: double.infinity,
+      height: 50,
+      child: Row(
+        children: [
+          //关注
+          Row(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                S.current.following,
+                isFontBold: true,
+                fontSize: 16,
+                textColor: context.appColors.textBlack,
+              ),
+              MyTextView(
+                "(26)",
+                isFontBold: true,
+                fontSize: 16,
+                textColor: context.appColors.textPrimary,
+              ),
+            ],
+          ).onTap(viewModel.gotoFollowingPage).expanded(),
+
+          Container(
+            width: 0.5,
+            height: 50,
+            color: context.appColors.dividerDefault,
+          ),
+          //粉丝
+          Row(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              MyTextView(
+                S.current.followers,
+                isFontBold: true,
+                fontSize: 16,
+                textColor: context.appColors.textBlack,
+              ),
+              MyTextView(
+                "(12)",
+                isFontBold: true,
+                fontSize: 16,
+                textColor: context.appColors.textPrimary,
+              ),
+            ],
+          ).onTap(viewModel.gotoFollowerPage).expanded(),
+        ],
+      ),
+    );
+  }
+
+  // 编辑顶部的个人信息
+  Widget _buildTopProfile(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(meViewModelProvider.notifier);
+    return Container(
+      color: context.appColors.btnBgDefault,
+      width: double.infinity,
+      padding: const EdgeInsets.only(left: 26, right: 20, top: 5),
+      height: 120,
+      child: Row(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyLoadImage(
+            "https://img1.baidu.com/it/u=1656098746,3560654086&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=800",
+            width: 80,
+            height: 80,
+            isCircle: true,
+          ),
+          Column(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Row(
+                children: [
+                  MyTextView(
+                    "Wu Bing Bing",
+                    textColor: Colors.white,
+                    fontSize: 18,
+                    isFontMedium: true,
+                  ).expanded(),
+                  const MyAssetImage(
+                    Assets.mainMeEditIcon,
+                    width: 20.5,
+                    height: 20,
+                  ).onTap(viewModel.gotoEditProfilePage, padding: 5),
+                ],
+              ),
+
+              //电话
+              MyTextView(
+                "+86 12345678901",
+                textColor: Colors.white,
+                fontSize: 15,
+                isFontRegular: true,
+              ),
+
+              //住宅
+              MyTextView(
+                "Owner135 #08-29",
+                marginTop: 12,
+                textColor: Colors.white,
+                fontSize: 15,
+                isFontRegular: true,
+              ),
+            ],
+          ).marginOnly(left: 11).expanded(),
+        ],
+      ),
+    );
+  }
 }

+ 46 - 0
packages/cpt_main/lib/modules/me/me_view_model.dart

@@ -0,0 +1,46 @@
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:router/componentRouter/component_service_manager.dart';
+
+part 'me_view_model.g.dart';
+
+@riverpod
+class MeViewModel extends _$MeViewModel {
+  @override
+  void build() {}
+
+  //去我的房产页面
+  void gotoMyEstatePage() {
+    ToastEngine.show("去我的房产页面");
+  }
+
+  //去我的家庭成员页面
+  void gotoMyHouseholdPage() {
+    ToastEngine.show("去我的家庭成员页面");
+  }
+
+  //去我的发布页面
+  void gotoMyPostPage() {
+    ToastEngine.show("去我的发布页面");
+  }
+
+  //去设置页面
+  void gotoSettingPage() {
+    ComponentServiceManager().profileService.startSettingPage();
+  }
+
+  //我的关注Tab
+  void gotoFollowingPage() {
+    ToastEngine.show("我的关注Tab");
+  }
+
+  //我的粉丝Tab
+  void gotoFollowerPage() {
+    ToastEngine.show("我的粉丝Tab");
+  }
+
+  //编辑附加信息
+  void gotoEditProfilePage() {
+    ToastEngine.show("编辑附加信息");
+  }
+}

+ 25 - 0
packages/cpt_main/lib/modules/me/me_view_model.g.dart

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

+ 99 - 0
packages/cpt_main/lib/modules/notification/item_notification.dart

@@ -0,0 +1,99 @@
+import 'package:cpt_main/modules/demo_page.dart';
+import 'package:cpt_main/modules/notification/notification_group_data.dart';
+import 'package:cs_resources/generated/assets.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';
+
+class NotificationItem extends StatelessWidget {
+  final String item;
+  final int index;
+
+  const NotificationItem({
+    required this.item,
+    required this.index,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      color: context.appColors.whiteBG,
+      padding: const EdgeInsets.only(left: 11, right: 15, top: 10.5),
+      child: Column(
+        children: [
+          Row(
+            children: [
+              const MyAssetImage(Assets.mainNotificationItemIcon, width: 42.5, height: 42.5).marginOnly(right: 16),
+              Column(
+                children: [
+                  //标题
+                  Row(
+                    crossAxisAlignment: CrossAxisAlignment.center,
+                    children: [
+                      //未读的小圆点
+                      Container(
+                        width: 6,
+                        height: 6,
+                        margin: const EdgeInsets.only(right: 8.5),
+                        decoration: BoxDecoration(
+                          shape: BoxShape.circle,
+                          color: context.appColors.tabBgSelectedPrimary,
+                        ),
+                      ),
+
+                      //消息标题
+                      MyTextView(
+                        "NEW ANNOUNCEMENT",
+                        fontSize: 16,
+                        isFontBold: true,
+                        textColor: context.appColors.textBlack,
+                        maxLines: 2,
+                      ).expanded(),
+
+                      //消息时间
+                      MyTextView(
+                        "10:19 AM",
+                        fontSize: 13,
+                        isFontRegular: true,
+                        textColor: context.appColors.textLightPurple,
+                      ),
+                    ],
+                  ),
+
+                  //内容
+                  Row(
+                    children: [
+                      //文本内容
+                      MyTextView(
+                        "Standard operating procedure for replacement vehicles andover night parking vehicles.",
+                        fontSize: 15,
+                        marginRight: 15,
+                        isFontRegular: true,
+                        textColor: context.appColors.textBlack,
+                      ).expanded(),
+
+                      //图片
+                      MyLoadImage(
+                        "https://img1.baidu.com/it/u=1656098746,3560654086&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=800",
+                        width: 87.5,
+                        height: 60.5,
+                      ),
+                    ],
+                  ).marginOnly(top: 9),
+                ],
+              ).expanded(),
+            ],
+          ),
+          const SizedBox(height: 17.5),
+          Divider(
+            height: 0.5,
+            color: context.appColors.backgroundDark,
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 26 - 0
packages/cpt_main/lib/modules/notification/item_notification_header.dart

@@ -0,0 +1,26 @@
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:widgets/my_text_view.dart';
+
+class NotificationItemHeader extends StatelessWidget {
+  String? groupId;
+
+  NotificationItemHeader(this.groupId);
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      color: context.appColors.backgroundDark,
+      padding: const EdgeInsets.symmetric(horizontal: 14),
+      child: MyTextView(
+        groupId ?? "-",
+        fontSize: 14,
+        paddingTop: 8,
+        paddingBottom: 8,
+        isFontMedium: true,
+        textColor: context.appColors.textBlack,
+      ),
+    );
+  }
+}

+ 6 - 0
packages/cpt_main/lib/modules/notification/notification_group_data.dart

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

+ 78 - 7
packages/cpt_main/lib/modules/notification/notification_page.dart

@@ -1,11 +1,23 @@
+import 'package:cpt_main/modules/notification/item_notification_header.dart';
 import 'package:cpt_main/router/page/main_page_router.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:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
 
-@RoutePage()
-class NotificationPage extends StatelessWidget {
+import 'item_notification.dart';
+import 'notification_view_model.dart';
 
+@RoutePage()
+class NotificationPage extends HookConsumerWidget {
   const NotificationPage({Key? key}) : super(key: key);
 
   static void startInstance({BuildContext? context}) {
@@ -17,12 +29,71 @@ class NotificationPage extends StatelessWidget {
   }
 
   @override
-  Widget build(BuildContext context) {
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(notificationViewModelProvider.notifier);
+    final state = ref.watch(notificationViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
     return Scaffold(
-      appBar: AppBar(title: Text("NotificationPage")),
-      body: Center(
-        child: Text("Notification Page"),
+      appBar: MyAppBar.appBar(context, S.current.notification,
+          backgroundColor: context.appColors.whiteBG,
+          actions: [
+            Center(
+                child: MyTextView(
+              S.current.mark_all,
+              fontSize: 16,
+              textColor: context.appColors.textPrimary,
+              onClick: viewModel.markAll,
+              isFontRegular: true,
+              marginRight: 15,
+            )),
+          ],
+          showBottomDivider: false),
+      backgroundColor: context.appColors.whiteBG,
+      body: SizedBox(
+        width: double.infinity,
+        height: double.infinity,
+        child: EasyRefresh(
+          controller: viewModel.refreshController,
+          onRefresh: viewModel.onRefresh,
+          onLoad: viewModel.loadMore,
+          child: LoadStateLayout(
+            state: state.loadingState,
+            errorMessage: state.errorMessage,
+            errorRetry: () {
+              viewModel.retryRequest();
+            },
+            successSliverWidget: [
+              SliverList(
+                  delegate: SliverChildBuilderDelegate(
+                (context, index) {
+                  return StickyHeader(
+                    header: NotificationItemHeader(state.datas[index].groupId),
+                    content: Column(
+                      children: _buildGroup(state.datas[index].groupDatas!, index),
+                    ),
+                  );
+                },
+                childCount: state.datas.length,
+              ))
+            ],
+          ),
+        ),
       ),
     );
   }
-}
+
+  //当前组内的子数据
+  _buildGroup(List<String> list, int index) {
+    return list.map((item) {
+      return NotificationItem(item: item, index: index);
+    }).toList();
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/notification/notification_state.dart

@@ -0,0 +1,31 @@
+import 'package:cpt_main/modules/notification/notification_group_data.dart';
+import 'package:widgets/load_state_layout.dart';
+
+class NotificationState {
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<NotificationGroupData> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  NotificationState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  NotificationState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<NotificationGroupData>? datas,
+  }) {
+    return NotificationState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 160 - 0
packages/cpt_main/lib/modules/notification/notification_view_model.dart

@@ -0,0 +1,160 @@
+import 'package:cpt_main/modules/notification/notification_group_data.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'notification_state.dart';
+
+part 'notification_view_model.g.dart';
+
+@riverpod
+class NotificationViewModel extends _$NotificationViewModel {
+  @override
+  NotificationState build() {
+    return NotificationState(datas: []);
+  }
+
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
+  );
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    List<NotificationGroupData> list = [];
+    if (_curPage > 1) {
+
+      //这里只加载一页吧
+    } else {
+
+      list.add(NotificationGroupData()
+        ..groupId = "Toady"
+        ..groupDatas = ["1", "2", "3", "4"]);
+
+      list.add(NotificationGroupData()
+        ..groupId = "Friday 11 oct 2024"
+        ..groupDatas = ["1", "2", "3"]);
+
+      list.add(NotificationGroupData()
+        ..groupId = "Thursday 10 oct 2024"
+        ..groupDatas = ["1", "2"]);
+
+      list.add(NotificationGroupData()
+        ..groupId = "Wednesday 9 oct 2024"
+        ..groupDatas = ["1"]);
+
+    }
+
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      // refreshController.finishLoad();
+      refreshController.finishLoad(IndicatorResult.noMore);
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+
+  /// 点击标记全部
+  void markAll() {
+    ToastEngine.show("点击标记全部");
+  }
+
+}

+ 27 - 0
packages/cpt_main/lib/modules/notification/notification_view_model.g.dart

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

+ 56 - 0
packages/cpt_main/lib/modules/visitor/active/visitor_active.dart

@@ -0,0 +1,56 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:cpt_main/modules/visitor/item_visitor.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'visitor_active_view_model.dart';
+
+@RoutePage()
+class VisitorActiveScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(visitorActiveViewModelProvider.notifier);
+    final state = ref.watch(visitorActiveViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchAppliedStaffList());
+      return () {
+        // 组件卸载时执行
+        Log.d("VisitorActiveScreen 组件卸载时执行");
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+              (context, index) {
+                return VisitorItem(index: index, item: state.datas[index]);
+              },
+              childCount: state.datas.length,
+            ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/visitor/active/visitor_active_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class VisitorActiveState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  VisitorActiveState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  VisitorActiveState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return VisitorActiveState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 133 - 0
packages/cpt_main/lib/modules/visitor/active/visitor_active_view_model.dart

@@ -0,0 +1,133 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'visitor_active_state.dart';
+
+part 'visitor_active_view_model.g.dart';
+
+@riverpod
+class VisitorActiveViewModel extends _$VisitorActiveViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  VisitorActiveState build() {
+    final state = VisitorActiveState(datas: []);
+    //初始化默认调用接口
+    Log.d("VisitorActiveViewModel 执行build");
+    return state;
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchAppliedStaffList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchAppliedStaffList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchAppliedStaffList();
+  }
+
+  /// 获取服务器数据
+  Future fetchAppliedStaffList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 27 - 0
packages/cpt_main/lib/modules/visitor/active/visitor_active_view_model.g.dart

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

+ 55 - 0
packages/cpt_main/lib/modules/visitor/history/visitor_history.dart

@@ -0,0 +1,55 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../item_visitor.dart';
+import 'visitor_history_view_model.dart';
+
+@RoutePage()
+class VisitorHistoryScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(visitorHistoryViewModelProvider.notifier);
+    final state = ref.watch(visitorHistoryViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+        Log.d("VisitorHistoryScreen 组件卸载时执行");
+      };
+    }, []);
+
+    return Container(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        onLoad: viewModel.loadMore,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+                      (context, index) {
+                    return VisitorItem(index: index, item: state.datas[index]);
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_main/lib/modules/visitor/history/visitor_history_state.dart

@@ -0,0 +1,31 @@
+import 'package:widgets/load_state_layout.dart';
+
+class VisitorHistoryState {
+
+  //页面 LoadView 状态的展示
+  LoadState loadingState;
+  String? errorMessage;
+
+  List<String> datas; //页面列表数据
+
+  // ===================================  Begin  ↓  ===================================
+
+  VisitorHistoryState({
+    this.loadingState = LoadState.State_Loading,
+    this.errorMessage,
+    required this.datas,
+  });
+
+  VisitorHistoryState copyWith({
+    LoadState? loadingState,
+    String? errorMessage,
+    bool? needShowPlaceholder,
+    List<String>? datas,
+  }) {
+    return VisitorHistoryState(
+      errorMessage: errorMessage ?? this.errorMessage,
+      loadingState: loadingState ?? this.loadingState,
+      datas: datas ?? this.datas,
+    );
+  }
+}

+ 133 - 0
packages/cpt_main/lib/modules/visitor/history/visitor_history_view_model.dart

@@ -0,0 +1,133 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import 'visitor_history_state.dart';
+
+part 'visitor_history_view_model.g.dart';
+
+@riverpod
+class VisitorHistoryViewModel extends _$VisitorHistoryViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  VisitorHistoryState build() {
+    final state = VisitorHistoryState(datas: []);
+    //初始化默认调用接口
+    Log.d("VisitorActiveViewModel 执行build");
+    return state;
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    fetchList();
+  }
+
+  // Refresh 加载事件
+  Future loadMore() async {
+    _curPage++;
+    fetchList();
+  }
+
+  // 重试请求
+  Future retryRequest() async {
+    _curPage = 1;
+    _needShowPlaceholder = true;
+    fetchList();
+  }
+
+  /// 获取服务器数据
+  Future fetchList() async {
+    if (_needShowPlaceholder) {
+      changeLoadingState(LoadState.State_Loading, null);
+    }
+
+    // 获取 Applied 列表
+    // var listResult = await _jobRepository.fetchJobAppliedList(
+    //   state.jobId,
+    //   state.selectedStatusId,
+    //   state.keyword,
+    //   curPage: _curPage,
+    //   cancelToken: cancelToken,
+    // );
+    //
+    // // 处理数据
+    // if (listResult.isSuccess) {
+    //   handleList(listResult.data?.rows);
+    // } else {
+    //   errorMessage = listResult.errorMsg;
+    //   changeLoadingState(LoadState.State_Error);
+    // }
+
+
+    await Future.delayed(const Duration(milliseconds: 1500));
+
+    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
+
+    if (_curPage == 1) {
+      //刷新的方式
+      state = state.copyWith(datas: list);
+      refreshController.finishRefresh();
+
+      //更新展示的状态
+      changeLoadingState(LoadState.State_Success, null);
+    } else {
+      //加载更多
+      final allList = state.datas;
+      allList.addAll(list);
+      state.datas.addAll(list);
+
+      refreshController.finishLoad();
+
+      state = state.copyWith(datas: allList);
+    }
+
+    // 最后赋值
+    _needShowPlaceholder = false;
+  }
+
+// 处理数据与展示的逻辑
+// void handleList(List<JobAppliedListSGRows>? list) {
+//   if (list != null && list.isNotEmpty) {
+//     //有数据,判断是刷新还是加载更多的数据
+//     if (_curPage == 1) {
+//       //刷新的方式
+//       state.datas.clear();
+//       state.datas.addAll(list);
+//       refreshController.finishRefresh();
+//
+//       //更新展示的状态
+//       changeLoadingState(LoadState.State_Success);
+//     } else {
+//       //加载更多
+//       state.datas.addAll(list);
+//       refreshController.finishLoad();
+//       update();
+//     }
+//   } else {
+//     if (_curPage == 1) {
+//       //展示无数据的布局
+//       state.datas.clear();
+//       changeLoadingState(LoadState.State_Empty);
+//       refreshController.finishRefresh();
+//     } else {
+//       //展示加载完成,没有更多数据了
+//       refreshController.finishLoad(IndicatorResult.noMore);
+//     }
+//   }
+// }
+}

+ 0 - 0
packages/cpt_main/lib/modules/visitor/history/visitor_history_view_model.g.dart


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels