Przeglądaj źródła

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

“shanwenxin” 4 dni temu
rodzic
commit
7b6936683b
100 zmienionych plików z 6545 dodań i 1387 usunięć
  1. 5 0
      packages/cpt_auth/lib/router/component/auth_component_service.dart
  2. 69 0
      packages/cpt_community/lib/components/garage_card_content.dart
  3. 111 0
      packages/cpt_community/lib/components/garage_card_footer.dart
  4. 149 0
      packages/cpt_community/lib/components/garage_card_header.dart
  5. 1 1
      packages/cpt_community/lib/components/newfeed_card_header.dart
  6. 63 39
      packages/cpt_community/lib/components/newsfeed_card_footer.dart
  7. 185 73
      packages/cpt_community/lib/modules/community/community_page.dart
  8. 10 15
      packages/cpt_community/lib/modules/community/community_state.dart
  9. 37 27
      packages/cpt_community/lib/modules/community/community_vm.dart
  10. 1 1
      packages/cpt_community/lib/modules/community/community_vm.g.dart
  11. 24 0
      packages/cpt_community/lib/modules/community/customSilverHeaderTabs.dart
  12. 48 0
      packages/cpt_community/lib/modules/community/following/following_page.dart
  13. 35 0
      packages/cpt_community/lib/modules/community/following/following_state.dart
  14. 110 0
      packages/cpt_community/lib/modules/community/following/following_vm.dart
  15. 25 0
      packages/cpt_community/lib/modules/community/following/following_vm.g.dart
  16. 79 0
      packages/cpt_community/lib/modules/community/foryou/foryou_page.dart
  17. 9 9
      packages/cpt_community/lib/modules/newsfeed/newsfeed_repository.dart
  18. 9 10
      packages/cpt_community/lib/modules/newsfeed/newsfeed_repository.g.dart
  19. 57 0
      packages/cpt_community/lib/modules/community/foryou/foryou_state.dart
  20. 196 0
      packages/cpt_community/lib/modules/community/foryou/foryou_vm.dart
  21. 25 0
      packages/cpt_community/lib/modules/community/foryou/foryou_vm.g.dart
  22. 169 0
      packages/cpt_community/lib/modules/community/news/news_page.dart
  23. 9 9
      packages/cpt_community/lib/modules/garagesale/garagesale_repository.dart
  24. 9 10
      packages/cpt_community/lib/modules/garagesale/garagesale_repository.g.dart
  25. 57 0
      packages/cpt_community/lib/modules/community/news/news_state.dart
  26. 196 208
      packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.dart
  27. 9 10
      packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.g.dart
  28. 188 0
      packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_page.dart
  29. 27 0
      packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_state.dart
  30. 60 0
      packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_vm.dart
  31. 26 0
      packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_vm.g.dart
  32. 0 0
      packages/cpt_community/lib/modules/community/newsfeed_myposts/newsfeed_myposts_page.dart
  33. 247 0
      packages/cpt_community/lib/modules/community/newsfeed_post/newsfeed_post_page.dart
  34. 38 0
      packages/cpt_community/lib/modules/community/newsfeed_post/newsfeed_post_page_state.dart
  35. 159 0
      packages/cpt_community/lib/modules/community/newsfeed_post/newsfeed_post_vm.dart
  36. 1 1
      packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_vm.g.dart
  37. 39 33
      packages/cpt_community/lib/modules/newsfeed/newsfeed_tabs.dart
  38. 80 0
      packages/cpt_community/lib/modules/garage/for_rent/for_rent_page.dart
  39. 71 0
      packages/cpt_community/lib/modules/garage/for_rent/for_rent_respository.dart
  40. 27 0
      packages/cpt_community/lib/modules/garage/for_rent/for_rent_respository.g.dart
  41. 57 0
      packages/cpt_community/lib/modules/garage/for_rent/for_rent_state.dart
  42. 196 0
      packages/cpt_community/lib/modules/garage/for_rent/for_rent_vm.dart
  43. 25 0
      packages/cpt_community/lib/modules/garage/for_rent/for_rent_vm.g.dart
  44. 138 0
      packages/cpt_community/lib/modules/garage/for_sale/for_sale_page.dart
  45. 71 0
      packages/cpt_community/lib/modules/garage/for_sale/for_sale_respository.dart
  46. 27 0
      packages/cpt_community/lib/modules/garage/for_sale/for_sale_respository.g.dart
  47. 57 0
      packages/cpt_community/lib/modules/garage/for_sale/for_sale_state.dart
  48. 185 0
      packages/cpt_community/lib/modules/garage/for_sale/for_sale_vm.dart
  49. 25 0
      packages/cpt_community/lib/modules/garage/for_sale/for_sale_vm.g.dart
  50. 278 0
      packages/cpt_community/lib/modules/garage/garage_page.dart
  51. 71 0
      packages/cpt_community/lib/modules/garage/garage_repository.dart
  52. 27 0
      packages/cpt_community/lib/modules/garage/garage_repository.g.dart
  53. 19 21
      packages/cpt_community/lib/modules/garagesale/garagesale_state.dart
  54. 17 17
      packages/cpt_community/lib/modules/garagesale/garagesale_tabs.dart
  55. 43 21
      packages/cpt_community/lib/modules/garagesale/garagesale_vm.dart
  56. 10 10
      packages/cpt_community/lib/modules/garagesale/garagesale_vm.g.dart
  57. 8 5
      packages/cpt_community/lib/modules/garagesale/garagesale_detail/garagesale_detail_page.dart
  58. 0 0
      packages/cpt_community/lib/modules/garage/garagesale_myposts/garagesale_myposts_page.dart
  59. 317 0
      packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_page.dart
  60. 91 0
      packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_state.dart
  61. 219 0
      packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_vm.dart
  62. 26 0
      packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_vm.g.dart
  63. 0 224
      packages/cpt_community/lib/modules/garagesale/garagesale_page.dart
  64. 0 38
      packages/cpt_community/lib/modules/garagesale/garagesale_post/garagesale_post_page.dart
  65. 0 38
      packages/cpt_community/lib/modules/newsfeed/newsfeed_detail/newsfeed_detail_page.dart
  66. 0 226
      packages/cpt_community/lib/modules/newsfeed/newsfeed_page.dart
  67. 0 155
      packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_page.dart
  68. 0 8
      packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_page_state.dart
  69. 0 47
      packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_vm.dart
  70. 0 69
      packages/cpt_community/lib/modules/newsfeed/newsfeed_state.dart
  71. 54 18
      packages/cpt_community/lib/router/page/community_page_router.dart
  72. 194 44
      packages/cpt_community/lib/router/page/community_page_router.gr.dart
  73. 66 0
      packages/cpt_facility/lib/modules/booking/facility_booking_page.dart
  74. 3 0
      packages/cpt_facility/lib/modules/booking/facility_booking_state.dart
  75. 13 0
      packages/cpt_facility/lib/modules/booking/facility_booking_view_model.dart
  76. 27 0
      packages/cpt_facility/lib/modules/booking/facility_booking_view_model.g.dart
  77. 308 0
      packages/cpt_facility/lib/modules/detail/facility_detail_page.dart
  78. 3 0
      packages/cpt_facility/lib/modules/detail/facility_detail_state.dart
  79. 13 0
      packages/cpt_facility/lib/modules/detail/facility_detail_view_model.dart
  80. 27 0
      packages/cpt_facility/lib/modules/detail/facility_detail_view_model.g.dart
  81. 57 0
      packages/cpt_facility/lib/modules/facility/active/facility_active_screen.dart
  82. 31 0
      packages/cpt_facility/lib/modules/facility/active/facility_active_state.dart
  83. 130 0
      packages/cpt_facility/lib/modules/facility/active/facility_active_view_model.dart
  84. 27 0
      packages/cpt_facility/lib/modules/facility/active/facility_active_view_model.g.dart
  85. 136 0
      packages/cpt_facility/lib/modules/facility/active/item_facility_active.dart
  86. 56 0
      packages/cpt_facility/lib/modules/facility/book/facility_book_screen.dart
  87. 31 0
      packages/cpt_facility/lib/modules/facility/book/facility_book_state.dart
  88. 130 0
      packages/cpt_facility/lib/modules/facility/book/facility_book_view_model.dart
  89. 27 0
      packages/cpt_facility/lib/modules/facility/book/facility_book_view_model.g.dart
  90. 48 0
      packages/cpt_facility/lib/modules/facility/book/item_facility_book.dart
  91. 147 0
      packages/cpt_facility/lib/modules/facility/deposit/facility_deposit_screen.dart
  92. 31 0
      packages/cpt_facility/lib/modules/facility/deposit/facility_deposit_state.dart
  93. 125 0
      packages/cpt_facility/lib/modules/facility/deposit/facility_deposit_view_model.dart
  94. 27 0
      packages/cpt_facility/lib/modules/facility/deposit/facility_deposit_view_model.g.dart
  95. 55 0
      packages/cpt_facility/lib/modules/facility/deposit/item_facility_deposit.dart
  96. 156 0
      packages/cpt_facility/lib/modules/facility/facility_page.dart
  97. 0 0
      packages/cpt_facility/lib/modules/facility/facility_view_model.dart
  98. 0 0
      packages/cpt_facility/lib/modules/facility/facility_view_model.g.dart
  99. 56 0
      packages/cpt_facility/lib/modules/facility/history/facility_history_screen.dart
  100. 0 0
      packages/cpt_facility/lib/modules/facility/history/facility_history_state.dart

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

@@ -25,4 +25,9 @@ class AuthComponentService extends AuthService {
   void startResetPasswordPage() {
     SelectEstatePage.startInstance();
   }
+
+  @override
+  void startSelectEstatePage() {
+    SelectEstatePage.startInstance();
+  }
 }

+ 69 - 0
packages/cpt_community/lib/components/garage_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 GarageCardContent extends StatelessWidget {
+  const GarageCardContent({
+    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"),
+                        ),
+                      )
+                  ],
+                ),
+              )
+          ]
+      ),
+    );
+  }
+}

+ 111 - 0
packages/cpt_community/lib/components/garage_card_footer.dart

@@ -0,0 +1,111 @@
+import 'package:cpt_community/components/newfeed_card_header.dart';
+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: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';
+
+// '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 GarageCardFooter extends StatelessWidget {
+  final bool isLike;
+  final VoidCallback? onLike;
+  final VoidCallback? onComment;
+  final VoidCallback? onShare;
+
+  const GarageCardFooter({
+    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: [
+                Container(
+                  height: 40,
+                  padding: const EdgeInsets.all(8),
+                  child: 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,
+                      ),
+                    ],
+                  ),
+                ).onTap((){
+                  Log.d("点击了like");
+                  onLike?.call();
+                }),
+                Container(
+                  height: 40,
+                  padding: const EdgeInsets.all(8),
+                  child: 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,
+                      ),
+                    ],
+                  ),
+                ).onTap((){
+                  Log.d("点击了comments");
+                  onComment?.call();
+                }),
+                Container(
+                  height: 40,
+                  padding: const EdgeInsets.all(8),
+                  child: 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,
+                      ),
+                    ],
+                  ),
+                ).onTap((){
+                  Log.d("点击了share");
+                  onShare?.call();
+                }),
+              ]
+          ),
+        )
+    );
+  }
+}

+ 149 - 0
packages/cpt_community/lib/components/garage_card_header.dart

@@ -0,0 +1,149 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.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 '../modules/garage/for_sale/for_sale_vm.dart';
+
+// 'id':1,
+// 'goods_img':  'https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg',
+// 'title': 'Electronic keyboard',
+// 'price': '\$66',
+// 'isCollection': true,
+// 'collection_num': '12',
+// 'publisher': 'William Jefferson',
+// 'publish_time': 'June 17,2016 at 7:23 p.m.',
+// 'publisher_avator': Assets.communityCamera,'
+
+
+
+
+
+class GarageCardHeader extends StatelessWidget {
+  Map<String, dynamic> itemObj;
+  final Function()? onTap;
+
+  GarageCardHeader({
+    Key? key,
+    required this.itemObj,
+    this.onTap,
+  }) : super(key: key);
+
+
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Row(
+          mainAxisAlignment: MainAxisAlignment.center,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            Expanded(
+              child: MyLoadImage(
+                itemObj['goods_img'],
+                width: 166.5,
+                height: 102.5,
+                isCircle: false,
+                fit: BoxFit.cover,
+              ).onTap(() {
+                // 点击头像
+                // onTap?.call();
+              }),
+            ),
+          ],
+        ),
+        Row(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            Expanded(
+              child: MyTextView(
+                itemObj['title'],
+                maxLines: 1,
+                isTextEllipsis: true,
+                textAlign: TextAlign.center,
+                textColor: context.appColors.textBlack,
+                fontSize: 16,
+                isFontRegular: true,
+                marginLeft: 12,
+                marginRight: 12,
+              ),
+            ),
+          ],
+        ),
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceAround,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            Expanded(
+              child: MyTextView(
+                itemObj['price'],
+                maxLines: 1,
+                isTextEllipsis: true,
+                textAlign: TextAlign.start,
+                textColor: ColorUtils.string2Color('#4161D0'),
+                fontSize: 18,
+                isFontMedium: true,
+              ),
+            ),
+            // 动态的 收藏数
+            CollectionWidget(collectionNum: itemObj['collection_num'], isCollection: itemObj['isCollection']),
+          ],
+        ),
+      ],
+    );
+  }
+}
+
+
+
+class CollectionWidget extends HookConsumerWidget {
+  int collectionNum = 0;
+  bool isCollection = false;
+  CollectionWidget({
+    Key? key,
+    required this.collectionNum,
+    required this.isCollection,
+  }) : super(key: key);
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final collectionNumState = useState(collectionNum);
+    final isCollectionState = useState(isCollection);
+
+    return Container(
+      width: 60,
+      height: 30,
+      alignment: Alignment.center,
+      decoration: BoxDecoration(
+        color: ColorUtils.string2Color('#E5E5E5'),
+        borderRadius: BorderRadius.circular(15),
+      ),
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          MyTextView(
+            '${collectionNumState.value}',
+            textColor: ColorUtils.string2Color('#999999'),
+            fontSize: 14,
+            isFontRegular: true,
+          ),
+          MyLoadImage(
+            isCollectionState.value? Assets.communityLikeActive: Assets.communityLike,
+            width: 14,
+            height: 14,
+          )
+        ]
+      ).onTap((){
+        // 点击 收餐/取消收藏
+        Log.d("点击了收藏按钮");
+      })
+    );
+  }
+}

+ 1 - 1
packages/cpt_community/lib/components/newfeed_card_header.dart

@@ -33,7 +33,7 @@ class NewsFeedCardHeader extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return Container(
-      padding: const EdgeInsets.symmetric(horizontal: 16),
+      padding: const EdgeInsets.only(left: 16,right: 60),
       child: Row(
         mainAxisAlignment: MainAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.start,

+ 63 - 39
packages/cpt_community/lib/components/newsfeed_card_footer.dart

@@ -1,7 +1,10 @@
+import 'package:cpt_community/components/newfeed_card_header.dart';
 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: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';
 
@@ -40,45 +43,66 @@ class NewsFeedCardFooter extends StatelessWidget {
         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,
-                ),
-              ],
-            ),
+            Container(
+              height: 40,
+              padding: const EdgeInsets.all(8),
+              child: 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,
+                  ),
+                ],
+              ),
+            ).onTap((){
+              Log.d("点击了like");
+              onLike?.call();
+            }),
+            Container(
+              height: 40,
+              padding: const EdgeInsets.all(8),
+              child: 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,
+                  ),
+                ],
+              ),
+            ).onTap((){
+              Log.d("点击了comments");
+              onComment?.call();
+            }),
+            Container(
+              height: 40,
+              padding: const EdgeInsets.all(8),
+              child: 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,
+                  ),
+                ],
+              ),
+            ).onTap((){
+              Log.d("点击了share");
+              onShare?.call();
+            }),
           ]
         ),
       )

+ 185 - 73
packages/cpt_community/lib/modules/community/community_page.dart

@@ -1,4 +1,5 @@
 
+import 'package:cs_resources/generated/assets.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter/rendering.dart';
@@ -15,7 +16,9 @@ import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:widgets/widget_export.dart';
 
 import '../../router/page/community_page_router.dart';
+import 'newsfeed_tabs.dart';
 import 'community_vm.dart';
+import 'customSilverHeaderTabs.dart';
 
 @RoutePage()
 class CommunityPage extends HookConsumerWidget {
@@ -30,12 +33,125 @@ class CommunityPage extends HookConsumerWidget {
       }
     }
 
+    bool _isPreventScroll(ScrollNotification notification, WidgetRef ref){
+      // 检查当前页面是否是可见的
+      bool isDownOrUp = notification.metrics.axis == Axis.vertical;
+      if (notification is UserScrollNotification) {
+        // 检查滚动方向
+        switch (notification.direction) {
+          case ScrollDirection.forward:
+            print('Scrolling down');
+            break;
+          case ScrollDirection.reverse:
+            print('Scrolling up');
+            break;
+          case ScrollDirection.idle:
+            print('Scrolling stopped');
+            break;
+        }
+      } else if (notification is ScrollUpdateNotification) {
+        // 检查滚动位置变化
+        double currentScrollPosition = notification.metrics.pixels;
+        double maxScrollExtent = notification.metrics.maxScrollExtent;
 
-     Widget _buildTopSection(BuildContext context, WidgetRef ref, vm, tabsRouter) {
+        // 判断是否满足某个条件
+        if (currentScrollPosition > 0 && currentScrollPosition < maxScrollExtent) {
+          print('Current scroll position: $currentScrollPosition');
+          // 在这里添加你的条件判断逻辑
+        }
+
+        // 只有当上下滚动时才拦截通知
+        if (isDownOrUp) {
+          final tabsRouter = ref.watch(communityVmProvider).tabsRouter;
+        }
+      }
+      return false;
+    }
+
+    @override
+    Widget build(BuildContext context, WidgetRef ref) {
+        final vm = ref.read(communityVmProvider.notifier);
+        final state = ref.watch(communityVmProvider);
+        final stateTabsRouter = ref.watch(communityVmProvider).tabsRouter;
+        // final state = ref.watch(communityVmProvider);
+        BuildContext contextPage = context;
+        // 创建 GlobalKey
+        final _tabsRouterKey = GlobalKey<AutoTabsRouterState>();
+
+        // useEffect((){
+        //   Log.d("CommunityPage initState");
+        //   return () {
+        //     Log.d("CommunityPage dispose");
+        //   };
+        // },[]);
+
+        return Scaffold(
+            appBar: MyAppBar.appBar(
+              context,
+              "Community",
+              backgroundColor: context.appColors.whiteBG,
+            ),
+            backgroundColor: context.appColors.backgroundDefault,
+            body:  NestedScrollView(
+              headerSliverBuilder: (context, innerBoxIsScrolled) {
+                return [
+                  SliverToBoxAdapter(
+                      child: Consumer(
+                        builder: (context, ref, _) {
+                          return _buildTopSection(context, ref, vm);
+                        },
+                      ),
+                  ),
+                  // SliverPersistentHeader(
+                  //   pinned: true, // 吸顶
+                  //   delegate: CustomSliverPersistentHeaderDelegate(
+                  //     child: _buildTabsSection(contextPage, ref),
+                  //   ),
+                  // ),
+                ];
+              },
+              body: NotificationListener<ScrollNotification>(
+                onNotification: (ScrollNotification notification) {
+                  // 是否拦截滚动  false 表示不拦截通知
+                  // return _isPreventScroll(notification, ref);
+                  return false;
+                },
+                child: AutoTabsRouter.pageView(
+                  key: _tabsRouterKey,
+                  routes: const [
+                    NewsPageRoute(),
+                    FollowingPageRoute(),
+                    ForyouPageRoute()
+                  ],
+                  builder: (context, child, pageController) {
+                    final tabsRouter = AutoTabsRouter.of(context);
+                    // Log.d("autotabsrouter build  ${tabsRouter.activeIndex}");
+                    // Log.d("communityVmProvider.notifier state.tabsRouter.tabsRouter:  ${ref.read(communityVmProvider.notifier).state.tabsRouter}");
+                    // ref.read(communityVmProvider.notifier).state.tabsRouter = tabsRouter;
+                    // ref.read(communityVmProvider.notifier).state.pageController = pageController;
+                    // Log.d("communityVmProvider.notifier state.tabsRouter.tabsRouter.activeIndex:  ${ref.read(communityVmProvider.notifier).state.tabsRouter.activeIndex}");
+
+                    return Column(
+                      children: [
+                        // tab 组件
+                        _buildTabsSection(contextPage, ref, tabsRouter),
+                        // post 组件
+                        _buildPostSection(context, ref, vm),
+                        Expanded(
+                          child: child,
+                        ),
+                      ],
+                    );
+                  },
+                ),
+              ),
+            )
+        );
+    }
+
+     Widget _buildTopSection(BuildContext context, WidgetRef ref, vm) {
         final topSectionsData = vm.topSectionsData;
-        final currentTabIdx = tabsRouter.activeIndex;
-        // 监听 curIdx 的变化
-        // final curIdx = ref.watch(communityVmProvider.select((value) => value.curIdx));
+        int curTagIdx = 0;
         return Container(
           color: Colors.white,
           padding: const EdgeInsets.only(top: 30, bottom: 30),
@@ -55,35 +171,31 @@ class CommunityPage extends HookConsumerWidget {
                         decoration: BoxDecoration(
                           // color: currentTabIdx == index ? ColorUtils.string2Color('#E6F2FF') : Colors.white,
                           shape: BoxShape.circle, // 设置为圆形
-                          boxShadow: currentTabIdx == index ? [
+                          boxShadow: index == curTagIdx ? [
                             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);
+                            vm.handlerChangeCommunityType(context,index);
                           },
                           type: ClickType.throttle,
                         ),
                       ),
                       SizedBox.fromSize(size: const Size(0, 9)),
-                      Text(
+                      MyTextView(
                         item['title'],
-                        maxLines: 1, // 设置最大行数为2
-                        overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
-                        style: TextStyle(
-                            fontSize: 15.0,
-                            color: currentTabIdx == index ? ColorUtils.string2Color('#4161D0'):Colors.black,
-                            fontWeight: FontWeight.w500
-                        ), // 设置字体大小
+                        fontSize: 15,
+                        textColor: index == curTagIdx ? ColorUtils.string2Color('#4161D0'):Colors.black,
+                        textAlign: TextAlign.center,
+                        isFontMedium: true,
                       ),
                     ],
                   ),
@@ -94,66 +206,66 @@ class CommunityPage extends HookConsumerWidget {
         );
     }
 
-    @override
-    Widget build(BuildContext context, WidgetRef ref) {
-        final vm = ref.read(communityVmProvider.notifier);
-
-        return Scaffold(
-            appBar: MyAppBar.appBar(
-              context,
-              "Community",
-              backgroundColor: context.appColors.whiteBG,
-            ),
-            backgroundColor: context.appColors.backgroundDefault,
-          body: NestedScrollView(
-              headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled){
-                return <Widget>[
-                  SliverToBoxAdapter(
-                    child: Container(
-                      child: const SizedBox.shrink(),
-                    )
-                  ),
-                  SliverToBoxAdapter(
-                    child: Consumer(
-                      builder: (context, ref, _) {
-                        final tabsRouter = ref.watch(communityVmProvider).tabsRouter;
-                        final vm = ref.read(communityVmProvider.notifier);
-                        Log.d("community_page---buildTopSection ---${tabsRouter}");
-                        Log.d("community_page---buildTopSection ---${vm.state.curIdx}");
+     Widget _buildTabsSection(BuildContext context, WidgetRef ref, tabsRouter){
+       final vm = ref.read(communityVmProvider.notifier);
+       final state = ref.watch(communityVmProvider);
+       final tabsList = ref.watch(communityVmProvider.select((state) => state.tabsList));
+       return Container(
+        width: double.infinity,
+        padding: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
+        child: NewsfeedTabs(
+          key: UniqueKey(),
+          tabsList: tabsList!,
+            tabsRouter: tabsRouter,
+          onClickAction:(activeTabIdx){
+            vm.handlerChangeTab(activeTabIdx, tabsRouter);
+          }
+        ),
+      );
+    }
 
-                        // return _buildTopSection(context, ref, vm, tabsRouter);
-                        if(tabsRouter != null){
-                          return _buildTopSection(context, ref, vm, tabsRouter);
-                        }else {
-                          return const SizedBox.shrink();
-                        }
-                      },
-                    ),
-                  ),
-                ];
-              },
-              body: AutoTabsRouter.pageView(
-                routes: const [
-                  NewsfeedPageRoute(),
-                  GaragesalePageRoute(),
-                ],
-                builder: (context, child, pageController) {
-                  final tabsRouter = AutoTabsRouter.of(context);
-                  // 设置当前的 useTag 0 newsFeed 1 garageSale
-                  vm.setCurrentUseTag(tabsRouter.activeIndex);
-                  // 将tabsRouter 放入 CommunityVmProvider 中
-                  vm.setTabsRouterAndPageController(tabsRouter, pageController);
-                  return Column(
-                    children: [
-                      // _buildTopSection(context, ref, vm, tabsRouter),
-                      Expanded(
-                        child: child,
+      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: Row(
+                  children: [
+                    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(context);
+                }),
               ),
+            ],
           ),
         );
-    }
+      }
+
 }

+ 10 - 15
packages/cpt_community/lib/modules/community/community_state.dart

@@ -1,49 +1,44 @@
+import 'package:cpt_community/modules/community/community_page.dart';
 import 'package:cs_resources/generated/assets.dart';
 
-import '../garagesale/garagesale_page.dart';
-import '../newsfeed/newsfeed_page.dart';
+import '../garage/garage_page.dart';
 
 class CommunityVmState {
-  int? useTag = 0;
   List<Map<String, dynamic>>? topSectionsData;
-  int? curIdx;
-
+  List? tabsList = ["News", "Following", "For You"];
   dynamic? tabsRouter;
   dynamic? pageController;
 
 
   CommunityVmState({
-    this.useTag = 0,
     List<Map<String, dynamic>>? topSectionsData,
-    this.curIdx = 0,
+    this.tabsList,
     this.tabsRouter,
     this.pageController,
   }) : topSectionsData = topSectionsData?? [
     {
       "title": "News Feed",
       "icon": Assets.communityNesFeed,
-      "pageStartInstanceFn": NewsfeedPage.startInstance,
-      "page": const NewsfeedPage(),
+      "pageStartInstanceFn": CommunityPage.startInstance,
+      "page": const CommunityPage(),
     },
     {
       "title": "Garage Sale",
       "icon": Assets.communityGarageSale,
-      "pageStartInstanceFn": GaragesalePage.startInstance,
-      "page": const GaragesalePage(),
+      "pageStartInstanceFn": GaragePage.startInstance,
+      "page": const GaragePage(),
     },
   ];
 
   CommunityVmState copyWith({
-    int? useTag,
     List<Map<String, dynamic>>? topSectionsData,
-    int? curIdx = 0,
+    List? tabsList,
     dynamic? tabsRouter,
     dynamic? pageController,
   }) {
     return CommunityVmState(
-      useTag: useTag ?? this.useTag,
       topSectionsData: topSectionsData ?? this.topSectionsData,
-      curIdx: curIdx ?? 0,
+      tabsList: tabsList ?? this.tabsList,
       tabsRouter: tabsRouter ?? this.tabsRouter,
       pageController: pageController ?? this.pageController,
     );

+ 37 - 27
packages/cpt_community/lib/modules/community/community_vm.dart

@@ -1,62 +1,72 @@
 
+import 'package:cpt_community/modules/garage/garage_page.dart';
+import 'package:cpt_community/router/page/community_page_router.dart';
 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:router/path/router_path.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:auto_route/auto_route.dart';
 
 import 'community_state.dart';
-
-import '../garagesale/garagesale_page.dart';
-import '../newsfeed/newsfeed_page.dart';
+import 'newsfeed_post/newsfeed_post_page.dart';
 
 part 'community_vm.g.dart';
 
 @riverpod
 class CommunityVm extends _$CommunityVm {
+  late PageController _pageController;
   get topSectionsData => state.topSectionsData;
 
   CommunityVmState initState() {
-    return CommunityVmState();
+    return CommunityVmState(
+      tabsList: ["News", "Following", "For You"],
+    );
   }
 
   @override
   CommunityVmState build(){
+
     final state = initState();
+
+
+    // 第一帧渲染完成
+
+    WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
+
+    });
     Log.d("--------------------------build---------------------");
 
     return state;
   }
 
-   // 设置当前的 tabsRouter 和 pageController
-  Future setTabsRouterAndPageController(dynamic tabsRouter, dynamic pageController) async{
-    Log.d("setTabsRouterAndPageController---: $tabsRouter");
-    state = await state.copyWith(tabsRouter: tabsRouter, pageController: pageController,curIdx: tabsRouter.activeIndex);
-  }
 
+  // 切换tab
+  handlerChangeTab(int index, tabsRouter) {
 
-   Future setCurrentUseTag(int useTag) async {
-    state = await state.copyWith(useTag: useTag, curIdx: useTag);
-    Log.d("useTag----: $useTag");
+    tabsRouter.setActiveIndex(index);
+    // state = state.copyWith(tabsRouter: tabsRouter ,activeTabIdx: index);
+    Log.d("community_vm handlerChangeTab--index:    $index");
   }
 
-  // 页面切换
-  switchPage(int index,int useTag,BuildContext? context, [bool? isFirstInitSwitch] ){
-    if(state.curIdx != index){
-      state = state.copyWith(curIdx: index, useTag: useTag);
-      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);
-      }
+
+  handlerChangeCommunityType(BuildContext context, int index){
+    if(index == 1){
+      Log.d("去往garage 页面");
+      // 跳转到 garage sale 页面
+      GaragePage.startInstance(context: context);
+      // AutoRouter.of(context).push(const GaragePageRoute());
     }
   }
 
+  // 点击发布的按钮 跳转到发布的页面
+  void handlerGotoPost(context){
+    // ComponentServiceManager().communityService.startCommunityPage();
+
+    // AutoRouter.of(context).pushNamed(RouterPath.newsFeedPost);
+
+    NewsfeedPostPage.startInstance();
+  }
 }
 

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

@@ -6,7 +6,7 @@ part of 'community_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$communityVmHash() => r'15dfd5c8d9c3d01bab9fc789c21ebe61b292c6f3';
+String _$communityVmHash() => r'5d1bae55bf25ed93006f6e35a20a27627183f458';
 
 /// See also [CommunityVm].
 @ProviderFor(CommunityVm)

+ 24 - 0
packages/cpt_community/lib/modules/community/customSilverHeaderTabs.dart

@@ -0,0 +1,24 @@
+import 'package:flutter/cupertino.dart';
+
+class CustomSliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
+   final Widget child;
+
+   CustomSliverPersistentHeaderDelegate({required this.child});
+
+   @override
+   double get minExtent => 50.0; // 最小高度
+
+   @override
+   double get maxExtent => 50.0; // 最大高度
+
+   @override
+   Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
+     return child;
+   }
+
+   @override
+   bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
+     return true;
+   }
+
+}

+ 48 - 0
packages/cpt_community/lib/modules/community/following/following_page.dart

@@ -0,0 +1,48 @@
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package: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 'following_vm.dart';
+
+@RoutePage()
+class FollowingPage extends HookConsumerWidget {
+  const FollowingPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const FollowingPageRoute());
+    } else {
+      appRouter.push(const FollowingPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    return const Scaffold(
+      // appBar: MyAppBar.appBar(
+      //   context,
+      //   "following",
+      //   backgroundColor: context.appColors.whiteBG,
+      // ),
+      // backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+      body: Column(
+        children: [
+          Text("newspage-following"),
+        ],
+      )
+    );
+  }
+}

+ 35 - 0
packages/cpt_community/lib/modules/community/following/following_state.dart

@@ -0,0 +1,35 @@
+class FollowingState {
+  int? activeTabIndex =0;
+  int? curPage =0;
+  int? pageSize =10;
+  int? filterCount =0;
+  List<String>? tabsList = ['News', 'Following', 'For You'];
+  List<Map<String, dynamic>>? list = [];
+
+  FollowingState({
+    this.activeTabIndex,
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    this.tabsList,
+    this.list,
+  });
+
+  FollowingState copyWith({
+    int? activeTabIndex,
+    int? curPage,
+    int? pageSize,
+    int? filterCount,
+    List<String>? tabsList,
+    List<Map<String, dynamic>>? list,
+  }) {
+    return FollowingState(
+      activeTabIndex: activeTabIndex ?? this.activeTabIndex,
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      filterCount: filterCount ?? this.filterCount,
+      tabsList: tabsList ?? this.tabsList,
+      list: list ?? this.list,
+    );
+  }
+}

+ 110 - 0
packages/cpt_community/lib/modules/community/following/following_vm.dart

@@ -0,0 +1,110 @@
+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 'following_state.dart';
+
+part 'following_vm.g.dart';
+
+@riverpod
+class FollowingVm extends _$FollowingVm {
+
+  FollowingState initState() {
+    return FollowingState(
+      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
+          },
+          {
+            'id':4,
+            '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
+          },
+          {
+            'id':5,
+            '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
+          },
+          {
+            'id':6,
+            '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
+          },
+          {
+            'id':7,
+            'avator': Assets.communityCamera,
+            'title': '放大发大水',
+            '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
+  FollowingState build(){
+    final state = initState();
+    Log.d("--------------------------build---------------------");
+
+    return state;
+  }
+
+   // 设置当前的 tabsRouter 和 pageController
+  Future setTabsRouterAndPageController(dynamic tabsRouter, dynamic pageController) async{
+    Log.d("setTabsRouterAndPageController---:$tabsRouter");
+  }
+}

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

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

+ 79 - 0
packages/cpt_community/lib/modules/community/foryou/foryou_page.dart

@@ -0,0 +1,79 @@
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package: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 'foryou_vm.dart';
+
+@RoutePage()
+class ForyouPage extends HookConsumerWidget {
+  const ForyouPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const ForyouPageRoute());
+    } else {
+      appRouter.push(const ForyouPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(foryouVmProvider.notifier);
+    return Scaffold(
+      // appBar: MyAppBar.appBar(
+      //   context,
+      //   "foryou",
+      //   backgroundColor: context.appColors.whiteBG,
+      // ),
+      // backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+        body: Column(
+          children: [
+            Expanded(
+              child: EasyRefresh(
+                // 上拉加载
+                onLoad: () async{
+                  Log.d("----onLoad");
+                  vm.onLoadData();
+                },
+                // 下拉刷新
+                onRefresh: () async{
+                  Log.d("----onRefresh");
+                  vm.refreshListData();
+                },
+                child: _buildForyouList(context, ref, vm),
+              ),
+            )
+          ],
+        )
+    );
+  }
+
+
+  Widget _buildForyouList(BuildContext context, WidgetRef ref, ForyouVm vm) {
+
+    return ListView.builder(
+      itemCount: 3,
+      itemBuilder: (context, index) {
+        return _buildListItem(context, ref, vm, index);
+      },
+    );
+  }
+
+  Widget _buildListItem(BuildContext context, WidgetRef ref, ForyouVm vm, int index) {
+    return Text("list-item");
+  }
+
+}

+ 9 - 9
packages/cpt_community/lib/modules/newsfeed/newsfeed_repository.dart

@@ -9,25 +9,25 @@ 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';
+import 'foryou_state.dart';
 
-part 'newsfeed_repository.g.dart';
+part 'foryou_respository.g.dart';
 
 @Riverpod(keepAlive: true)
-NewsfeedRepository newsfeedRepository(Ref ref) {
+ForyouRepository foryouRepository(Ref ref) {
   final dioEngine = ref.watch(dioEngineProvider);
-  return NewsfeedRepository(dioEngine: dioEngine);
+  return ForyouRepository(dioEngine: dioEngine);
 }
 
 /*
  * 数据仓库
  */
-class NewsfeedRepository {
+class ForyouRepository {
   DioEngine dioEngine;
 
-  NewsfeedRepository({required this.dioEngine});
+  ForyouRepository({required this.dioEngine});
 
-  Future<HttpResult<Object>> fetchNewsfeedList(
+  Future<HttpResult<Object>> fetchForyouList(
       Map<String, dynamic>? data, {
         CancelToken? cancelToken,
       }) async {
@@ -60,9 +60,9 @@ class NewsfeedRepository {
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      var data = NewsfeedState.fromMap(json!);
+      var data = ForyouState.fromMap(json!);
       //重新赋值data或list
-      return result.convert<NewsfeedState>(data: data);
+      return result.convert<ForyouState>(data: data);
     }
     return result.convert();
   }

+ 9 - 10
packages/cpt_community/lib/modules/newsfeed/newsfeed_repository.g.dart

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

+ 57 - 0
packages/cpt_community/lib/modules/community/foryou/foryou_state.dart

@@ -0,0 +1,57 @@
+class ForyouState {
+  int? activeTabIndex =0;
+  int? curPage =0;
+  int? pageSize =10;
+  int? filterCount =0;
+  List<String>? tabsList = ['News', 'Following', 'For You'];
+  List<Map<String, dynamic>>? list = [];
+
+  ForyouState({
+    this.activeTabIndex,
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    this.tabsList,
+    this.list,
+  });
+
+  ForyouState copyWith({
+    int? activeTabIndex,
+    int? curPage,
+    int? pageSize,
+    int? filterCount,
+    List<String>? tabsList,
+    List<Map<String, dynamic>>? list,
+  }) {
+    return ForyouState(
+      activeTabIndex: activeTabIndex ?? this.activeTabIndex,
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      filterCount: filterCount ?? this.filterCount,
+      tabsList: tabsList ?? this.tabsList,
+      list: list ?? this.list,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'activeTabIndex': this.activeTabIndex,
+      'curPage': this.curPage,
+      'pageSize': this.pageSize,
+      'filterCount': this.filterCount,
+      'tabsList': this.tabsList,
+      'list': this.list,
+    };
+  }
+
+  factory ForyouState.fromMap(Map<String, dynamic> map) {
+    return ForyouState(
+      activeTabIndex: map['activeTabIndex'] as int,
+      curPage: map['curPage'] as int,
+      pageSize: map['pageSize'] as int,
+      filterCount: map['filterCount'] as int,
+      tabsList: map['tabsList'] as List<String>,
+      list: map['list'] as List<Map<String, dynamic>>,
+    );
+  }
+}

+ 196 - 0
packages/cpt_community/lib/modules/community/foryou/foryou_vm.dart

@@ -0,0 +1,196 @@
+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:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import '../../../router/page/community_page_router.dart';
+import '../newsfeed_detail/newsfeed_detail_page.dart';
+import 'foryou_respository.dart';
+import 'foryou_state.dart';
+
+part 'foryou_vm.g.dart';
+
+@riverpod
+class ForyouVm extends _$ForyouVm {
+  late ForyouRepository ForyouRepositoryInstance;
+  ForyouState initState() {
+    return ForyouState(
+        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
+          },
+          {
+            'id':4,
+            '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
+          },
+          {
+            'id':5,
+            '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
+          },
+          {
+            'id':6,
+            '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
+          },
+          {
+            'id':7,
+            'avator': Assets.communityCamera,
+            'title': '放大发大水',
+            '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
+  ForyouState build(){
+    // 引入数据仓库
+    ForyouRepositoryInstance = ref.read(foryouRepositoryProvider);
+    final state = initState();
+    Log.d("--------------------------build---------------------");
+
+    return state;
+  }
+
+  // 设置当前的 tabsRouter 和 pageController
+  Future setTabsRouterAndPageController(dynamic tabsRouter, dynamic pageController) async{
+    Log.d("setTabsRouterAndPageController---:$tabsRouter");
+  }
+
+// 上拉加载
+  Future onLoadData() async {
+    Log.d("----Foryou_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 ForyouRepositoryInstance.fetchForyouList(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_foryou_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(ForyouVmProvider);
+    getListData();
+
+  }
+
+
+  // 点击 like comments  share
+  void handlerClickActionBtn(String? actionStr, item){
+    final id = item['id'];
+    switch (actionStr) {
+      case 'like':
+        Log.d("点击了 点赞");
+        handlerGotoDetail(id);
+        break;
+      case 'comments':
+        Log.d("点击了 评论");
+        handlerGotoDetail(id);
+        break;
+      case 'share':
+        Log.d("点击了 分享");
+        handlerGotoDetail(id);
+        break;
+      default:
+        break;
+    }
+  }
+  // 去详情页面
+  void handlerGotoDetail(id){
+    Log.d("去详情页面");
+    appRouter.push(NewsfeedDetailPageRoute(id: id, type: 'foryou'));
+  }
+}

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

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

+ 169 - 0
packages/cpt_community/lib/modules/community/news/news_page.dart

@@ -0,0 +1,169 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/my_button.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 '../../../components/newfeed_card_header.dart';
+import '../../../components/newsfeed_card_content.dart';
+import '../../../components/newsfeed_card_footer.dart';
+import '../../../router/page/community_page_router.dart';
+import 'news_vm.dart';
+
+@RoutePage()
+class NewsPage extends HookConsumerWidget {
+  const NewsPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const NewsPageRoute());
+    } else {
+      appRouter.push(const NewsPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(newsVmProvider.notifier);
+    return Scaffold(
+      // appBar: MyAppBar.appBar(
+      //   context,
+      //   "news",
+      //   backgroundColor: context.appColors.whiteBG,
+      // ),
+      // backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+      body: Column(
+        children: [
+            Expanded(
+              child: EasyRefresh(
+                // 上拉加载
+                onLoad: () async{
+                  Log.d("----onLoad");
+                  vm.onLoadData();
+                },
+                // 下拉刷新
+                onRefresh: () async{
+                  Log.d("----onRefresh");
+                  vm.refreshListData();
+                },
+                child: _buildNewsFeedList(context, ref, vm),
+              ),
+            )
+        ],
+      )
+    );
+  }
+
+  Widget _buildNewsItem(BuildContext context, WidgetRef ref, item, vm){
+    return Container(
+      width: double.infinity,
+      //   color: Colors.yellow,
+      child: Stack(
+        children: [
+          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(
+                    key: UniqueKey(),
+                    title: item['title'],
+                    avator: item['avator'],
+                    time: item['time'],
+                  ),
+                  const SizedBox(height: 15),
+                  // 卡片中间 (文字和图片)
+                  Expanded(
+                    child: NewsFeedCardContent(
+                      key: UniqueKey(),
+                      content: item['content'],
+                      imageUrls: item['imageUrls'],
+                    ),
+                  ),
+                  const SizedBox(height: 26),
+                  // // 卡片底部 (点赞 评论 分享)
+                  NewsFeedCardFooter(
+                      key: UniqueKey(),
+                      isLike: item['isLike'],
+                      onLike: (){
+                        vm.handlerClickActionBtn('like', item);
+                      },
+                      onComment: (){
+                        vm.handlerClickActionBtn('comments', item);
+                      },
+                      onShare: (){
+                        vm.handlerClickActionBtn('share', item);
+                      },
+                  ),
+                ]
+            ),
+          ),
+          // 右上角 关注/取消关注 按钮
+          Visibility(
+            visible: !item['isFollow'],
+            child: Positioned(
+              right: 40,
+              top: 35,
+              child: Container(
+                width: 83.5,
+                height: 45.5,
+                alignment: Alignment.center,
+                // decoration: BoxDecoration(
+                //   color:  ColorUtils.string2Color('#4161D0'),
+                //   borderRadius: BorderRadius.circular(5),
+                // ),
+                child: MyButton(
+                  text: '+Follow',
+                  textColor: Colors.white,
+                  backgroundColor: ColorUtils.string2Color('#4161D0'),
+                  radius: 8,
+                  minHeight: 27.5,
+                  padding: const EdgeInsets.only(left: 5, right: 5,top:9,bottom:9),
+                  fontWeight: FontWeight.w400,
+                  fontSize: 14,
+                  onPressed: (){
+                    // Navigator.pop(context);
+                  },
+                ),
+              )
+            ),
+          )
+        ],
+      ),
+    );
+  }
+
+  Widget _buildNewsFeedList(BuildContext context, WidgetRef ref, vm){
+    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(
+        key: UniqueKey(),
+        itemCount: itemsList.length,
+        itemBuilder: (context, index) {
+          return _buildNewsItem(context, ref, itemsList[index], vm);
+        },
+      );
+    }
+    // return Text("879424");
+  }
+}

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

@@ -9,25 +9,25 @@ import 'package:shared/utils/util.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:plugin_basic/provider/http_provider/http_provider.dart';
 
-import 'garagesale_state.dart';
+import 'news_state.dart';
 
-part 'garagesale_repository.g.dart';
+part 'news_respository.g.dart';
 
 @Riverpod(keepAlive: true)
-GaragesaleRepository garagesaleRepository(Ref ref) {
+NewsRepository newsRepository(Ref ref) {
   final dioEngine = ref.watch(dioEngineProvider);
-  return GaragesaleRepository(dioEngine: dioEngine);
+  return NewsRepository(dioEngine: dioEngine);
 }
 
 /*
  * 数据仓库
  */
-class GaragesaleRepository {
+class NewsRepository {
   DioEngine dioEngine;
 
-  GaragesaleRepository({required this.dioEngine});
+  NewsRepository({required this.dioEngine});
 
-  Future<HttpResult<Object>> fetchGaragesaleList(
+  Future<HttpResult<Object>> fetchNewsList(
       Map<String, dynamic>? data, {
         CancelToken? cancelToken,
       }) async {
@@ -60,9 +60,9 @@ class GaragesaleRepository {
     if (result.isSuccess) {
       //重新赋值data或list
       final json = result.getDataJson();
-      var data = GaragesaleState.fromMap(json!);
+      var data = NewsState.fromMap(json!);
       //重新赋值data或list
-      return result.convert<GaragesaleState>(data: data);
+      return result.convert<NewsState>(data: data);
     }
     return result.convert();
   }

+ 9 - 10
packages/cpt_community/lib/modules/garagesale/garagesale_repository.g.dart

@@ -1,28 +1,27 @@
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
-part of 'garagesale_repository.dart';
+part of 'news_respository.dart';
 
 // **************************************************************************
 // RiverpodGenerator
 // **************************************************************************
 
-String _$garagesaleRepositoryHash() =>
-    r'0b158a0c8d06f9f2fa4b6646c215f09c0656eaad';
+String _$newsRepositoryHash() => r'097145b82f467702467a6b71c1500d8364d69eb7';
 
-/// See also [garagesaleRepository].
-@ProviderFor(garagesaleRepository)
-final garagesaleRepositoryProvider = Provider<GaragesaleRepository>.internal(
-  garagesaleRepository,
-  name: r'garagesaleRepositoryProvider',
+/// See also [newsRepository].
+@ProviderFor(newsRepository)
+final newsRepositoryProvider = Provider<NewsRepository>.internal(
+  newsRepository,
+  name: r'newsRepositoryProvider',
   debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
       ? null
-      : _$garagesaleRepositoryHash,
+      : _$newsRepositoryHash,
   dependencies: null,
   allTransitiveDependencies: null,
 );
 
 @Deprecated('Will be removed in 3.0. Use Ref instead')
 // ignore: unused_element
-typedef GaragesaleRepositoryRef = ProviderRef<GaragesaleRepository>;
+typedef NewsRepositoryRef = ProviderRef<NewsRepository>;
 // 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

+ 57 - 0
packages/cpt_community/lib/modules/community/news/news_state.dart

@@ -0,0 +1,57 @@
+class NewsState {
+  int? activeTabIndex =0;
+  int? curPage =0;
+  int? pageSize =10;
+  int? filterCount =0;
+  List<String>? tabsList = ['News', 'Following', 'For You'];
+  List<Map<String, dynamic>>? list = [];
+
+  NewsState({
+    this.activeTabIndex,
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    this.tabsList,
+    this.list,
+  });
+
+  NewsState copyWith({
+    int? activeTabIndex,
+    int? curPage,
+    int? pageSize,
+    int? filterCount,
+    List<String>? tabsList,
+    List<Map<String, dynamic>>? list,
+  }) {
+    return NewsState(
+      activeTabIndex: activeTabIndex ?? this.activeTabIndex,
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      filterCount: filterCount ?? this.filterCount,
+      tabsList: tabsList ?? this.tabsList,
+      list: list ?? this.list,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'activeTabIndex': this.activeTabIndex,
+      'curPage': this.curPage,
+      'pageSize': this.pageSize,
+      'filterCount': this.filterCount,
+      'tabsList': this.tabsList,
+      'list': this.list,
+    };
+  }
+
+  factory NewsState.fromMap(Map<String, dynamic> map) {
+    return NewsState(
+      activeTabIndex: map['activeTabIndex'] as int,
+      curPage: map['curPage'] as int,
+      pageSize: map['pageSize'] as int,
+      filterCount: map['filterCount'] as int,
+      tabsList: map['tabsList'] as List<String>,
+      list: map['list'] as List<Map<String, dynamic>>,
+    );
+  }
+}

+ 196 - 208
packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.dart

@@ -1,208 +1,196 @@
-
-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:router/componentRouter/component_service_manager.dart';
-import 'package:router/path/router_path.dart';
-import 'package:shared/utils/color_utils.dart';
-import 'package:shared/utils/log_utils.dart';
-import 'package:auto_route/auto_route.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(
-      useTag: 0,
-      activeIndex: 0,
-      tabsList: [
-        {
-          'title': 'News',
-          'icon': null,
-          'active': true,
-          'activeTitleColor': Colors.white,
-          'activeTitleFontSize': 16,
-          'activeTitleBackgroundColor': ColorUtils.string2Color("#4161D0"),
-        },
-        {
-          'title': 'Following',
-          'icon': null,
-          'active': false,
-          '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
-          },
-          {
-            'id':4,
-            '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
-          },
-          {
-            'id':5,
-            '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
-          },
-          {
-            'id':6,
-            '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
-          },
-          {
-            'id':7,
-            'avator': Assets.communityCamera,
-            'title': '放大发大水',
-            '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("----newsfeed_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(context){
-    // ComponentServiceManager().communityService.startCommunityPage();
-
-    AutoRouter.of(context).pushNamed(RouterPath.newsFeedPost);
-  }
-
-  // 点击tab
-  void handlerClickTab(int index, item){
-    state = state.copyWith(activeIndex: index);
-    print("切换后新的 sate, ${state.tabsList}");
-
-    // ref.invalidate(customTabsVmProvider);
-  }
-}
+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:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import '../../../router/page/community_page_router.dart';
+import '../newsfeed_detail/newsfeed_detail_page.dart';
+import 'news_respository.dart';
+import 'news_state.dart';
+
+part 'news_vm.g.dart';
+
+@riverpod
+class NewsVm extends _$NewsVm {
+  late NewsRepository NewsRepositoryInstance;
+  NewsState initState() {
+    return NewsState(
+      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
+          },
+          {
+            'id':4,
+            '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
+          },
+          {
+            'id':5,
+            '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
+          },
+          {
+            'id':6,
+            '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
+          },
+          {
+            'id':7,
+            'avator': Assets.communityCamera,
+            'title': '放大发大水',
+            '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
+  NewsState build(){
+    // 引入数据仓库
+    NewsRepositoryInstance = ref.read(newsRepositoryProvider);
+    final state = initState();
+    Log.d("--------------------------build---------------------");
+
+    return state;
+  }
+
+   // 设置当前的 tabsRouter 和 pageController
+  Future setTabsRouterAndPageController(dynamic tabsRouter, dynamic pageController) async{
+    Log.d("setTabsRouterAndPageController---:$tabsRouter");
+  }
+
+// 上拉加载
+  Future onLoadData() async {
+    Log.d("----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 NewsRepositoryInstance.fetchNewsList(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(NewsVmProvider);
+    getListData();
+
+  }
+
+
+  // 点击 like comments  share
+  void handlerClickActionBtn(String? actionStr, item){
+    final id = item['id'];
+    switch (actionStr) {
+      case 'like':
+        Log.d("点击了 点赞");
+        handlerGotoDetail(id);
+        break;
+      case 'comments':
+        Log.d("点击了 评论");
+        handlerGotoDetail(id);
+        break;
+      case 'share':
+        Log.d("点击了 分享");
+        handlerGotoDetail(id);
+        break;
+      default:
+        break;
+    }
+  }
+  // 去详情页面
+  void handlerGotoDetail(id){
+    Log.d("去详情页面");
+    appRouter.push(NewsfeedDetailPageRoute(id: id, type:'news'));
+  }
+}

+ 9 - 10
packages/cpt_community/lib/modules/newsfeed/newsfeed_vm.g.dart

@@ -1,25 +1,24 @@
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
-part of 'newsfeed_vm.dart';
+part of 'news_vm.dart';
 
 // **************************************************************************
 // RiverpodGenerator
 // **************************************************************************
 
-String _$newsfeedVmHash() => r'8913ddbbe012f28caa65fbc8fdd824a8b818d4c6';
+String _$newsVmHash() => r'f5a5a082bc85c87229ff78e9b20eef1acb230831';
 
-/// See also [NewsfeedVm].
-@ProviderFor(NewsfeedVm)
-final newsfeedVmProvider =
-    AutoDisposeNotifierProvider<NewsfeedVm, NewsfeedState>.internal(
-  NewsfeedVm.new,
-  name: r'newsfeedVmProvider',
+/// See also [NewsVm].
+@ProviderFor(NewsVm)
+final newsVmProvider = AutoDisposeNotifierProvider<NewsVm, NewsState>.internal(
+  NewsVm.new,
+  name: r'newsVmProvider',
   debugGetCreateSourceHash:
-      const bool.fromEnvironment('dart.vm.product') ? null : _$newsfeedVmHash,
+      const bool.fromEnvironment('dart.vm.product') ? null : _$newsVmHash,
   dependencies: null,
   allTransitiveDependencies: null,
 );
 
-typedef _$NewsfeedVm = AutoDisposeNotifier<NewsfeedState>;
+typedef _$NewsVm = AutoDisposeNotifier<NewsState>;
 // 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

+ 188 - 0
packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_page.dart

@@ -0,0 +1,188 @@
+import 'package:cpt_community/router/page/community_page_router.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_text_view.dart';
+
+import '../../../components/newfeed_card_header.dart';
+import '../../../components/newsfeed_card_content.dart';
+import '../../../components/newsfeed_card_footer.dart';
+import 'newsfeed_detail_state.dart';
+import 'newsfeed_detail_vm.dart';
+
+@RoutePage()
+class NewsfeedDetailPage extends HookConsumerWidget {
+  final int? id;
+  final String? type;  // news  following foryou
+
+  const NewsfeedDetailPage({Key? key, required this.id, required this.type}) : super(key: key);
+  // 启动当前页面
+  static void startInstance({BuildContext? context, int? id, String? type='news'}) {
+    if (context != null) {
+      context.router.push(NewsfeedDetailPageRoute(id: id, type: type));
+    } else {
+      appRouter.push(NewsfeedDetailPageRoute(id: id, type: type));
+    }
+  }
+
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(newsfeedDetailVmProvider.notifier);
+    final state = ref.watch(newsfeedDetailVmProvider);
+    useEffect((){
+      // 组件挂载时执行 - 执行接口请求
+      // Future.microtask(() => vm.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        "News Feed Detail",
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+      body: Column(
+        children: [
+          _buildTopCard(context, ref),
+         // 评论区域
+          Expanded(child: _buildCommentListCard(context, ref)),
+         //  底部 like comments 按钮区
+          Container(
+            color: ColorUtils.string2Color("#2956B7"),
+            child: Row(
+              children: [
+                Expanded(
+                  child: MyButton(
+                    minHeight: 50,
+                    text: 'Like',
+                    textColor: Colors.white,
+                    onPressed: () {},
+                  )
+                )
+              ]
+            )
+          )
+        ],
+      ),
+    );
+  }
+
+  Widget _buildTopCard(BuildContext context, WidgetRef ref){
+    final vm = ref.read(newsfeedDetailVmProvider.notifier);
+    final state = ref.watch(newsfeedDetailVmProvider);
+    return Container(
+      width: double.infinity,
+      //   color: Colors.yellow,
+      child: Stack(
+        children: [
+          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(
+                    key: UniqueKey(),
+                    title: state?.detailInfo!['title'],
+                    avator: state?.detailInfo['avator'],
+                    time: state?.detailInfo['time'],
+                  ),
+                  const SizedBox(height: 15),
+                  // 卡片中间 (文字和图片)
+                  Expanded(
+                    child: NewsFeedCardContent(
+                      key: UniqueKey(),
+                      content: state.detailInfo['content'],
+                      imageUrls: state.detailInfo['imageUrls'],
+                    ),
+                  ),
+                  const SizedBox(height: 26),
+                ]
+            ),
+          ),
+          // 右上角 关注/取消关注 按钮
+          Visibility(
+            visible: !state.detailInfo['isFollow'],
+            child: Positioned(
+                right: 40,
+                top: 35,
+                child: Container(
+                  width: 83.5,
+                  height: 45.5,
+                  alignment: Alignment.center,
+                  // decoration: BoxDecoration(
+                  //   color:  ColorUtils.string2Color('#4161D0'),
+                  //   borderRadius: BorderRadius.circular(5),
+                  // ),
+                  child: MyButton(
+                    text: '+Follow',
+                    textColor: Colors.white,
+                    backgroundColor: ColorUtils.string2Color('#4161D0'),
+                    radius: 8,
+                    minHeight: 27.5,
+                    padding: const EdgeInsets.only(left: 5, right: 5,top:9,bottom:9),
+                    fontWeight: FontWeight.w400,
+                    fontSize: 14,
+                    onPressed: (){
+                      // Navigator.pop(context);
+                    },
+                  ),
+                )
+            ),
+          )
+        ],
+      ),
+    );
+  }
+
+  Widget _buildCommentListCard(BuildContext context,  WidgetRef ref){
+    return Container(
+      color: Colors.white,
+      margin: const EdgeInsets.only(left: 15, right: 15,top: 18,bottom: 18),
+      child: Column(
+        children: [
+          Row(
+            children: [
+              Expanded(
+                child: Container(
+                  padding: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
+                  child: Row(
+                    children: [
+                      MyTextView('Comments', textColor: ColorUtils.string2Color("#2956B7"), fontSize: 15, isFontLight: true,),
+                      const SizedBox(width: 5,),
+                      MyTextView('95', textColor: ColorUtils.string2Color("#2956B7"), fontSize: 15, isFontLight: true,),
+                    ]
+                  )
+                )
+              )
+            ],
+          ),
+          const Expanded(
+            child:  Row(
+              children: [
+                 Text("fsdf"),
+              ],
+            ),
+          ),
+        ]
+      ),
+    ).borderRadius(all:8);
+  }
+}

+ 27 - 0
packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_state.dart

@@ -0,0 +1,27 @@
+class NewsfeedDetailState {
+  int? curPage;
+  int? pageSize;
+  int? filterCount;
+  Map<String, dynamic> detailInfo;
+
+  NewsfeedDetailState({
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    required this.detailInfo,
+  });
+
+  NewsfeedDetailState copyWith({
+    int? curPage,
+    int? pageSize,
+    int? filterCount,
+    Map<String, dynamic>? detailInfo,
+  }) {
+    return NewsfeedDetailState(
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      filterCount: filterCount ?? this.filterCount,
+      detailInfo: detailInfo ?? this.detailInfo,
+    );
+  }
+}

+ 60 - 0
packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_vm.dart

@@ -0,0 +1,60 @@
+
+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 'newsfeed_detail_state.dart';
+import 'newsfeed_detail_page.dart';
+
+part 'newsfeed_detail_vm.g.dart';
+
+@riverpod
+class NewsfeedDetailVm extends _$NewsfeedDetailVm {
+
+   initState() {
+    return NewsfeedDetailState(
+      curPage: 1,
+      pageSize: 10,
+      filterCount: 0,
+      detailInfo: {
+        'id':1,
+        'avator': Assets.communityCamera,
+        'title': 'William Jefferson',
+        '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,
+        'isFollow': false,
+        'likeno': 12,
+        'commentsInfo': {
+          'total': 12,
+          'list': [
+            {
+                'userId': 1,
+                'userName': 'William Jefferson',
+                'avator': Assets.communityCamera,
+                'time': 'June 17,2016 at 7:23 p.m.',
+                'content': 'She said YES and our lives changed.Thank you all for coming to my propose today.We hope everyone can ……[More]'
+            },
+          ]
+        }
+      },
+    );
+  }
+
+
+  @override
+  NewsfeedDetailState build(){
+     final state = initState();
+
+    // 第一次挂载后
+    // WidgetsBinding.instance!.addPostFrameCallback((_) {
+    // }
+
+    // Log.d("---------444-----------------build---------------${state.detailInfo}------");
+    return state;
+  }
+}
+

+ 26 - 0
packages/cpt_community/lib/modules/community/newsfeed_detail/newsfeed_detail_vm.g.dart

@@ -0,0 +1,26 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'newsfeed_detail_vm.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$newsfeedDetailVmHash() => r'058d92cd086572a5cc7e16f57db7d89405bf3c2f';
+
+/// See also [NewsfeedDetailVm].
+@ProviderFor(NewsfeedDetailVm)
+final newsfeedDetailVmProvider =
+    AutoDisposeNotifierProvider<NewsfeedDetailVm, NewsfeedDetailState>.internal(
+  NewsfeedDetailVm.new,
+  name: r'newsfeedDetailVmProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$newsfeedDetailVmHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$NewsfeedDetailVm = AutoDisposeNotifier<NewsfeedDetailState>;
+// 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

packages/cpt_community/lib/modules/newsfeed/newsfeed_myposts/newsfeed_myposts_page.dart → packages/cpt_community/lib/modules/community/newsfeed_myposts/newsfeed_myposts_page.dart


+ 247 - 0
packages/cpt_community/lib/modules/community/newsfeed_post/newsfeed_post_page.dart

@@ -0,0 +1,247 @@
+import 'package:cpt_community/router/page/community_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:plugin_platform/engine/image/image_nine_grid.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:widgets/my_button.dart';
+
+import 'newsfeed_post_vm.dart';
+
+@RoutePage()
+class NewsfeedPostPage extends HookConsumerWidget {
+  const NewsfeedPostPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const NewsfeedPostPageRoute());
+    } else {
+      appRouter.push(const NewsfeedPostPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(newsfeedPostVmProvider.notifier);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        "Create Post",
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+      body: Column(
+          children: [
+            Expanded(
+                child: SingleChildScrollView(
+                    scrollDirection: Axis.vertical,
+                    physics: const BouncingScrollPhysics(),
+                    clipBehavior: Clip.none,
+                    child: Column(
+                        children: [
+                          // mind textearea
+                          Container(
+                            margin: const EdgeInsets.only(left:15, right:15,top: 20),
+                            width: double.infinity,
+                            height: 200,
+                            padding: const EdgeInsets.all(15),
+                            decoration: BoxDecoration(
+                                color: Colors.white,
+                                borderRadius: BorderRadius.circular(5),
+                                boxShadow: [
+                                  BoxShadow(
+                                    color: Colors.grey.withOpacity(0.2),
+                                    spreadRadius:1,
+                                    blurRadius: 2,
+                                    offset: const Offset(0.5, 0.5), // changes position of shadow
+                                  ),
+                                ]
+                            ),
+                            child: _buildTextAreaLayout(context,ref,'mind',),
+                          ),
+                          Container(
+                            width: double.infinity,
+                            height: 200,
+                            margin: const EdgeInsets.only(left:15, right:15, top: 20, bottom: 20),
+                            padding: const EdgeInsets.all(15),
+                            decoration: BoxDecoration(
+                                color: Colors.white,
+                                borderRadius: BorderRadius.circular(5),
+                                boxShadow: [
+                                  BoxShadow(
+                                    color: Colors.grey.withOpacity(0.2),
+                                    spreadRadius:1,
+                                    blurRadius: 2,
+                                    offset: const Offset(0.5, 0.5), // changes position of shadow
+                                  ),
+                                ]
+                            ),
+                            // 选择图片上传 控件
+                            child: _buildImageSelectCmp(context, ref,vm),
+                          ),
+                        ]
+                    )
+                )
+            ),
+            // 底部 按钮
+            Container(
+              child: Row(
+                  children: [
+                    Expanded(
+                      child: MyButton(
+                        text: "Add Card",
+                        radius: 0,
+                        minHeight: 50,
+                        backgroundColor: context.appColors.textPrimary,
+                        textColor: Colors.white,
+                        fontWeight: FontWeight.w500,
+                        fontSize: 16,
+                        onPressed: (){
+                          // Navigator.pop(context);
+                          vm.submitNewsfeedPost();
+                        },
+                      ),
+                    ),
+                  ]
+              ),
+            )
+          ]
+      ),
+    );
+  }
+
+  /// 选择图片上传组件
+  Widget _buildImageSelectCmp(BuildContext context, WidgetRef ref,vm,){
+    final state = ref.watch(newsfeedPostVmProvider);
+    return ImageNineGrid(
+      isSelectEnable: true,
+      maxImages: 10,
+      spacing: 10,
+      aspectRatio: 108 / 80,
+      initialImages: state.imgList,
+      onImagesChanged: (list) {
+        vm.setImgList(list);
+      },
+    );
+  }
+
+  /// 多行输入框
+  Widget _buildTextAreaLayout(BuildContext context, ref, key){
+    final state = ref.watch(newsfeedPostVmProvider);
+    final vm = ref.read(newsfeedPostVmProvider.notifier);
+    final noteCount = useState(0);
+
+    return Stack(
+      children: [
+        TextField(
+          cursorColor: context.appColors.authFiledText,
+          cursorWidth: 1.5,
+          autofocus: false,
+          enabled: true,
+          maxLines: null,
+          focusNode: state.formData[key]!['focusNode'],
+          controller: state.formData[key]!['controller'],
+          decoration: InputDecoration(
+            isDense: true,
+            isCollapsed: true,
+            border: InputBorder.none,
+            hintText: state.formData[key]!['hintText'],
+            hintStyle: TextStyle(
+              color: context.appColors.authFiledHint,
+              fontSize: 16.0,
+              fontWeight: FontWeight.w500,
+            ),
+          ),
+          style: TextStyle(
+            color: context.appColors.authFiledText,
+            fontSize: 16.0,
+            fontWeight: FontWeight.w500,
+          ),
+          textInputAction: TextInputAction.done,
+          onSubmitted: (value) {
+            FocusScope.of(context).unfocus();
+          },
+          expands: true,
+          onChanged: (text) {
+            // 当文本改变时,更新字符数量
+            noteCount.value = text.length;
+          },
+        ),
+        Positioned(
+          bottom: 0.0,
+          right: 0.0,
+          child: Text(
+            S.current.characters(noteCount.value),
+            style: TextStyle(
+              color: context.appColors.textBlack,
+              fontSize: 15.0,
+            ),
+          ),
+        ),
+      ]
+    );
+  }
+
+
+  /// 单行输入框
+  Widget _buildInputLayout(
+      BuildContext context,
+      state,
+      String key,
+      {
+        double height = 48,
+        double maxLines = 1,
+        double marginTop = 0,
+        bool? showRightIcon = false, //是否展示右侧的布局
+        Widget? rightWidget, //右侧的布局
+        TextInputType textInputType = TextInputType.text,
+        String? errorText,
+        bool obscureText = false,
+        TextInputAction textInputAction = TextInputAction.done,
+        Function? onSubmit,
+      }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        height: height,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+}

+ 38 - 0
packages/cpt_community/lib/modules/community/newsfeed_post/newsfeed_post_page_state.dart

@@ -0,0 +1,38 @@
+import 'package:flutter/cupertino.dart';
+
+class NewsfeedPostPageState {
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+  // 选择的图片
+  final List<String> imgList;
+
+  //表单的错误信息展示
+  String? mindFieldErrorText;
+
+  NewsfeedPostPageState({
+    formData,
+    required this.imgList,
+    this.mindFieldErrorText,
+  }): formData = formData ?? {
+    'mind': {
+      'value': '',
+      'controller': TextEditingController(),
+      'hintText': 'What\'s on your mind?',
+      'focusNode': FocusNode(),
+      'obsecure': false,
+    }
+  };
+
+  NewsfeedPostPageState copyWith({
+    Map<String, Map<String, dynamic>>? formData,
+    List<String>? imgList,
+    String? mindFieldErrorText,
+  }) {
+    return NewsfeedPostPageState(
+      formData: formData ?? this.formData,
+      imgList: imgList ?? this.imgList,
+      mindFieldErrorText: mindFieldErrorText ?? this.mindFieldErrorText,
+    );
+  }
+
+}

+ 159 - 0
packages/cpt_community/lib/modules/community/newsfeed_post/newsfeed_post_vm.dart

@@ -0,0 +1,159 @@
+
+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:router/path/router_path.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:shared/utils/util.dart';
+
+
+import 'newsfeed_post_page_state.dart';
+
+part 'newsfeed_post_vm.g.dart';
+
+@riverpod
+class NewsfeedPostVm extends _$NewsfeedPostVm {
+
+  NewsfeedPostPageState initState() {
+    return NewsfeedPostPageState(
+        mindFieldErrorText: null,
+        formData: {
+          'mind': {
+            'value': '',
+            'controller': TextEditingController(),
+            'hintText': 'What\'s on your mind?',
+            'focusNode': FocusNode(),
+            'obsecure': false,
+          }
+        },
+        imgList: [],
+    );
+  }
+
+  @override
+  NewsfeedPostPageState build() {
+    // 初始化状态
+    NewsfeedPostPageState state = initState();
+
+    // 当前渲染完成后执行一次
+    WidgetsBinding.instance!.addPostFrameCallback((_) {
+      // 获取焦点
+      initListener(state);
+      ref.onDispose(() {
+        onDispose(state);
+      });
+    });
+
+    return state;
+  }
+
+  // //选择选项
+  // void pickCategory() {
+  //   _dismissKeyboard();
+  //
+  //   OptionPickerUtil.showCupertinoOptionPicker(
+  //     items: state.optionList,
+  //     initialSelectIndex: 0,
+  //     onPickerChanged: (_, index) {
+  //       state = state.copyWith(selectedOption: state.optionList[index]);
+  //     },
+  //   );
+  // }
+
+  // 获取聚焦的node
+  FocusNode getFocusNode(Map<String, dynamic> formData, String keyStr) {
+    return formData![keyStr]!['focusNode'];
+  }
+
+  // 取消表单聚焦状态
+  void _dismissKeyboard({String? keyStr}) {
+    if(keyStr!.isNotEmpty){
+      Log.d("FeedbackCreateViewModel 取消单个表单 $keyStr 聚焦状态");
+      final FocusNode sigleItemFocusNode = state.formData[keyStr]!['focusNode'];
+      sigleItemFocusNode!.unfocus();
+    }else {
+      Log.d("FeedbackCreateViewModel 取消所有表单聚焦状态");
+      // 遍历 formData 的所有表单 然后逐一取消聚焦
+      Map<String, dynamic> formData = state.formData;
+      for(String key in formData.keys){
+        final FocusNode sigleItemFocusNode = formData[key]['focusNode'];
+        sigleItemFocusNode!.unfocus();
+      }
+    }
+  }
+
+  // 获取表单的值
+  dynamic _getFormFieldValue({List<String>? keys, String? keyStr}) {
+    if(keyStr!.isEmpty){
+      if(keys!.isNotEmpty){
+        // 遍历keys获取指定多个 keys 的表单value
+        Map<String, dynamic> resultValueMap = {};
+        for (String itemStr in keys!) {
+          TextEditingController sigleItemController = state.formData[itemStr]!['controller'];
+          resultValueMap[itemStr] = sigleItemController.text;
+        }
+        return resultValueMap;
+      }
+    }else if(keyStr!.isNotEmpty){
+      // 获取单个表单的value
+      final TextEditingController sigleItemController = state.formData[keyStr]!['controller'];
+      return sigleItemController.text;
+    }
+  }
+
+  ///提交反馈
+  void submitNewsfeedPost() {
+    state = state.copyWith(mindFieldErrorText: null);
+
+    _dismissKeyboard(keyStr: 'mind');
+
+    // 获取表单的值
+    String mindValue = _getFormFieldValue(keyStr: 'mind');
+
+    Log.d('当前待提交的 mind:$mindValue  imgList:${state.imgList}');
+
+
+    if (Utils.isEmpty(mindValue)) {
+      state = state.copyWith(mindFieldErrorText: "Mind cannot be empty!");
+      ToastEngine.show("${state.mindFieldErrorText}");
+      return;
+    }
+
+    //去成功页面
+    // FeedbackCreateSuccessPage.startInstance();
+    // 返回上一页
+  }
+
+  //选中图片
+  void setImgList(List<String> list) {
+    state = state.copyWith(imgList: list);
+  }
+
+  //初始化监听
+  void initListener(NewsfeedPostPageState initState) {
+
+    // 获取表单的焦点节点
+    final FocusNode focusNode = getFocusNode(state.formData, 'mind');
+
+    focusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (focusNode.hasFocus) {
+        state = state.copyWith(mindFieldErrorText: null);
+      }
+    });
+  }
+
+  //销毁资源
+  void onDispose(NewsfeedPostPageState initState) {
+    // 获取表单的焦点节点
+    final FocusNode focusNode = getFocusNode(state.formData, 'mind');
+    focusNode.dispose();
+
+    Log.d("NewsfeedPostPageState 销毁 onDispose");
+  }
+
+
+}

+ 1 - 1
packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_vm.g.dart

@@ -6,7 +6,7 @@ part of 'newsfeed_post_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$newsfeedPostVmHash() => r'3717034c813e1d4cf8b2f212aa15ab483c6f220e';
+String _$newsfeedPostVmHash() => r'fe82190c049d9a9e370a5c4f0b6aba182b73b27f';
 
 /// See also [NewsfeedPostVm].
 @ProviderFor(NewsfeedPostVm)

+ 39 - 33
packages/cpt_community/lib/modules/newsfeed/newsfeed_tabs.dart

@@ -1,4 +1,3 @@
-import 'package:cpt_community/modules/newsfeed/newsfeed_vm.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
@@ -12,31 +11,37 @@ import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_text_view.dart';
 import 'package:widgets/my_appbar.dart';
 
-import '../community/community_vm.dart';
-import '../garagesale/garagesale_vm.dart';
+import 'community_vm.dart';
+import '../garage/garage_vm.dart';
 
 class NewsfeedTabs extends HookConsumerWidget {
   List tabsList;
   Widget? Function(BuildContext)? tabItemBuilder;
-  VoidCallback? onClickAction;
+  dynamic? tabsRouter;
+  void Function(int)? onClickAction;
   NewsfeedTabs({
     Key? key,
     required this.tabsList,
+    this.tabsRouter,
     this.onClickAction,
     this.tabItemBuilder
   }) : super(key: key);
 
   Widget _buildTabItem(BuildContext context, WidgetRef ref, vm, item, index) {
-    // 监听 activeIndex 的变化
-    final activeIndex = ref.watch(newsfeedVmProvider.select((state) => state.activeIndex));
+    // Log.d("NewsfeedTabs _buildTabItem index: ${vm.state.tabsList}");
+    // Log.d("NewsfeedTabs _buildTabItem index: ${vm.state.activeTabIdx}");
+    // 监听 activeTabIdx 的变化
+    // final activeTabIdx = ref.watch(communityVmProvider.select((state) => state.activeTabIdx));
 
+    final activeTabIdx = tabsRouter!.activeIndex;
 
+    // Log.d("NewsfeedTabs _buildTabItem activeTabIdx: $activeTabIdx");
     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"),
+      decoration: index==activeTabIdx? BoxDecoration(
+        color: index==activeTabIdx? context.appColors.btnBgDefault: ColorUtils.string2Color("#F2F3F6"),
         borderRadius: BorderRadius.circular(20),
         boxShadow: [
           BoxShadow(
@@ -53,47 +58,48 @@ class NewsfeedTabs extends HookConsumerWidget {
             child: Container(
               alignment: Alignment.center,
               child: MyTextView(
-                item['title'],
+                item,
                 fontSize: 16,
                 textAlign: TextAlign.center,
                 isFontMedium: true,
-                textColor: index == activeIndex ? Colors.white :ColorUtils.string2Color("#000000"),
+                textColor: index == activeTabIdx ? Colors.white :ColorUtils.string2Color("#000000"),
               ),
-            ),
+            ).onTap((){
+              print("newsfeed_tabs 中点击的tab index:  $index");
+              onClickAction?.call(index);
+            }),
           ),
         ],
       ),
-    ).onTap((){
-      vm.handlerClickTab(index, item);
-    });
+    );
   }
 
   List<Widget> _buildTabs(BuildContext context, WidgetRef ref, vm){
-
-    int currentUseTag = ref.watch(newsfeedVmProvider.select((state) => state.useTag!));
-
-    List tabsList = ref.read(newsfeedVmProvider).tabsList;
-
     int tabsLength = tabsList.length;
-
-    return List.generate(tabsLength, (index) {
-      return _buildTabItem(context, ref, vm, tabsList[index], index);
-    });
+    if(tabsLength>0){
+      return List.generate(tabsLength, (index) {
+        return _buildTabItem(context, ref, vm, tabsList[index], index);
+      });
+    }else{
+      return [
+        const SizedBox.shrink()
+      ];
+    }
   }
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final vm = ref.read(newsfeedVmProvider.notifier);
+    final vm = ref.read(communityVmProvider.notifier);
     // 使用useEffect钩子
-    useEffect(() {
-      print('副作用函数执行');
-      // 这里是副作用逻辑
-      // vm.initPropData(tabsList, tabItemBuilder, onClickAction);
-      // 返回清理函数
-      return () {
-        print('清理函数执行');
-      };
-    }, []); // 空依赖列表意味着这个副作用只在组件挂载时执行一次
+    // useEffect(() {
+    //   print('副作用函数执行');
+    //   // 这里是副作用逻辑
+    //   // vm.initPropData(tabsList, tabItemBuilder, onClickAction);
+    //   // 返回清理函数
+    //   return () {
+    //     print('清理函数执行');
+    //   };
+    // }, []); // 空依赖列表意味着这个副作用只在组件挂载时执行一次
 
     return SingleChildScrollView(
       scrollDirection: Axis.horizontal,

+ 80 - 0
packages/cpt_community/lib/modules/garage/for_rent/for_rent_page.dart

@@ -0,0 +1,80 @@
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package: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 'for_rent_vm.dart';
+
+@RoutePage()
+class ForrentPage extends HookConsumerWidget {
+  const ForrentPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const ForrentPageRoute());
+    } else {
+      appRouter.push(const ForrentPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(forrentVmProvider.notifier);
+    return const Scaffold(
+      // appBar: MyAppBar.appBar(
+      //   context,
+      //   "forrent",
+      //   backgroundColor: context.appColors.whiteBG,
+      // ),
+      // backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+        body: Column(
+          children: [
+            // Expanded(
+            //   child: EasyRefresh(
+            //     // 上拉加载
+            //     onLoad: () async{
+            //       Log.d("----onLoad");
+            //       vm.onLoadData();
+            //     },
+            //     // 下拉刷新
+            //     onRefresh: () async{
+            //       Log.d("----onRefresh");
+            //       vm.refreshListData();
+            //     },
+            //     child: _buildForrentList(context, ref, vm),
+            //   ),
+            // )
+            Text("FOR RENT PAGE"),
+          ],
+        )
+    );
+  }
+
+
+  Widget _buildForrentList(BuildContext context, WidgetRef ref, ForrentVm vm) {
+
+    return ListView.builder(
+      itemCount: 3,
+      itemBuilder: (context, index) {
+        return _buildListItem(context, ref, vm, index);
+      },
+    );
+  }
+
+  Widget _buildListItem(BuildContext context, WidgetRef ref, ForrentVm vm, int index) {
+    return Text("list-item");
+  }
+
+}

+ 71 - 0
packages/cpt_community/lib/modules/garage/for_rent/for_rent_respository.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 'for_rent_state.dart';
+
+part 'for_rent_respository.g.dart';
+
+@Riverpod(keepAlive: true)
+ForrentRepository forrentRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return ForrentRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class ForrentRepository {
+  DioEngine dioEngine;
+
+  ForrentRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchForrentList(
+      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 = ForrentState.fromMap(json!);
+      //重新赋值data或list
+      return result.convert<ForrentState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 27 - 0
packages/cpt_community/lib/modules/garage/for_rent/for_rent_respository.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'for_rent_respository.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$forrentRepositoryHash() => r'71a721607b225fc5d56217c1fc769af32a7510de';
+
+/// See also [forrentRepository].
+@ProviderFor(forrentRepository)
+final forrentRepositoryProvider = Provider<ForrentRepository>.internal(
+  forrentRepository,
+  name: r'forrentRepositoryProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$forrentRepositoryHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+@Deprecated('Will be removed in 3.0. Use Ref instead')
+// ignore: unused_element
+typedef ForrentRepositoryRef = ProviderRef<ForrentRepository>;
+// 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

+ 57 - 0
packages/cpt_community/lib/modules/garage/for_rent/for_rent_state.dart

@@ -0,0 +1,57 @@
+class ForrentState {
+  int? activeTabIndex =0;
+  int? curPage =0;
+  int? pageSize =10;
+  int? filterCount =0;
+  List<String>? tabsList = ['For Sale', 'For Rent'];
+  List<Map<String, dynamic>>? list = [];
+
+  ForrentState({
+    this.activeTabIndex,
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    this.tabsList,
+    this.list,
+  });
+
+  ForrentState copyWith({
+    int? activeTabIndex,
+    int? curPage,
+    int? pageSize,
+    int? filterCount,
+    List<String>? tabsList,
+    List<Map<String, dynamic>>? list,
+  }) {
+    return ForrentState(
+      activeTabIndex: activeTabIndex ?? this.activeTabIndex,
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      filterCount: filterCount ?? this.filterCount,
+      tabsList: tabsList ?? this.tabsList,
+      list: list ?? this.list,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'activeTabIndex': this.activeTabIndex,
+      'curPage': this.curPage,
+      'pageSize': this.pageSize,
+      'filterCount': this.filterCount,
+      'tabsList': this.tabsList,
+      'list': this.list,
+    };
+  }
+
+  factory ForrentState.fromMap(Map<String, dynamic> map) {
+    return ForrentState(
+      activeTabIndex: map['activeTabIndex'] as int,
+      curPage: map['curPage'] as int,
+      pageSize: map['pageSize'] as int,
+      filterCount: map['filterCount'] as int,
+      tabsList: map['tabsList'] as List<String>,
+      list: map['list'] as List<Map<String, dynamic>>,
+    );
+  }
+}

+ 196 - 0
packages/cpt_community/lib/modules/garage/for_rent/for_rent_vm.dart

@@ -0,0 +1,196 @@
+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:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import '../../../router/page/community_page_router.dart';
+import '../garagesale_detail/garagesale_detail_page.dart';
+import 'for_rent_respository.dart';
+import 'for_rent_state.dart';
+
+part 'for_rent_vm.g.dart';
+
+@riverpod
+class ForrentVm extends _$ForrentVm {
+  late ForrentRepository ForrentRepositoryInstance;
+  ForrentState initState() {
+    return ForrentState(
+        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
+          },
+          {
+            'id':4,
+            '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
+          },
+          {
+            'id':5,
+            '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
+          },
+          {
+            'id':6,
+            '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
+          },
+          {
+            'id':7,
+            'avator': Assets.communityCamera,
+            'title': '放大发大水',
+            '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
+  ForrentState build(){
+    // 引入数据仓库
+    ForrentRepositoryInstance = ref.read(forrentRepositoryProvider);
+    final state = initState();
+    Log.d("--------------------------build---------------------");
+
+    return state;
+  }
+
+  // 设置当前的 tabsRouter 和 pageController
+  Future setTabsRouterAndPageController(dynamic tabsRouter, dynamic pageController) async{
+    Log.d("setTabsRouterAndPageController---:$tabsRouter");
+  }
+
+// 上拉加载
+  Future onLoadData() async {
+    Log.d("----Forrent_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 ForrentRepositoryInstance.fetchForrentList(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_forrent_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(ForrentVmProvider);
+    getListData();
+
+  }
+
+
+  // 点击 like comments  share
+  void handlerClickActionBtn(String? actionStr, item){
+    final id = item['id'];
+    switch (actionStr) {
+      case 'like':
+        Log.d("点击了 点赞");
+        handlerGotoDetail(id);
+        break;
+      case 'comments':
+        Log.d("点击了 评论");
+        handlerGotoDetail(id);
+        break;
+      case 'share':
+        Log.d("点击了 分享");
+        handlerGotoDetail(id);
+        break;
+      default:
+        break;
+    }
+  }
+  // 去详情页面
+  void handlerGotoDetail(id){
+    Log.d("去详情页面");
+    appRouter.push(GaragesaleDetailPageRoute(id: id, type: 'forrent'));
+  }
+}

+ 25 - 0
packages/cpt_community/lib/modules/garage/for_rent/for_rent_vm.g.dart

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

+ 138 - 0
packages/cpt_community/lib/modules/garage/for_sale/for_sale_page.dart

@@ -0,0 +1,138 @@
+import 'package:cpt_community/components/garage_card_content.dart';
+import 'package:cpt_community/components/garage_card_footer.dart';
+import 'package:cs_resources/generated/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/my_button.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 '../../../components/garage_card_header.dart';
+import '../../../components/newfeed_card_header.dart';
+import '../../../router/page/community_page_router.dart';
+import 'for_sale_vm.dart';
+
+@RoutePage()
+class ForsalePage extends HookConsumerWidget {
+  const ForsalePage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const ForsalePageRoute());
+    } else {
+      appRouter.push(const ForsalePageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(forsaleVmProvider.notifier);
+    return Scaffold(
+      // appBar: MyAppBar.appBar(
+      //   context,
+      //   "Forsale",
+      //   backgroundColor: context.appColors.whiteBG,
+      // ),
+      // backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+      body: Column(
+        children: [
+            Expanded(
+              child: EasyRefresh(
+                // 上拉加载
+                onLoad: () async{
+                  Log.d("----onLoad");
+                  vm.onLoadData();
+                },
+                // 下拉刷新
+                onRefresh: () async{
+                  Log.d("----onRefresh");
+                  vm.refreshListData();
+                },
+                child: _buildForsaleFeedList(context, ref, vm),
+              ),
+            )
+        ],
+      )
+    );
+  }
+
+  Widget _buildForsaleItem(BuildContext context, WidgetRef ref, item, vm){
+    return Container(
+      width: double.infinity,
+      //   color: Colors.yellow,
+      child: Stack(
+        children: [
+          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: [
+                  // 卡片头部(头像 标题 时间)
+                  GarageCardHeader(
+                    key: UniqueKey(),
+                    itemObj: item,
+                  ),
+                  const SizedBox(height: 15),
+                  // 卡片中间 (文字和图片)
+                  // Expanded(
+                  //   child: GarageCardContent(
+                  //     key: UniqueKey(),
+                  //     content: item['content'],
+                  //     imageUrls: item['imageUrls'],
+                  //   ),
+                  // ),
+                  const SizedBox(height: 26),
+                  // // 卡片底部 (点赞 评论 分享)
+                  // GarageCardFooter(
+                  //     key: UniqueKey(),
+                  //     isLike: item['isLike'],
+                  //     onLike: (){
+                  //       vm.handlerClickActionBtn('like', item);
+                  //     },
+                  //     onComment: (){
+                  //       vm.handlerClickActionBtn('comments', item);
+                  //     },
+                  //     onShare: (){
+                  //       vm.handlerClickActionBtn('share', item);
+                  //     },
+                  // ),
+                ]
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildForsaleFeedList(BuildContext context, WidgetRef ref, vm){
+    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(
+        key: UniqueKey(),
+        itemCount: itemsList.length,
+        itemBuilder: (context, index) {
+          return _buildForsaleItem(context, ref, itemsList[index], vm);
+        },
+      );
+    }
+    // return Text("879424");
+  }
+}

+ 71 - 0
packages/cpt_community/lib/modules/garage/for_sale/for_sale_respository.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 'for_sale_state.dart';
+
+part 'for_sale_respository.g.dart';
+
+@Riverpod(keepAlive: true)
+ForsaleRepository newsRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return ForsaleRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class ForsaleRepository {
+  DioEngine dioEngine;
+
+  ForsaleRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchForsaleList(
+      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 = ForsaleState.fromMap(json!);
+      //重新赋值data或list
+      return result.convert<ForsaleState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 27 - 0
packages/cpt_community/lib/modules/garage/for_sale/for_sale_respository.g.dart

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

+ 57 - 0
packages/cpt_community/lib/modules/garage/for_sale/for_sale_state.dart

@@ -0,0 +1,57 @@
+class ForsaleState {
+  int? activeTabIndex =0;
+  int? curPage =0;
+  int? pageSize =10;
+  int? filterCount =0;
+  List<String>? tabsList = ['For Sale', 'For Rent'];
+  List<Map<String, dynamic>>? list = [];
+
+  ForsaleState({
+    this.activeTabIndex,
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    this.tabsList,
+    this.list,
+  });
+
+  ForsaleState copyWith({
+    int? activeTabIndex,
+    int? curPage,
+    int? pageSize,
+    int? filterCount,
+    List<String>? tabsList,
+    List<Map<String, dynamic>>? list,
+  }) {
+    return ForsaleState(
+      activeTabIndex: activeTabIndex ?? this.activeTabIndex,
+      curPage: curPage ?? this.curPage,
+      pageSize: pageSize ?? this.pageSize,
+      filterCount: filterCount ?? this.filterCount,
+      tabsList: tabsList ?? this.tabsList,
+      list: list ?? this.list,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'activeTabIndex': this.activeTabIndex,
+      'curPage': this.curPage,
+      'pageSize': this.pageSize,
+      'filterCount': this.filterCount,
+      'tabsList': this.tabsList,
+      'list': this.list,
+    };
+  }
+
+  factory ForsaleState.fromMap(Map<String, dynamic> map) {
+    return ForsaleState(
+      activeTabIndex: map['activeTabIndex'] as int,
+      curPage: map['curPage'] as int,
+      pageSize: map['pageSize'] as int,
+      filterCount: map['filterCount'] as int,
+      tabsList: map['tabsList'] as List<String>,
+      list: map['list'] as List<Map<String, dynamic>>,
+    );
+  }
+}

+ 185 - 0
packages/cpt_community/lib/modules/garage/for_sale/for_sale_vm.dart

@@ -0,0 +1,185 @@
+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:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
+
+import '../../../router/page/community_page_router.dart';
+import '../garagesale_detail/garagesale_detail_page.dart';
+import 'for_sale_respository.dart';
+import 'for_sale_state.dart';
+
+part 'for_sale_vm.g.dart';
+
+@riverpod
+class ForsaleVm extends _$ForsaleVm {
+  late ForsaleRepository ForsaleRepositoryInstance;
+  ForsaleState initState() {
+    return ForsaleState(
+      list: [
+          {
+            'id':1,
+            'goods_img':  'https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg',
+            'title': 'Electronic keyboard',
+            'price': '\$66',
+            'isCollection': true,
+            'collection_num': '12',
+            'publisher': 'William Jefferson',
+            'publish_time': 'June 17,2016 at 7:23 p.m.',
+            'publisher_avator': Assets.communityCamera
+          },
+          {
+            'id':2,
+            'goods_img':  'https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg',
+            'title': 'Electronic keyboard',
+            'price': '\$88',
+            'isCollection': false,
+            'collection_num': '12',
+            'publisher': 'William Jefferson',
+            'publish_time': 'June 17,2016 at 7:23 p.m.',
+            'publisher_avator': Assets.communityCamera
+          },
+          {
+            'id':3,
+            'goods_img':  'https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg',
+            'title': 'Electronic keyboard',
+            'price': '\$66',
+            'isCollection': true,
+            'collection_num': '12',
+            'publisher': 'William Jefferson',
+            'publish_time': 'June 17,2016 at 7:23 p.m.',
+            'publisher_avator': Assets.communityCamera
+          },
+          {
+            'id':4,
+            'goods_img':  'https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg',
+            'title': 'Electronic keyboard',
+            'price': '\$88',
+            'isCollection': false,
+            'collection_num': '12',
+            'publisher': 'William Jefferson',
+            'publish_time': 'June 17,2016 at 7:23 p.m.',
+            'publisher_avator': Assets.communityCamera
+          },
+          {
+            'id':5,
+            'goods_img':  'https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg',
+            'title': 'Electronic keyboard',
+            'price': '\$66',
+            'isCollection': true,
+            'collection_num': '12',
+            'publisher': 'William Jefferson',
+            'publish_time': 'June 17,2016 at 7:23 p.m.',
+            'publisher_avator': Assets.communityCamera
+          },
+          {
+            'id':6,
+            'goods_img':  'https://img.alicdn.com/tfs/TB1h.o9O4MPMeJjy1XaXXcSsFXa-640-360.jpg',
+            'title': 'Electronic keyboard',
+            'price': '\$88',
+            'isCollection': false,
+            'collection_num': '12',
+            'publisher': 'William Jefferson',
+            'publish_time': 'June 17,2016 at 7:23 p.m.',
+            'publisher_avator': Assets.communityCamera
+          },
+      ]
+    );
+  }
+
+  @override
+  ForsaleState build(){
+    // 引入数据仓库
+    ForsaleRepositoryInstance = ref.read(newsRepositoryProvider);
+    final state = initState();
+    Log.d("--------------------------build---------------------");
+
+    return state;
+  }
+
+   // 设置当前的 tabsRouter 和 pageController
+  Future setTabsRouterAndPageController(dynamic tabsRouter, dynamic pageController) async{
+    Log.d("setTabsRouterAndPageController---:$tabsRouter");
+  }
+
+// 上拉加载
+  Future onLoadData() async {
+    Log.d("----Forsale_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 ForsaleRepositoryInstance.fetchForsaleList(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(ForsaleVmProvider);
+    getListData();
+
+  }
+
+
+  // 点击 like comments  share
+  void handlerClickActionBtn(String? actionStr, item){
+    final id = item['id'];
+    switch (actionStr) {
+      case 'like':
+        Log.d("点击了 点赞");
+        handlerGotoDetail(id);
+        break;
+      case 'comments':
+        Log.d("点击了 评论");
+        handlerGotoDetail(id);
+        break;
+      case 'share':
+        Log.d("点击了 分享");
+        handlerGotoDetail(id);
+        break;
+      default:
+        break;
+    }
+  }
+  // 去详情页面
+  void handlerGotoDetail(id){
+    Log.d("去详情页面");
+    appRouter.push(GaragesaleDetailPageRoute(id: id, type: 'forsale'));
+  }
+}

+ 25 - 0
packages/cpt_community/lib/modules/garage/for_sale/for_sale_vm.g.dart

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

+ 278 - 0
packages/cpt_community/lib/modules/garage/garage_page.dart

@@ -0,0 +1,278 @@
+
+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:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:flutter/rendering.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_appbar.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 '../garage/garage_vm.dart';
+
+import 'garage_tabs.dart';
+
+import 'garage_vm.dart';
+
+
+@RoutePage()
+class GaragePage extends HookConsumerWidget {
+  const GaragePage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const GaragePageRoute());
+    } else {
+      appRouter.push(const GaragePageRoute());
+    }
+  }
+
+  Widget _buildTabsSection(BuildContext context, WidgetRef ref, tabsRouter){
+    final vm = ref.read(garageVmProvider.notifier);
+    return Container(
+      width: double.infinity,
+      padding: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
+      child: GarageTabs(
+        key: UniqueKey(),
+        tabsList: vm.state.tabsList,
+        tabsRouter: tabsRouter,
+        onClickAction:(activeTabIdx){
+          vm.handlerChangeTab(activeTabIdx, tabsRouter);
+        }
+      ),
+    );
+  }
+
+  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: Row(
+              children: [
+                Expanded(
+                  child: Container(
+                    // height: 65.5,
+                    // color: Colors.blue,
+                    child: MyTextView(
+                      "Sell Item",
+                      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(context);
+            }),
+          ),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildNewsItem(BuildContext context, WidgetRef ref, item, vm){
+    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(
+                  key: UniqueKey(),
+                  title: item['title'],
+                  avator: item['avator'],
+                  time: item['time'],
+                ),
+                const SizedBox(height: 15),
+                // 卡片中间 (文字和图片)
+                Expanded(
+                  child: NewsFeedCardContent(
+                    key: UniqueKey(),
+                    content: item['content'],
+                    imageUrls: item['imageUrls'],
+                  ),
+                ),
+                const SizedBox(height: 26),
+                // // 卡片底部 (点赞 评论 分享)
+                NewsFeedCardFooter(
+                  key: UniqueKey(),
+                  isLike: item['isLike'],
+                ),
+              ]
+          ),
+        )
+    );
+  }
+
+  Widget _buildNewsFeedList(BuildContext context, WidgetRef ref, vm){
+    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(
+        key: UniqueKey(),
+        itemCount: itemsList.length,
+        itemBuilder: (context, index) {
+          return _buildNewsItem(context, ref, itemsList[index], vm);
+        },
+      );
+    }
+  }
+
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.read(garageVmProvider.notifier);
+
+    return Scaffold(
+      appBar: MyAppBar.searchAppBar(
+        context,
+        backgroundColor: context.appColors.whiteBG,
+        actions: [
+          IconButton(
+            icon: const Icon(Icons.search),
+            onPressed: () {
+              // do something
+            },
+          ),
+        ],
+      ),
+      backgroundColor: ColorUtils.string2Color("#F2F3F6"),
+      body: NestedScrollView(
+        headerSliverBuilder: (context, innerBoxIsScrolled) {
+          return [
+            SliverToBoxAdapter(
+              child: Consumer(
+                builder: (context, ref, _) {
+                  return _buildTopSection(context, ref, vm);
+                },
+              ),
+            ),
+          ];
+        },
+        body: NotificationListener<ScrollNotification>(
+          onNotification: (ScrollNotification notification) {
+            // 是否拦截滚动  false 表示不拦截通知
+            // return _isPreventScroll(notification, ref);
+            return false;
+          },
+          child: AutoTabsRouter.pageView(
+            key: UniqueKey(),
+            routes: const [
+              ForsalePageRoute(),
+              ForrentPageRoute(),
+            ],
+            builder: (context, child, animation) {
+              final tabsRouter = AutoTabsRouter.of(context);
+              return Column(
+                children: [
+                  //  garagesale tab 分类 (For sale  For Rent)
+                  _buildTabsSection(context, ref, tabsRouter),
+                  // 发布 garage sale 组件
+                  _buildPostSection(context, ref, vm),
+                  Expanded(
+                    child: child,
+                  )
+                ],
+              );
+            },
+          ),
+        ),
+      ),
+    );
+  }
+
+  Widget _buildTopSection(BuildContext context, WidgetRef ref, vm) {
+    final topSectionsData = vm.topSectionsData;
+    int curTagIdx = 1;
+    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: index == curTagIdx ? [
+                        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(() {
+                      vm.handlerChangeCommunityType(context,index);
+                    },
+                      type: ClickType.throttle,
+                    ),
+                  ),
+                  SizedBox.fromSize(size: const Size(0, 9)),
+                  MyTextView(
+                    item['title'],
+                    fontSize: 15,
+                    textColor: index == curTagIdx ? ColorUtils.string2Color('#4161D0'):Colors.black,
+                    textAlign: TextAlign.center,
+                    isFontMedium: true,
+                  ),
+                ],
+              ),
+            ).marginOnly(left: 18, right: 18, top: 10, bottom: 10);
+          }),
+        ),
+      ),
+    );
+  }
+}

+ 71 - 0
packages/cpt_community/lib/modules/garage/garage_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 'garage_state.dart';
+
+part 'garage_repository.g.dart';
+
+@Riverpod(keepAlive: true)
+GarageRepository garageRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return GarageRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class GarageRepository {
+  DioEngine dioEngine;
+
+  GarageRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchGarageList(
+      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 = GarageState.fromMap(json!);
+      //重新赋值data或list
+      return result.convert<GarageState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 27 - 0
packages/cpt_community/lib/modules/garage/garage_repository.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'garage_repository.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$garageRepositoryHash() => r'93e545c5f107ba1eb1f1e188d7a4744046d0da64';
+
+/// See also [garageRepository].
+@ProviderFor(garageRepository)
+final garageRepositoryProvider = Provider<GarageRepository>.internal(
+  garageRepository,
+  name: r'garageRepositoryProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$garageRepositoryHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+@Deprecated('Will be removed in 3.0. Use Ref instead')
+// ignore: unused_element
+typedef GarageRepositoryRef = ProviderRef<GarageRepository>;
+// 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

+ 19 - 21
packages/cpt_community/lib/modules/garagesale/garagesale_state.dart

@@ -2,8 +2,8 @@ import 'package:cs_resources/generated/assets.dart';
 import 'package:flutter/material.dart';
 import 'package:shared/utils/color_utils.dart';
 
-class GaragesaleState {
-  int? useTag;
+class GarageState {
+  List<Map<String, dynamic>>? topSectionsData;
   int? curPage;
   int? pageSize;
   int? filterCount;
@@ -11,10 +11,18 @@ class GaragesaleState {
   List tabsList = [];
   List? list = [];
 
+  GarageState({
+    this.topSectionsData,
+    this.curPage,
+    this.pageSize,
+    this.filterCount,
+    this.activeIndex,
+    required this.tabsList,
+    this.list,
+  });
 
-
-  GaragesaleState copyWith({
-    int? useTag,
+  GarageState copyWith({
+    List<Map<String, dynamic>>? topSectionsData,
     int? curPage,
     int? pageSize,
     int? filterCount,
@@ -22,8 +30,8 @@ class GaragesaleState {
     List? tabsList,
     List? list,
   }) {
-    return GaragesaleState(
-      useTag: useTag ?? this.useTag,
+    return GarageState(
+      topSectionsData: topSectionsData ?? this.topSectionsData,
       curPage: curPage ?? this.curPage,
       pageSize: pageSize ?? this.pageSize,
       filterCount: filterCount ?? this.filterCount,
@@ -35,7 +43,7 @@ class GaragesaleState {
 
   Map<String, dynamic> toMap() {
     return {
-      'useTag': this.useTag,
+      'topSectionsData': this.topSectionsData,
       'curPage': this.curPage,
       'pageSize': this.pageSize,
       'filterCount': this.filterCount,
@@ -45,9 +53,9 @@ class GaragesaleState {
     };
   }
 
-  factory GaragesaleState.fromMap(Map<String, dynamic> map) {
-    return GaragesaleState(
-      useTag: map['useTag'] as int,
+  factory GarageState.fromMap(Map<String, dynamic> map) {
+    return GarageState(
+      topSectionsData: map['topSectionsData'] as List<Map<String, dynamic>>,
       curPage: map['curPage'] as int,
       pageSize: map['pageSize'] as int,
       filterCount: map['filterCount'] as int,
@@ -56,14 +64,4 @@ class GaragesaleState {
       list: map['list'] as List,
     );
   }
-
-  GaragesaleState({
-    this.useTag,
-    this.curPage,
-    this.pageSize,
-    this.filterCount,
-    this.activeIndex,
-    required this.tabsList,
-    this.list,
-  });
 }

+ 17 - 17
packages/cpt_community/lib/modules/garagesale/garagesale_tabs.dart

@@ -1,4 +1,3 @@
-import 'package:cpt_community/modules/newsfeed/newsfeed_vm.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
@@ -13,30 +12,31 @@ import 'package:widgets/my_text_view.dart';
 import 'package:widgets/my_appbar.dart';
 
 import '../community/community_vm.dart';
-import '../garagesale/garagesale_vm.dart';
+import '../garage/garage_vm.dart';
 
-class GaragesaleTabs extends HookConsumerWidget {
+class GarageTabs extends HookConsumerWidget {
   List tabsList;
   Widget? Function(BuildContext)? tabItemBuilder;
-  VoidCallback? onClickAction;
-  GaragesaleTabs({
+  dynamic? tabsRouter;
+  void Function(int)? onClickAction;
+  GarageTabs({
     Key? key,
     required this.tabsList,
+    this.tabsRouter,
     this.onClickAction,
     this.tabItemBuilder
   }) : super(key: key);
 
   Widget _buildTabItem(BuildContext context, WidgetRef ref, vm, item, index) {
     // 监听 activeIndex 的变化
-    final activeIndex = ref.watch(garagesaleVmProvider.select((state) => state.activeIndex));
-
+    final activeTabIdx = tabsRouter!.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"),
+      decoration: index==activeTabIdx? BoxDecoration(
+        color: index==activeTabIdx? context.appColors.btnBgDefault: ColorUtils.string2Color("#F2F3F6"),
         borderRadius: BorderRadius.circular(20),
         boxShadow: [
           BoxShadow(
@@ -57,22 +57,22 @@ class GaragesaleTabs extends HookConsumerWidget {
                 fontSize: 16,
                 textAlign: TextAlign.center,
                 isFontMedium: true,
-                textColor: index == activeIndex ? Colors.white :ColorUtils.string2Color("#000000"),
+                textColor: index == activeTabIdx ? Colors.white :ColorUtils.string2Color("#000000"),
               ),
-            ),
+            ).onTap((){
+              print("garage_tabs 中点击的tab index:  $index");
+              onClickAction?.call(index);
+            }),
           ),
         ],
       ),
-    ).onTap((){
-      vm.handlerClickTab(index, item);
-    });
+    );
   }
 
   List<Widget> _buildTabs(BuildContext context, WidgetRef ref, vm){
 
-    int currentUseTag = ref.watch(garagesaleVmProvider.select((state) => state.useTag!));
 
-    List tabsList = ref.read(garagesaleVmProvider).tabsList;
+    List tabsList = ref.read(garageVmProvider).tabsList;
 
     int tabsLength = tabsList.length;
 
@@ -83,7 +83,7 @@ class GaragesaleTabs extends HookConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final vm = ref.read(garagesaleVmProvider.notifier);
+    final vm = ref.read(garageVmProvider.notifier);
     // 使用useEffect钩子
     useEffect(() {
       print('副作用函数执行');

+ 43 - 21
packages/cpt_community/lib/modules/garagesale/garagesale_vm.dart

@@ -1,4 +1,5 @@
 
+import 'package:cpt_community/modules/community/community_page.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:flutter/material.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
@@ -8,18 +9,33 @@ import 'package:shared/utils/color_utils.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:auto_route/auto_route.dart';
 
-import 'garagesale_state.dart';
-import 'garagesale_repository.dart';
+import 'garage_page.dart';
+import 'garage_state.dart';
+import 'garage_repository.dart';
 
-part 'garagesale_vm.g.dart';
+part 'garage_vm.g.dart';
 
 @riverpod
-class GaragesaleVm extends _$GaragesaleVm {
-  late GaragesaleRepository garagesaleRepository;
-  GaragesaleState initState() {
-    return GaragesaleState(
-        useTag: 1,
+class GarageVm extends _$GarageVm {
+  late GarageRepository garageRepository;
+  get topSectionsData => state.topSectionsData;
+  GarageState initState() {
+    return GarageState(
         activeIndex: 0,
+        topSectionsData: [
+          {
+            "title": "News Feed",
+            "icon": Assets.communityNesFeed,
+            "pageStartInstanceFn": CommunityPage.startInstance,
+            "page": const CommunityPage(),
+          },
+          {
+            "title": "Garage Sale",
+            "icon": Assets.communityGarageSale,
+            "pageStartInstanceFn": GaragePage.startInstance,
+            "page": const GaragePage(),
+          },
+        ],
         tabsList: [
           {
             'title': 'For Sale',
@@ -65,17 +81,17 @@ class GaragesaleVm extends _$GaragesaleVm {
     );
   }
   @override
-  GaragesaleState build(){
+  GarageState build(){
     // 引入数据仓库
-    garagesaleRepository = ref.read(garagesaleRepositoryProvider);
+    garageRepository = ref.read(garageRepositoryProvider);
     // 初始化状态
-    GaragesaleState state = initState();
+    GarageState state = initState();
     return state;
   }
 
   // 上拉加载
   Future onLoadData() async {
-    Log.d("----garagesale_vm-----initListData");
+    Log.d("----garage_vm-----initListData");
     // await Future.delayed(const Duration(seconds: 2));
     // if(state.list.length >= state.filterCount){
     //   return;
@@ -97,7 +113,7 @@ class GaragesaleVm extends _$GaragesaleVm {
         "pageSize": state.pageSize,
       };
       Log.d("请求参数------$params");
-      final result = await garagesaleRepository.fetchGaragesaleList(params);
+      final result = await garageRepository.fetchGarageList(params);
       Log.d("请求完成结果------${result.data}");
       //校验成功失败
       if (result.isSuccess) {
@@ -115,31 +131,37 @@ class GaragesaleVm extends _$GaragesaleVm {
 
   // 下拉刷新
   Future refreshListData() async {
-    Log.d("----garagesale_vm-----refreshListData ");
+    Log.d("----garage_vm-----refreshListData ");
 
     // await Future.delayed(const Duration(seconds: 2));
 
     state = state.copyWith(curPage: 1, pageSize: 10);
     // ref.invalidateSelf();
-    // ref.invalidate(garagesaleVmProvider);
+    // ref.invalidate(garageVmProvider);
     getListData();
 
   }
 
+  // 切换tab
+  handlerChangeTab(int index, tabsRouter) {
+    tabsRouter.setActiveIndex(index);
+    // state = state.copyWith(tabsRouter: tabsRouter ,activeTabIdx: index);
+    Log.d("garage_vm handlerChangeTab--index:    $index");
+  }
 
 
   // 点击发布的按钮 跳转到发布的页面
   void handlerGotoPost(context){
     // ComponentServiceManager().communityService.startCommunityPage();
-
     AutoRouter.of(context).pushNamed(RouterPath.garageSalePost);
   }
 
-  // 点击tab
-  void handlerClickTab(int index, item){
-    state = state.copyWith(activeIndex: index);
-    print("切换后新的 sate, ${state.tabsList}");
 
-    // ref.invalidate(customTabsVmProvider);
+  handlerChangeCommunityType(context, int index){
+    if(index == 0){
+      // 返回到 newsfeed 页面
+      Navigator.pop(context);
+    }
   }
+
 }

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

@@ -1,25 +1,25 @@
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
-part of 'garagesale_vm.dart';
+part of 'garage_vm.dart';
 
 // **************************************************************************
 // RiverpodGenerator
 // **************************************************************************
 
-String _$garagesaleVmHash() => r'd531a4a4393b7310a34957d2636d8be9f4a3d697';
+String _$garageVmHash() => r'04b50f6dd914e6c44422b4ca33154dddf07e4cd0';
 
-/// See also [GaragesaleVm].
-@ProviderFor(GaragesaleVm)
-final garagesaleVmProvider =
-    AutoDisposeNotifierProvider<GaragesaleVm, GaragesaleState>.internal(
-  GaragesaleVm.new,
-  name: r'garagesaleVmProvider',
+/// See also [GarageVm].
+@ProviderFor(GarageVm)
+final garageVmProvider =
+    AutoDisposeNotifierProvider<GarageVm, GarageState>.internal(
+  GarageVm.new,
+  name: r'garageVmProvider',
   debugGetCreateSourceHash:
-      const bool.fromEnvironment('dart.vm.product') ? null : _$garagesaleVmHash,
+      const bool.fromEnvironment('dart.vm.product') ? null : _$garageVmHash,
   dependencies: null,
   allTransitiveDependencies: null,
 );
 
-typedef _$GaragesaleVm = AutoDisposeNotifier<GaragesaleState>;
+typedef _$GarageVm = AutoDisposeNotifier<GarageState>;
 // 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

+ 8 - 5
packages/cpt_community/lib/modules/garagesale/garagesale_detail/garagesale_detail_page.dart

@@ -8,17 +8,20 @@ import 'package:widgets/my_appbar.dart';
 
 @RoutePage()
 class GaragesaleDetailPage extends HookConsumerWidget {
-  const GaragesaleDetailPage({Key? key}) : super(key: key);
+  final int? id;
+  final String? type;  // forsale  forrent
 
-  //启动当前页面
-  static void startInstance({BuildContext? context}) {
+  const GaragesaleDetailPage({Key? key, required this.id, required this.type}) : super(key: key);
+  // 启动当前页面
+  static void startInstance({BuildContext? context, int? id, String? type = 'forsale'}) {
     if (context != null) {
-      context.router.push(const GaragesaleDetailPageRoute());
+      context.router.push(GaragesaleDetailPageRoute(id: id, type: type));
     } else {
-      appRouter.push(const GaragesaleDetailPageRoute());
+      appRouter.push(GaragesaleDetailPageRoute(id: id, type: type));
     }
   }
 
+
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     // final viewModel = ref.watch(newsfeedPostVmProvider.notifier);

packages/cpt_community/lib/modules/garagesale/garagesale_myposts/garagesale_myposts_page.dart → packages/cpt_community/lib/modules/garage/garagesale_myposts/garagesale_myposts_page.dart


+ 317 - 0
packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_page.dart

@@ -0,0 +1,317 @@
+import 'package:cpt_community/router/page/community_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:plugin_platform/engine/image/image_nine_grid.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_button.dart';
+import 'package:widgets/my_text_field.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:widgets/shatter/picker_container.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/ext/ex_widget.dart';
+
+
+import 'garagesale_post_vm.dart';
+
+@RoutePage()
+class GaragesalePostPage extends HookConsumerWidget {
+  const GaragesalePostPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const GaragesalePostPageRoute());
+    } else {
+      appRouter.push(const GaragesalePostPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final vm = ref.watch(garagesalePostVmProvider.notifier);
+    final state = ref.watch(garagesalePostVmProvider);
+    // print("9999999999999999999 ${state.titleErrorText}");
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        "Post New Item",
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      backgroundColor: Colors.white,
+      body: Column(
+          children: [
+            Expanded(
+                child: SingleChildScrollView(
+                    scrollDirection: Axis.vertical,
+                    physics: const BouncingScrollPhysics(),
+                    clipBehavior: Clip.none,
+                    child: Column(
+                        children: [
+                          // sale 选择
+                          Container(
+                            margin: const EdgeInsets.only(left:15, right:15, top: 5),
+                            child: _buildSaleInputSelectCmp(context, ref),
+                          ),
+                          // category 选择
+                          Container(
+                            margin: const EdgeInsets.only(left:15, right:15, top: 5),
+                            child: _buildCategoryInputSelectCmp(context, ref),
+                          ),
+                          // title
+                          Container(
+                            margin: const EdgeInsets.only(left:15, right:15, top: 15),
+                            child: Column(
+                              crossAxisAlignment: CrossAxisAlignment.start,
+                              children: [
+                                FormRequireText(
+                                  text: "Title",
+                                  textColor: context.appColors.textBlack,
+                                  fontSize: 17,
+                                ).marginOnly(bottom: 14.5),
+                                _buildInputLayout(
+                                  context,
+                                  ref,
+                                  state,
+                                  'title',
+                                  marginTop: 16,
+                                  textInputType: TextInputType.text,
+                                  textInputAction: TextInputAction.next,
+                                  errorText: state.titleErrorText,
+                                  onSubmit: (formKey, value) {
+                                    state!.formData[formKey]!['focusNode'].unfocus();
+                                    FocusScope.of(context).requestFocus(state.formData['description']!['focusNode']);
+                                  },
+                                ),
+                              ]
+                            )
+                          ),
+                          // description
+                          Container(
+                            margin: const EdgeInsets.only(left:15, right:15,top: 15),
+                            child: Column(
+                                crossAxisAlignment: CrossAxisAlignment.start,
+                                children: [
+                                  FormRequireText(
+                                    text: "Description",
+                                    textColor: context.appColors.textBlack,
+                                    fontSize: 17,
+                                  ).marginOnly(bottom: 14.5),
+                                  _buildTextArea(context, ref, 'description',),
+                                ]
+                            )
+
+                          ),
+                          Container(
+                            width: double.infinity,
+                            height: 200,
+                            color: Colors.white,
+                            margin: const EdgeInsets.only(left:15, right:15, top: 15, bottom: 20),
+                            // 选择图片上传 控件
+                            child: _buildImageSelectCmp(context, ref,vm),
+                          ),
+                        ]
+                    )
+                )
+            ),
+            // 底部 按钮
+            Container(
+              child: Row(
+                  children: [
+                    Expanded(
+                      child: MyButton(
+                        text: "Add Card",
+                        radius: 0,
+                        minHeight: 50,
+                        backgroundColor: context.appColors.textPrimary,
+                        textColor: Colors.white,
+                        fontWeight: FontWeight.w500,
+                        fontSize: 16,
+                        onPressed: (){
+                          // Navigator.pop(context);
+                          vm.submitGaragesalePost();
+                        },
+                      ),
+                    ),
+                  ]
+              ),
+            )
+          ]
+      ),
+    );
+  }
+
+  /// textarea
+  Widget _buildTextArea(BuildContext context, WidgetRef ref, key){
+    final state = ref.watch(garagesalePostVmProvider);
+    final vm = ref.read(garagesalePostVmProvider.notifier);
+
+    return Container(
+      width: double.infinity,
+      height: 200,
+      padding: const EdgeInsets.all(15),
+      decoration: BoxDecoration(
+        color: context.appColors.authFiledBG,
+        borderRadius: BorderRadius.circular(5),
+      ),
+      child: _buildTextAreaLayout(
+        context,
+        ref,
+        key,
+      ),
+    );
+  }
+  /// 选择图片上传组件
+  Widget _buildImageSelectCmp(BuildContext context, WidgetRef ref,vm,){
+    final state = ref.watch(garagesalePostVmProvider);
+    return ImageNineGrid(
+      isSelectEnable: true,
+      maxImages: 10,
+      spacing: 10,
+      aspectRatio: 108 / 80,
+      initialImages: state.imgList,
+      onImagesChanged: (list) {
+        vm.setImgList(list);
+      },
+    );
+  }
+
+  /// 多行输入框
+  Widget _buildTextAreaLayout(BuildContext context, ref, key){
+    final state = ref.watch(garagesalePostVmProvider);
+    final vm = ref.read(garagesalePostVmProvider.notifier);
+    final noteCount = useState(0);
+
+    return Stack(
+        children: [
+          TextField(
+            cursorColor: context.appColors.authFiledText,
+            cursorWidth: 1.5,
+            autofocus: false,
+            enabled: true,
+            maxLines: null,
+            focusNode: state.formData[key]!['focusNode'],
+            controller: state.formData[key]!['controller'],
+            decoration: InputDecoration(
+              isDense: true,
+              isCollapsed: true,
+              border: InputBorder.none,
+              hintText: state.formData[key]!['hintText'],
+              hintStyle: TextStyle(
+                color: context.appColors.authFiledHint,
+                fontSize: 16.0,
+                fontWeight: FontWeight.w500,
+              ),
+            ),
+            style: TextStyle(
+              color: context.appColors.authFiledText,
+              fontSize: 16.0,
+              fontWeight: FontWeight.w500,
+            ),
+            textInputAction: TextInputAction.done,
+            onSubmitted: (value) {
+              FocusScope.of(context).unfocus();
+            },
+            expands: true,
+            onChanged: (text) {
+              // 当文本改变时,更新字符数量
+              noteCount.value = text.length;
+            },
+          ),
+          Positioned(
+            bottom: 0.0,
+            right: 0.0,
+            child: Text(
+              S.current.characters(noteCount.value),
+              style: TextStyle(
+                color: context.appColors.textBlack,
+                fontSize: 15.0,
+              ),
+            ),
+          ),
+        ]
+    );
+  }
+
+  /// sale 选择
+  Widget _buildSaleInputSelectCmp(BuildContext context, WidgetRef ref, ){
+    final vm = ref.read(garagesalePostVmProvider.notifier);
+    final state = ref.watch(garagesalePostVmProvider);
+    return PickerContainer(
+      content: state.saleSelectedOption ?? "",
+      hint: S.current.choose_category,
+      margin: const EdgeInsets.only(top: 16),
+      onClick: vm.pickSaleCallback,
+    );
+  }
+
+  /// category 选择
+  Widget _buildCategoryInputSelectCmp(BuildContext context, WidgetRef ref, ){
+    final vm = ref.read(garagesalePostVmProvider.notifier);
+    final state = ref.watch(garagesalePostVmProvider);
+    return PickerContainer(
+      content: state.categorySelectedOption ?? "",
+      hint: S.current.choose_category,
+      margin: const EdgeInsets.only(top: 16),
+      onClick: vm.pickCategoryCallback,
+    );
+  }
+
+  /// 单行输入框
+  Widget _buildInputLayout(
+      BuildContext context,
+      WidgetRef ref,
+      state,
+      String key,
+      {
+        double marginTop = 0,
+        bool? showRightIcon = false, //是否展示右侧的布局
+        Widget? rightWidget, //右侧的布局
+        TextInputType textInputType = TextInputType.text,
+        String? errorText,
+        bool obscureText = false,
+        bool enable = true,
+        TextInputAction textInputAction = TextInputAction.done,
+        Function? onSubmit,
+      }) {
+    // final state = ref.watch(garagesalePostVmProvider);
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintText: state.formData[key]!['hintText'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+}

+ 91 - 0
packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_state.dart

@@ -0,0 +1,91 @@
+import 'package:flutter/cupertino.dart';
+
+class GaragesalePostPageState {
+  //title 字段的错误信息展示
+  String? titleErrorText;
+
+  //title 字段的错误信息展示
+  String? descriptionErrorText;
+
+  //表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  // 标题
+  final String? title;
+  // 描述
+  final String? description;
+
+  //sale 类型选项
+  final List<String> saleOptionsList = ["For Sale", "For Rent",];
+  String? saleSelectedOption;
+
+  //category 类型选项
+  final List<String> categoryOptionsList = ["Kids", "Homeware", "Fashion", "Electronics","Sports","Furniture","Others"];
+  String? categorySelectedOption;
+
+  // 选择的图片
+  final List<String> imgList;
+
+  GaragesalePostPageState({
+    formData,
+    required this.imgList,
+    this.titleErrorText,
+    this.descriptionErrorText,
+    this.title,
+    this.description,
+    this.saleSelectedOption,
+    this.categorySelectedOption,
+  }): formData = formData ?? {
+    'sale': {
+      'value': '',
+      'controller': TextEditingController(),
+      'hintText': '',
+      'focusNode': FocusNode(),
+      'obsecure': false,
+    },
+    'category': {
+      'value': '',
+      'controller': TextEditingController(),
+      'hintText': '',
+      'focusNode': FocusNode(),
+      'obsecure': false,
+    },
+    'title': {
+      'value': '',
+      'controller': TextEditingController(),
+      'hintText': '',
+      'focusNode': FocusNode(),
+      'obsecure': false,
+    },
+    'description': {
+      'value': '',
+      'controller': TextEditingController(),
+      'hintText': '',
+      'focusNode': FocusNode(),
+      'obsecure': false,
+    },
+  };
+
+  GaragesalePostPageState copyWith({
+    Map<String, Map<String, dynamic>>? formData,
+    List<String>? imgList,
+    String? titleErrorText,
+    String? descriptionErrorText,
+    String? saleSelectedOption,
+    String? categorySelectedOption,
+    String? title,
+    String? description,
+  }) {
+    return GaragesalePostPageState(
+      formData: formData ?? this.formData,
+      title: title ?? this.title,
+      description: description ?? this.description,
+      imgList: imgList ?? this.imgList,
+      saleSelectedOption: saleSelectedOption ?? this.saleSelectedOption,
+      categorySelectedOption: categorySelectedOption ?? this.categorySelectedOption,
+      titleErrorText: titleErrorText ,
+      descriptionErrorText: descriptionErrorText,
+    );
+  }
+
+}

+ 219 - 0
packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_vm.dart

@@ -0,0 +1,219 @@
+
+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:router/path/router_path.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+
+
+import 'garagesale_post_page.dart';
+import 'garagesale_post_state.dart';
+
+part 'garagesale_post_vm.g.dart';
+
+
+@riverpod
+class GaragesalePostVm extends _$GaragesalePostVm {
+  GaragesalePostPageState initState() {
+    return GaragesalePostPageState(
+      titleErrorText: null,
+      descriptionErrorText: '',
+      formData: {
+        'sale': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': '',
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
+        'category': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': '',
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
+        'title': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': '',
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
+        'description': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': '',
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
+      },
+      imgList: [],
+    );
+  }
+
+
+  @override
+  GaragesalePostPageState build() {
+    // 初始化状态
+    GaragesalePostPageState state = initState();
+
+    // 当前渲染完成后执行一次
+    WidgetsBinding.instance!.addPostFrameCallback((_) {
+      initListener(state);
+      ref.onDispose(() {
+        onDispose(state);
+      });
+    });
+
+    return state;
+  }
+
+  //catogery 选择选项
+  void pickCategoryCallback() {
+    _dismissKeyboard(keyStr: 'title');
+    _dismissKeyboard(keyStr: 'description');
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.categoryOptionsList,
+      initialSelectIndex: 0,
+      onPickerChanged: (_, index) {
+        state = state.copyWith(categorySelectedOption: state.categoryOptionsList[index]);
+      },
+    );
+  }
+
+  //sale 选择选项
+  void pickSaleCallback() {
+    _dismissKeyboard(keyStr: 'title');
+    _dismissKeyboard(keyStr: 'description');
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.saleOptionsList,
+      initialSelectIndex: 0,
+      onPickerChanged: (_, index) {
+        state = state.copyWith(saleSelectedOption: state.saleOptionsList[index]);
+      },
+    );
+  }
+
+  // 获取聚焦的node
+  FocusNode getFocusNode(Map<String, dynamic> formData, String keyStr) {
+    return formData![keyStr]!['focusNode'];
+  }
+
+  // 取消表单聚焦状态
+  void _dismissKeyboard({String? keyStr}) {
+    if(keyStr!.isNotEmpty){
+      Log.d("FeedbackCreateViewModel 取消单个表单 $keyStr 聚焦状态");
+      final FocusNode sigleItemFocusNode = state.formData[keyStr]!['focusNode'];
+      sigleItemFocusNode!.unfocus();
+    }else {
+      Log.d("FeedbackCreateViewModel 取消所有表单聚焦状态");
+      // 遍历 formData 的所有表单 然后逐一取消聚焦
+      Map<String, dynamic> formData = state.formData;
+      for(String key in formData.keys){
+        final FocusNode sigleItemFocusNode = formData[key]['focusNode'];
+        sigleItemFocusNode!.unfocus();
+      }
+    }
+  }
+
+  // 获取表单的值
+  dynamic _getFormFieldValue({List<String>? keys, String? keyStr}) {
+    if(keyStr!.isEmpty){
+      Log.d("获取指定集合的表单值");
+      if(keys!.isNotEmpty){
+        // 遍历keys获取指定多个 keys 的表单value
+        Map<String, dynamic> resultValueMap = {};
+        for (String itemStr in keys!) {
+          TextEditingController sigleItemController = state.formData[itemStr]!['controller'];
+          resultValueMap[itemStr] = sigleItemController!.text;
+        }
+        return resultValueMap;
+      }
+    }else if(keyStr!.isNotEmpty){
+      Log.d("获取单个表单值  ${keyStr}");
+      // 获取单个表单的value
+      final TextEditingController sigleItemController = state.formData[keyStr]!['controller'];
+      return sigleItemController!.text;
+    }
+  }
+
+  ///提交反馈
+  void submitGaragesalePost() {
+    Log.d("GaragesalePostPageState 提交表单");
+    state = state.copyWith(titleErrorText: null, descriptionErrorText: null);
+    _dismissKeyboard(keyStr: "");
+
+    // 获取表单的值
+    String  saleValue= state.saleSelectedOption ?? "";
+    String  categoryValue= state.categorySelectedOption ?? "";
+
+    String  titleValue= _getFormFieldValue(keyStr: 'title');
+    String  descriptionValue= _getFormFieldValue(keyStr: 'description');
+
+    Log.d('当前待提交的 sale:$saleValue category:$categoryValue title:$titleValue description:$descriptionValue  imgList:${state.imgList}');
+
+
+    if (Utils.isEmpty(saleValue)) {
+      ToastEngine.show('Sale is empty');
+      return;
+    }
+
+    if (Utils.isEmpty(titleValue)) {
+      state = state.copyWith(titleErrorText: 'Title is empty',);
+      return;
+    }else {
+      state.titleErrorText = null;
+      state = state.copyWith(titleErrorText: null);
+    }
+
+    if (Utils.isEmpty(descriptionValue)) {
+      state = state.copyWith(descriptionErrorText: 'Description is empty');
+      return;
+    }else {
+      state = state.copyWith(descriptionErrorText: null);
+    }
+
+
+    //去成功页面
+    // FeedbackCreateSuccessPage.startInstance();
+    // 返回上一页
+  }
+
+  //选中图片
+  void setImgList(List<String> list) {
+    state = state.copyWith(imgList: list);
+  }
+
+  //初始化监听
+  void initListener(GaragesalePostPageState initState) {
+
+    // 获取表单的焦点节点
+    final FocusNode focusNode = getFocusNode(state.formData, 'title');
+
+    focusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (focusNode.hasFocus) {
+        state = state.copyWith(titleErrorText: null, descriptionErrorText: null);
+      }
+    });
+  }
+
+  //销毁资源
+  void onDispose(GaragesalePostPageState initState) {
+    // 获取表单的焦点节点
+    final FocusNode focusNode = getFocusNode(state.formData, 'title');
+    focusNode.dispose();
+
+    Log.d("GaragesalePostPageState 销毁 onDispose");
+  }
+
+
+}

+ 26 - 0
packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_vm.g.dart

@@ -0,0 +1,26 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'garagesale_post_vm.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$garagesalePostVmHash() => r'263c880d5ef88c9a3808b91d6448cbee51b8ff8e';
+
+/// See also [GaragesalePostVm].
+@ProviderFor(GaragesalePostVm)
+final garagesalePostVmProvider = AutoDisposeNotifierProvider<GaragesalePostVm,
+    GaragesalePostPageState>.internal(
+  GaragesalePostVm.new,
+  name: r'garagesalePostVmProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$garagesalePostVmHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$GaragesalePostVm = AutoDisposeNotifier<GaragesalePostPageState>;
+// 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 - 224
packages/cpt_community/lib/modules/garagesale/garagesale_page.dart

@@ -1,224 +0,0 @@
-
-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:flutter/rendering.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 '../community/community_vm.dart';
-import 'garagesale_tabs.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());
-    }
-  }
-
-  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: GaragesaleTabs(
-        tabsList: vm.state.tabsList,
-      ),
-    );
-  }
-
-  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: Row(
-              children: [
-                Expanded(
-                  child: Container(
-                    // height: 65.5,
-                    // color: Colors.blue,
-                    child: MyTextView(
-                      "Sell Item",
-                      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(context);
-            }),
-          ),
-        ],
-      ),
-    );
-  }
-
-  Widget _buildNewsItem(BuildContext context, WidgetRef ref, item, vm){
-    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,
-    // );
-    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(garagesaleVmProvider.notifier);
-
-    return Scaffold(
-      backgroundColor: ColorUtils.string2Color("#F2F3F6"),
-      body: Column(
-        children: [
-          _buildTabsSection(context, ref, vm),
-
-          _buildPostSection(context, ref, vm),
-
-          NotificationListener<ScrollNotification>(
-            onNotification: (ScrollNotification notification) {
-              // 检查当前页面是否是可见的
-              bool isDownOrUp = notification.metrics.axis == Axis.vertical;
-              if (notification is UserScrollNotification) {
-                // 检查滚动方向
-                switch (notification.direction) {
-                  case ScrollDirection.forward:
-                    print('Scrolling down');
-                    break;
-                  case ScrollDirection.reverse:
-                    print('Scrolling up');
-                    break;
-                  case ScrollDirection.idle:
-                    print('Scrolling stopped');
-                    break;
-                }
-              } else if (notification is ScrollUpdateNotification) {
-                // 检查滚动位置变化
-                double currentScrollPosition = notification.metrics.pixels;
-                double maxScrollExtent = notification.metrics.maxScrollExtent;
-
-                // 判断是否满足某个条件
-                if (currentScrollPosition > 0 && currentScrollPosition < maxScrollExtent) {
-                  print('Current scroll position: $currentScrollPosition');
-                  // 在这里添加你的条件判断逻辑
-                }
-
-                // 只有当上下滚动时才拦截通知
-                if (notification.metrics.axis == Axis.vertical) {
-                  final tabsRouter = ref.watch(communityVmProvider).tabsRouter;
-                  final curUseTag = ref.watch(communityVmProvider).useTag;
-
-                  if(curUseTag != 1 ){
-                    // 非当前 页面都阻止滚动
-                    return true; // 返回 true 表示已处理通知
-                  }
-                }
-              }
-              return false; // 返回 false 表示不拦截通知
-            },
-            child: Expanded(
-              child: EasyRefresh(
-                // 上拉加载
-                onLoad: () async{
-                  Log.d("----onLoad");
-                  vm.onLoadData();
-                },
-                // 下拉刷新
-                onRefresh: () async{
-                  Log.d("----onRefresh");
-                  vm.refreshListData();
-                },
-                child: _buildNesFeedList(context, ref, vm),
-              ),
-            ),
-          )
-        ],
-      ),
-    );
-  }
-}

+ 0 - 38
packages/cpt_community/lib/modules/garagesale/garagesale_post/garagesale_post_page.dart

@@ -1,38 +0,0 @@
-import 'package:cpt_community/router/page/community_page_router.dart';
-import 'package:cs_resources/theme/app_colors_theme.dart';
-import 'package:flutter/material.dart';
-import 'package:auto_route/auto_route.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:router/ext/auto_router_extensions.dart';
-import 'package:widgets/my_appbar.dart';
-
-@RoutePage()
-class GaragesalePostPage extends HookConsumerWidget {
-  const GaragesalePostPage({Key? key}) : super(key: key);
-
-  //启动当前页面
-  static void startInstance({BuildContext? context}) {
-    if (context != null) {
-      context.router.push(const GaragesalePostPageRoute());
-    } else {
-      appRouter.push(const GaragesalePostPageRoute());
-    }
-  }
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    // final viewModel = ref.watch(newsfeedPostVmProvider.notifier);
-
-    return Scaffold(
-      appBar: MyAppBar.appBar(
-        context,
-        "Garage Sale Post",
-        backgroundColor: context.appColors.whiteBG,
-      ),
-      backgroundColor: context.appColors.backgroundDefault,
-      body: Center(
-        child: Text("GaragesalePost"),
-      ),
-    );
-  }
-}

+ 0 - 38
packages/cpt_community/lib/modules/newsfeed/newsfeed_detail/newsfeed_detail_page.dart

@@ -1,38 +0,0 @@
-import 'package:cpt_community/router/page/community_page_router.dart';
-import 'package:cs_resources/theme/app_colors_theme.dart';
-import 'package:flutter/material.dart';
-import 'package:auto_route/auto_route.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:router/ext/auto_router_extensions.dart';
-import 'package:widgets/my_appbar.dart';
-
-@RoutePage()
-class NewsfeedDetailPage extends HookConsumerWidget {
-  const NewsfeedDetailPage({Key? key}) : super(key: key);
-
-  //启动当前页面
-  static void startInstance({BuildContext? context}) {
-    if (context != null) {
-      context.router.push(const NewsfeedDetailPageRoute());
-    } else {
-      appRouter.push(const NewsfeedDetailPageRoute());
-    }
-  }
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    // final viewModel = ref.watch(newsfeedPostVmProvider.notifier);
-
-    return Scaffold(
-      appBar: MyAppBar.appBar(
-        context,
-        "News Feed Detail",
-        backgroundColor: context.appColors.whiteBG,
-      ),
-      backgroundColor: context.appColors.backgroundDefault,
-      body: Center(
-        child: Text("NewsfeedDetail"),
-      ),
-    );
-  }
-}

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

@@ -1,226 +0,0 @@
-
-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:flutter/rendering.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 '../community/community_vm.dart';
-import 'newsfeed_tabs.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: NewsfeedTabs(
-        tabsList: vm.state.tabsList,
-      ),
-    );
-  }
-
-  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: Row(
-              children: [
-                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(context);
-            }),
-          ),
-        ],
-      ),
-    );
-  }
-
-  Widget _buildNewsItem(BuildContext context, WidgetRef ref, item, vm){
-    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),
-            //   ),
-            // )
-            NotificationListener <ScrollNotification>(
-              onNotification: (ScrollNotification notification) {
-                // 检查当前页面是否是可见的
-                bool isDownOrUp = notification.metrics.axis == Axis.vertical;
-                if (notification is UserScrollNotification) {
-                  // 检查滚动方向
-                  switch (notification.direction) {
-                    case ScrollDirection.forward:
-                      print('Scrolling down');
-                      break;
-                    case ScrollDirection.reverse:
-                      print('Scrolling up');
-                      break;
-                    case ScrollDirection.idle:
-                      print('Scrolling stopped');
-                      break;
-                  }
-                } else if (notification is ScrollUpdateNotification) {
-                  // 检查滚动位置变化
-                  double currentScrollPosition = notification.metrics.pixels;
-                  double maxScrollExtent = notification.metrics.maxScrollExtent;
-
-                  // 判断是否满足某个条件
-                  if (currentScrollPosition > 0 && currentScrollPosition < maxScrollExtent) {
-                    print('Current scroll position: $currentScrollPosition');
-                    // 在这里添加你的条件判断逻辑
-                  }
-
-                  // 只有当上下滚动时才拦截通知
-                  if (notification.metrics.axis == Axis.vertical) {
-                    final tabsRouter = ref.watch(communityVmProvider).tabsRouter;
-                    final curUseTag = ref.watch(communityVmProvider).useTag;
-                    if(curUseTag != 0 ){
-                      // 非当前 页面都阻止滚动
-                      return true; // 返回 true 表示已处理通知
-                    }
-                  }
-                }
-                return false; // 返回 false 表示不拦截通知
-              },
-              child: Expanded(
-                child: _buildNesFeedList(context, ref, vm),
-              ),
-            )
-          ],
-      ),
-    );
-  }
-}

+ 0 - 155
packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_page.dart

@@ -1,155 +0,0 @@
-import 'package:cpt_community/router/page/community_page_router.dart';
-import 'package:cs_resources/theme/app_colors_theme.dart';
-import 'package:flutter/material.dart';
-import 'package:auto_route/auto_route.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:router/ext/auto_router_extensions.dart';
-import 'package:widgets/ext/ex_widget.dart';
-import 'package:widgets/my_appbar.dart';
-import 'package:widgets/my_text_field.dart';
-import 'package:widgets/widget_export.dart';
-import 'package:widgets/my_button.dart';
-
-import 'newsfeed_post_vm.dart';
-
-@RoutePage()
-class NewsfeedPostPage extends HookConsumerWidget {
-  const NewsfeedPostPage({Key? key}) : super(key: key);
-
-  //启动当前页面
-  static void startInstance({BuildContext? context}) {
-    if (context != null) {
-      context.router.push(const NewsfeedPostPageRoute());
-    } else {
-      appRouter.push(const NewsfeedPostPageRoute());
-    }
-  }
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    // final viewModel = ref.watch(newsfeedPostVmProvider.notifier);
-    final state = ref.watch(newsfeedPostVmProvider);
-
-    return Scaffold(
-      appBar: MyAppBar.appBar(
-        context,
-        "Create Post",
-        backgroundColor: context.appColors.whiteBG,
-      ),
-      backgroundColor: context.appColors.backgroundDefault,
-      body: Column(
-        children: [
-          Expanded(
-            child: SingleChildScrollView(
-              scrollDirection: Axis.vertical,
-              physics: const BouncingScrollPhysics(),
-              clipBehavior: Clip.none,
-              child: Column(
-                children: [
-                  Container(
-                    width: double.infinity,
-                    height: 200,
-                    decoration: BoxDecoration(
-                      border: Border.all(
-                        color: Colors.grey,
-                        width: 1
-                      ),
-                      borderRadius: BorderRadius.circular(10),
-                      boxShadow: [
-                        BoxShadow(
-                          color: Colors.grey.withOpacity(0.5),
-                          spreadRadius: 1,
-                          blurRadius: 1,
-                          offset: const Offset(0, 3), // changes position of shadow
-                        ),
-                      ]
-                    ),
-                    child: _buildInputLayout(
-                      context,
-                      state,
-                      'mind'
-                    ),
-                  ).marginOnly(left:15, right:15, top: 20, bottom: 20),
-                  Container(
-                    width: double.infinity,
-                    height: 200,
-                    color: Colors.grey,
-                  ),
-                ]
-              )
-            )
-          ),
-          Container(
-            child: Row(
-                children: [
-                  Expanded(
-                    child: MyButton(
-                      text: "Add Card",
-                      backgroundColor: context.appColors.textPrimary,
-                      textColor: Colors.white,
-                      fontWeight: FontWeight.w500,
-                      fontSize: 16,
-                      onPressed: (){
-                        // Navigator.pop(context);
-                      },
-                    ),
-                  ),
-                ]
-            ),
-          )
-        ]
-      ),
-    );
-  }
-
-
-  /// 输入框
-  Widget _buildInputLayout(
-      BuildContext context,
-      state,
-      String key,
-      {
-        double marginTop = 0,
-        bool? showRightIcon = false, //是否展示右侧的布局
-        Widget? rightWidget, //右侧的布局
-        TextInputType textInputType = TextInputType.text,
-        String? errorText,
-        bool obscureText = false,
-        TextInputAction textInputAction = TextInputAction.done,
-        Function? onSubmit,
-      }) {
-    return IgnoreKeyboardDismiss(
-      child: MyTextField(
-        key,
-        fillBackgroundColor: context.appColors.authFiledBG,
-        state.formData[key]!['value'],
-        hintText: state.formData[key]!['hintText'],
-        hintStyle: TextStyle(
-          color: context.appColors.authFiledHint,
-          fontSize: 16.0,
-          fontWeight: FontWeight.w500,
-        ),
-        controller: state.formData[key]!['controller'],
-        focusNode: state.formData[key]!['focusNode'],
-        margin: EdgeInsets.only(top: marginTop),
-        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
-        showDivider: false,
-        height: 44,
-        style: TextStyle(
-          color: context.appColors.authFiledText,
-          fontSize: 16.0,
-          fontWeight: FontWeight.w500,
-        ),
-        inputType: textInputType,
-        textInputAction: textInputAction,
-        onSubmit: onSubmit,
-        cursorColor: context.appColors.authFiledText,
-        obscureText: obscureText,
-        errorText: errorText,
-        showLeftIcon: true,
-        showRightIcon: showRightIcon,
-        rightWidget: rightWidget,
-      ),
-    );
-  }
-}

+ 0 - 8
packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_page_state.dart

@@ -1,8 +0,0 @@
-class NewsfeedPostPageState {
-  //表单的校验与数据
-  final Map<String, Map<String, dynamic>> formData;
-
-  const NewsfeedPostPageState({
-    required this.formData,
-  });
-}

+ 0 - 47
packages/cpt_community/lib/modules/newsfeed/newsfeed_post/newsfeed_post_vm.dart

@@ -1,47 +0,0 @@
-
-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:router/path/router_path.dart';
-import 'package:shared/utils/color_utils.dart';
-import 'package:shared/utils/log_utils.dart';
-import 'package:auto_route/auto_route.dart';
-
-
-import 'newsfeed_post_page_state.dart';
-
-part 'newsfeed_post_vm.g.dart';
-
-@riverpod
-class NewsfeedPostVm extends _$NewsfeedPostVm {
-
-  NewsfeedPostPageState initState() {
-    return NewsfeedPostPageState(
-      formData: {
-        'mind': {
-          'value': '',
-          'controller': TextEditingController(),
-          'hintText': 'What\'s on your mind?',
-          'focusNode': FocusNode(),
-          'obsecure': false,
-        },
-        'images': {
-          'value': '',
-          'controller': TextEditingController(),
-          'hintText': '',
-          'focusNode': FocusNode(),
-          'obsecure': false,
-        },
-      },
-    );
-  }
-  @override
-  NewsfeedPostPageState build(){
-    // 初始化状态
-    NewsfeedPostPageState state = initState();
-    return state;
-  }
-
-
-}

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

@@ -1,69 +0,0 @@
-import 'package:cs_resources/generated/assets.dart';
-import 'package:flutter/material.dart';
-import 'package:shared/utils/color_utils.dart';
-
-class NewsfeedState {
-  int? useTag = 0;
-  int? curPage;
-  int? pageSize;
-  int? filterCount;
-  int? activeIndex = 0;
-  List tabsList = [];
-  List? list = [];
-
-
-
-  NewsfeedState copyWith({
-    int? useTag,
-    int? curPage,
-    int? pageSize,
-    int? filterCount,
-    int? activeIndex,
-    List? tabsList,
-    List? list,
-  }) {
-    return NewsfeedState(
-      useTag: useTag ?? this.useTag,
-      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 {
-      'useTag': this.useTag,
-      '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(
-      useTag: map['useTag'] as int,
-      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.useTag,
-    this.curPage,
-    this.pageSize,
-    this.filterCount,
-    this.activeIndex,
-    required this.tabsList,
-    this.list,
-  });
-}

+ 54 - 18
packages/cpt_community/lib/router/page/community_page_router.dart

@@ -4,14 +4,22 @@ import 'package:router/ext/auto_router_extensions.dart';
 import 'package:router/path/router_path.dart';
 
 import '../../modules/community/community_page.dart';
-import '../../modules/garagesale/garagesale_detail/garagesale_detail_page.dart';
-import '../../modules/newsfeed/newsfeed_page.dart';
-import '../../modules/garagesale/garagesale_page.dart';
-import '../../modules/newsfeed/newsfeed_post/newsfeed_post_page.dart';
-import '../../modules/newsfeed/newsfeed_detail/newsfeed_detail_page.dart';
-import '../../modules/newsfeed/newsfeed_myposts/newsfeed_myposts_page.dart';
-import '../../modules/garagesale/garagesale_myposts/garagesale_myposts_page.dart';
-import '../../modules/garagesale/garagesale_post/garagesale_post_page.dart';
+import '../../modules/community/news/news_page.dart';
+import '../../modules/community/following/following_page.dart';
+import '../../modules/community/foryou/foryou_page.dart';
+import '../../modules/community/newsfeed_detail/newsfeed_detail_page.dart';
+import '../../modules/community/newsfeed_post/newsfeed_post_page.dart';
+import '../../modules/community/newsfeed_myposts/newsfeed_myposts_page.dart';
+
+import '../../modules/garage/garage_page.dart';
+import '../../modules/garage/for_sale/for_sale_page.dart';
+import '../../modules/garage/for_rent/for_rent_page.dart';
+import '../../modules/garage/garagesale_detail/garagesale_detail_page.dart';
+import '../../modules/garage/garagesale_post/garagesale_post_page.dart';
+import '../../modules/garage/garagesale_myposts/garagesale_myposts_page.dart';
+
+
+
 
 part 'community_page_router.gr.dart';
 
@@ -28,16 +36,24 @@ class CommunityPageRouter extends _$CommunityPageRouter {
         path: RouterPath.community,
         transitionsBuilder: applySlideTransition,
         children: [
-          CustomRoute(
-              page: NewsfeedPageRoute.page,
-              path: RouterPath.newsFeed,
-              transitionsBuilder: applySlideTransition,
-          ),
-          CustomRoute(
-            page: GaragesalePageRoute.page,
-            path: RouterPath.garageSale,
-            transitionsBuilder: applySlideTransition,
-          ),
+           // newsfeed-news page
+            CustomRoute(
+                page: NewsPageRoute.page,
+                path: RouterPath.newsfeedNews,
+                transitionsBuilder: applySlideTransition,
+            ),
+            // newsfeed-following page
+            CustomRoute(
+                page: FollowingPageRoute.page,
+                path: RouterPath.newsfeedFollowing,
+                transitionsBuilder: applySlideTransition,
+            ),
+            // newsfeed-foryou page
+            CustomRoute(
+                page: ForyouPageRoute.page,
+                path: RouterPath.newsfeedForyou,
+                transitionsBuilder: applySlideTransition,
+            ),
         ],
     ),
     CustomRoute(
@@ -55,6 +71,26 @@ class CommunityPageRouter extends _$CommunityPageRouter {
       path: RouterPath.newsFeedMyPosts,
       transitionsBuilder: applySlideTransition,
     ),
+    // Garage
+    CustomRoute(
+      page: GaragePageRoute.page,
+      path: RouterPath.garage,
+      transitionsBuilder: applySlideTransition,
+      children: [
+        // garageSale-forSale page
+        CustomRoute(
+          page: ForsalePageRoute.page,
+          path: RouterPath.garageForSale,
+          transitionsBuilder: applySlideTransition,
+        ),
+        // garageSale-forRent page
+        CustomRoute(
+          page: ForrentPageRoute.page,
+          path: RouterPath.garageForRent,
+          transitionsBuilder: applySlideTransition,
+        )
+      ]
+    ),
     CustomRoute(
       page: GaragesalePostPageRoute.page,
       path: RouterPath.garageSalePost,

+ 194 - 44
packages/cpt_community/lib/router/page/community_page_router.gr.dart

@@ -21,22 +21,51 @@ abstract class _$CommunityPageRouter extends RootStackRouter {
         child: const CommunityPage(),
       );
     },
-    GaragesaleDetailPageRoute.name: (routeData) {
+    FollowingPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: const GaragesaleDetailPage(),
+        child: const FollowingPage(),
       );
     },
-    GaragesaleMypostsPageRoute.name: (routeData) {
+    ForrentPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: const GaragesaleMypostsPage(),
+        child: const ForrentPage(),
+      );
+    },
+    ForsalePageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const ForsalePage(),
+      );
+    },
+    ForyouPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const ForyouPage(),
+      );
+    },
+    GaragePageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const GaragePage(),
       );
     },
-    GaragesalePageRoute.name: (routeData) {
+    GaragesaleDetailPageRoute.name: (routeData) {
+      final args = routeData.argsAs<GaragesaleDetailPageRouteArgs>();
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: GaragesaleDetailPage(
+          key: args.key,
+          id: args.id,
+          type: args.type,
+        ),
+      );
+    },
+    GaragesaleMypostsPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: const GaragesalePage(),
+        child: const GaragesaleMypostsPage(),
       );
     },
     GaragesalePostPageRoute.name: (routeData) {
@@ -45,22 +74,27 @@ abstract class _$CommunityPageRouter extends RootStackRouter {
         child: const GaragesalePostPage(),
       );
     },
-    NewsfeedDetailPageRoute.name: (routeData) {
+    NewsPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: const NewsfeedDetailPage(),
+        child: const NewsPage(),
       );
     },
-    NewsfeedMypostsPageRoute.name: (routeData) {
+    NewsfeedDetailPageRoute.name: (routeData) {
+      final args = routeData.argsAs<NewsfeedDetailPageRouteArgs>();
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: const NewsfeedMypostsPage(),
+        child: NewsfeedDetailPage(
+          key: args.key,
+          id: args.id,
+          type: args.type,
+        ),
       );
     },
-    NewsfeedPageRoute.name: (routeData) {
+    NewsfeedMypostsPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: const NewsfeedPage(),
+        child: const NewsfeedMypostsPage(),
       );
     },
     NewsfeedPostPageRoute.name: (routeData) {
@@ -87,43 +121,129 @@ class CommunityPageRoute extends PageRouteInfo<void> {
 }
 
 /// generated route for
-/// [GaragesaleDetailPage]
-class GaragesaleDetailPageRoute extends PageRouteInfo<void> {
-  const GaragesaleDetailPageRoute({List<PageRouteInfo>? children})
+/// [FollowingPage]
+class FollowingPageRoute extends PageRouteInfo<void> {
+  const FollowingPageRoute({List<PageRouteInfo>? children})
       : super(
-          GaragesaleDetailPageRoute.name,
+          FollowingPageRoute.name,
           initialChildren: children,
         );
 
-  static const String name = 'GaragesaleDetailPageRoute';
+  static const String name = 'FollowingPageRoute';
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }
 
 /// generated route for
-/// [GaragesaleMypostsPage]
-class GaragesaleMypostsPageRoute extends PageRouteInfo<void> {
-  const GaragesaleMypostsPageRoute({List<PageRouteInfo>? children})
+/// [ForrentPage]
+class ForrentPageRoute extends PageRouteInfo<void> {
+  const ForrentPageRoute({List<PageRouteInfo>? children})
       : super(
-          GaragesaleMypostsPageRoute.name,
+          ForrentPageRoute.name,
           initialChildren: children,
         );
 
-  static const String name = 'GaragesaleMypostsPageRoute';
+  static const String name = 'ForrentPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [ForsalePage]
+class ForsalePageRoute extends PageRouteInfo<void> {
+  const ForsalePageRoute({List<PageRouteInfo>? children})
+      : super(
+          ForsalePageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'ForsalePageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [ForyouPage]
+class ForyouPageRoute extends PageRouteInfo<void> {
+  const ForyouPageRoute({List<PageRouteInfo>? children})
+      : super(
+          ForyouPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'ForyouPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [GaragePage]
+class GaragePageRoute extends PageRouteInfo<void> {
+  const GaragePageRoute({List<PageRouteInfo>? children})
+      : super(
+          GaragePageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'GaragePageRoute';
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }
 
 /// generated route for
-/// [GaragesalePage]
-class GaragesalePageRoute extends PageRouteInfo<void> {
-  const GaragesalePageRoute({List<PageRouteInfo>? children})
+/// [GaragesaleDetailPage]
+class GaragesaleDetailPageRoute
+    extends PageRouteInfo<GaragesaleDetailPageRouteArgs> {
+  GaragesaleDetailPageRoute({
+    Key? key,
+    required int? id,
+    required String? type,
+    List<PageRouteInfo>? children,
+  }) : super(
+          GaragesaleDetailPageRoute.name,
+          args: GaragesaleDetailPageRouteArgs(
+            key: key,
+            id: id,
+            type: type,
+          ),
+          initialChildren: children,
+        );
+
+  static const String name = 'GaragesaleDetailPageRoute';
+
+  static const PageInfo<GaragesaleDetailPageRouteArgs> page =
+      PageInfo<GaragesaleDetailPageRouteArgs>(name);
+}
+
+class GaragesaleDetailPageRouteArgs {
+  const GaragesaleDetailPageRouteArgs({
+    this.key,
+    required this.id,
+    required this.type,
+  });
+
+  final Key? key;
+
+  final int? id;
+
+  final String? type;
+
+  @override
+  String toString() {
+    return 'GaragesaleDetailPageRouteArgs{key: $key, id: $id, type: $type}';
+  }
+}
+
+/// generated route for
+/// [GaragesaleMypostsPage]
+class GaragesaleMypostsPageRoute extends PageRouteInfo<void> {
+  const GaragesaleMypostsPageRoute({List<PageRouteInfo>? children})
       : super(
-          GaragesalePageRoute.name,
+          GaragesaleMypostsPageRoute.name,
           initialChildren: children,
         );
 
-  static const String name = 'GaragesalePageRoute';
+  static const String name = 'GaragesaleMypostsPageRoute';
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }
@@ -143,43 +263,73 @@ class GaragesalePostPageRoute extends PageRouteInfo<void> {
 }
 
 /// generated route for
-/// [NewsfeedDetailPage]
-class NewsfeedDetailPageRoute extends PageRouteInfo<void> {
-  const NewsfeedDetailPageRoute({List<PageRouteInfo>? children})
+/// [NewsPage]
+class NewsPageRoute extends PageRouteInfo<void> {
+  const NewsPageRoute({List<PageRouteInfo>? children})
       : super(
-          NewsfeedDetailPageRoute.name,
+          NewsPageRoute.name,
           initialChildren: children,
         );
 
-  static const String name = 'NewsfeedDetailPageRoute';
+  static const String name = 'NewsPageRoute';
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }
 
 /// generated route for
-/// [NewsfeedMypostsPage]
-class NewsfeedMypostsPageRoute extends PageRouteInfo<void> {
-  const NewsfeedMypostsPageRoute({List<PageRouteInfo>? children})
-      : super(
-          NewsfeedMypostsPageRoute.name,
+/// [NewsfeedDetailPage]
+class NewsfeedDetailPageRoute
+    extends PageRouteInfo<NewsfeedDetailPageRouteArgs> {
+  NewsfeedDetailPageRoute({
+    Key? key,
+    required int? id,
+    required String? type,
+    List<PageRouteInfo>? children,
+  }) : super(
+          NewsfeedDetailPageRoute.name,
+          args: NewsfeedDetailPageRouteArgs(
+            key: key,
+            id: id,
+            type: type,
+          ),
           initialChildren: children,
         );
 
-  static const String name = 'NewsfeedMypostsPageRoute';
+  static const String name = 'NewsfeedDetailPageRoute';
 
-  static const PageInfo<void> page = PageInfo<void>(name);
+  static const PageInfo<NewsfeedDetailPageRouteArgs> page =
+      PageInfo<NewsfeedDetailPageRouteArgs>(name);
+}
+
+class NewsfeedDetailPageRouteArgs {
+  const NewsfeedDetailPageRouteArgs({
+    this.key,
+    required this.id,
+    required this.type,
+  });
+
+  final Key? key;
+
+  final int? id;
+
+  final String? type;
+
+  @override
+  String toString() {
+    return 'NewsfeedDetailPageRouteArgs{key: $key, id: $id, type: $type}';
+  }
 }
 
 /// generated route for
-/// [NewsfeedPage]
-class NewsfeedPageRoute extends PageRouteInfo<void> {
-  const NewsfeedPageRoute({List<PageRouteInfo>? children})
+/// [NewsfeedMypostsPage]
+class NewsfeedMypostsPageRoute extends PageRouteInfo<void> {
+  const NewsfeedMypostsPageRoute({List<PageRouteInfo>? children})
       : super(
-          NewsfeedPageRoute.name,
+          NewsfeedMypostsPageRoute.name,
           initialChildren: children,
         );
 
-  static const String name = 'NewsfeedPageRoute';
+  static const String name = 'NewsfeedMypostsPageRoute';
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }

+ 66 - 0
packages/cpt_facility/lib/modules/booking/facility_booking_page.dart

@@ -0,0 +1,66 @@
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../router/page/facility_page_router.dart';
+import 'facility_booking_view_model.dart';
+
+@RoutePage()
+class FacilityBookingPage extends HookConsumerWidget {
+  const FacilityBookingPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const FacilityBookingPageRoute());
+    } else {
+      appRouter.push(const FacilityBookingPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(facilityBookingViewModelProvider.notifier);
+    final state = ref.watch(facilityBookingViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, "Kids party room", backgroundColor: context.appColors.whiteBG),
+      backgroundColor: context.appColors.backgroundDark,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            MyTextView(
+              "Friday,11 October 2024",
+              textColor: context.appColors.textBlack,
+              fontSize: 17,
+              marginTop: 18,
+              marginBottom: 16,
+              marginLeft: 15,
+              isFontMedium: true,
+            ),
+            WeeklyCalendar(
+              isAutoSelect: false,
+              selectedDate: DateTime.now().add(Duration(days: 1)),
+              onChangedSelectedDate: (dateTime) {
+                Log.d("onChangedSelectedDate选中 - ${dateTime}}");
+              },
+              onChangedPage: (dateTime, state) {
+                Log.d("onChangedPage - ${dateTime} state:${state}");
+              },
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 3 - 0
packages/cpt_facility/lib/modules/booking/facility_booking_state.dart

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

+ 13 - 0
packages/cpt_facility/lib/modules/booking/facility_booking_view_model.dart

@@ -0,0 +1,13 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+import 'facility_booking_state.dart';
+
+part 'facility_booking_view_model.g.dart';
+
+@riverpod
+class FacilityBookingViewModel extends _$FacilityBookingViewModel{
+  @override
+  FacilityBookingState build() {
+    return FacilityBookingState();
+  }
+}

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

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

+ 308 - 0
packages/cpt_facility/lib/modules/detail/facility_detail_page.dart

@@ -0,0 +1,308 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+import '../../router/page/facility_page_router.dart';
+import 'facility_detail_view_model.dart';
+
+@RoutePage()
+class FacilityDetailPage extends HookConsumerWidget {
+  const FacilityDetailPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const FacilityDetailPageRoute());
+    } else {
+      appRouter.push(const FacilityDetailPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(facilityDetailViewModelProvider.notifier);
+    final state = ref.watch(facilityDetailViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, "Kids party room", backgroundColor: context.appColors.whiteBG),
+      backgroundColor: context.appColors.backgroundDark,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Column(
+          mainAxisSize: MainAxisSize.max,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            //顶部的信息展示
+            _buildHeaderWidget(context, ref),
+
+            //预定
+            _buildDetailItem(
+              context,
+              ref,
+              S.current.book,
+              Assets.facilityConfirmDateIcon,
+              28.5,
+              29,
+              "Tue,24 Oct 2023",
+              null,
+              "05:00 PM-10:00 PM",
+              null,
+            ),
+
+            //设施
+            _buildDetailItem(
+              context,
+              ref,
+              S.current.facility,
+              Assets.facilityConfirmFacilityIcon,
+              25.0,
+              30.5,
+              "Kids party room",
+              null,
+              "Blue room",
+              null,
+            ),
+
+            //付款
+            _buildDetailItem(
+              context,
+              ref,
+              S.current.payment,
+              Assets.facilityConfirmPaymentIcon,
+              27.0,
+              22.0,
+              "Booking Fee",
+              "10.80",
+              S.current.total,
+              "\$10.80",
+            ),
+
+            // 押金
+            _buildDetailItem(
+              context,
+              ref,
+              S.current.deposit,
+              Assets.facilityConfirmDepositIcon,
+              28.0,
+              26.5,
+              "On Hold",
+              "\$100.00",
+              null,
+              null,
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _buildHeaderWidget(BuildContext context, WidgetRef ref) {
+    return Container(
+      width: double.infinity,
+      color: context.appColors.whiteBG,
+      margin: const EdgeInsets.only(bottom: 7.5),
+      child: Column(
+        children: [
+          //成功图片
+          const MyAssetImage(
+            Assets.facilityPaymentSuccessIcon,
+            width: 54,
+            height: 54,
+          ).marginOnly(top: 11, bottom: 13),
+
+          //支付成功
+          MyTextView(
+            S.current.booking_successful,
+            fontSize: 18,
+            marginBottom: 3,
+            isFontMedium: true,
+            textColor: context.appColors.textPrimary,
+          ),
+          MyTextView(
+            S.current.have_fun,
+            fontSize: 18,
+            marginBottom: 19,
+            isFontMedium: true,
+            textColor: context.appColors.textPrimary,
+          ),
+
+          //支付金额
+          MyTextView(
+            S.current.fee_paid,
+            fontSize: 15,
+            isFontRegular: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            "\$10.80",
+            fontSize: 15,
+            isFontRegular: true,
+            textColor: context.appColors.textPrimary,
+          ),
+
+          //付款类型与时间
+          Row(
+            mainAxisSize: MainAxisSize.min,
+            children: [
+              MyTextView(
+                "Master card ending",
+                fontSize: 15,
+                isFontRegular: true,
+                textColor: context.appColors.textBlack,
+              ),
+              MyTextView(
+                "9423",
+                fontSize: 15,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+            ],
+          ).marginOnly(top: 12),
+
+          Row(
+            mainAxisSize: MainAxisSize.min,
+            children: [
+              MyTextView(
+                S.current.paid_on,
+                fontSize: 15,
+                isFontRegular: true,
+                textColor: context.appColors.textBlack,
+              ),
+              MyTextView(
+                "24 Oct 2023 at 02:19 PM",
+                fontSize: 15,
+                isFontMedium: true,
+                textColor: context.appColors.textBlack,
+              ),
+            ],
+          ).marginOnly(top: 5),
+
+          Divider(height: 0.5, color: context.appColors.dividerDefault).marginOnly(top: 14, bottom: 14),
+
+          //押金
+          MyTextView(
+            S.current.deposit_released_caps,
+            fontSize: 15,
+            isFontRegular: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            "\$100.00",
+            fontSize: 15,
+            marginTop: 5,
+            isFontRegular: true,
+            textColor: context.appColors.textPrimary,
+          ),
+
+          const SizedBox(height: 23),
+        ],
+      ),
+    );
+  }
+
+  //Item的列表
+  Widget _buildDetailItem(
+    BuildContext context,
+    WidgetRef ref,
+    String title,
+    String iconPath,
+    double iconWidth,
+    double iconHeight,
+    String line1Txt,
+    String? line1Content,
+    String? line2Txt,
+    String? line2Content,
+  ) {
+    return Container(
+      width: double.infinity,
+      height: 92.5,
+      padding: const EdgeInsets.only(left: 20, right: 20),
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 7.5, bottom: 7.5),
+      decoration: BoxDecoration(
+        color: context.appColors.whiteBG,
+        borderRadius: BorderRadius.circular(6.0), // 圆角
+        boxShadow: [
+          BoxShadow(
+            color: const Color(0xFFB8BFD9).withOpacity(0.3), // 阴影颜色
+            offset: const Offset(0, 3), // 阴影的偏移量
+            blurRadius: 8.0, // 模糊半径
+            spreadRadius: 3.0, // 扩散半径
+          ),
+        ],
+      ),
+      child: Center(
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            MyTextView(
+              title,
+              textColor: context.appColors.textBlack,
+              fontSize: 16,
+              marginBottom: 7,
+              isFontMedium: true,
+            ),
+            Row(
+              mainAxisSize: MainAxisSize.max,
+              children: [
+                MyAssetImage(
+                  iconPath,
+                  width: iconWidth,
+                  height: iconHeight,
+                ).marginOnly(right: 15),
+                Column(
+                  mainAxisSize: MainAxisSize.min,
+                  children: [
+                    Row(
+                      children: [
+                        MyTextView(
+                          line1Txt,
+                          textColor: context.appColors.textBlack,
+                          fontSize: 14,
+                          isFontRegular: true,
+                        ).expanded(),
+                        MyTextView(
+                          line1Content ?? "",
+                          textColor: context.appColors.textBlack,
+                          fontSize: 14,
+                          isFontRegular: true,
+                        ),
+                      ],
+                    ),
+                    Visibility(
+                      visible: line2Txt != null,
+                      child: Row(
+                        children: [
+                          MyTextView(
+                            line2Txt ?? "",
+                            textColor: context.appColors.textBlack,
+                            fontSize: 14,
+                            isFontRegular: true,
+                          ).expanded(),
+                          MyTextView(
+                            line2Content ?? "",
+                            textColor: context.appColors.textBlack,
+                            fontSize: 14,
+                            isFontRegular: true,
+                          ),
+                        ],
+                      ).marginOnly(top: 6),
+                    ),
+                  ],
+                ).expanded(),
+              ],
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 3 - 0
packages/cpt_facility/lib/modules/detail/facility_detail_state.dart

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

+ 13 - 0
packages/cpt_facility/lib/modules/detail/facility_detail_view_model.dart

@@ -0,0 +1,13 @@
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+import 'facility_detail_state.dart';
+
+part 'facility_detail_view_model.g.dart';
+
+@riverpod
+class FacilityDetailViewModel extends _$FacilityDetailViewModel{
+  @override
+  FacilityDetailState build() {
+    return FacilityDetailState();
+  }
+}

+ 27 - 0
packages/cpt_facility/lib/modules/detail/facility_detail_view_model.g.dart

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

+ 57 - 0
packages/cpt_facility/lib/modules/facility/active/facility_active_screen.dart

@@ -0,0 +1,57 @@
+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:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../detail/facility_detail_page.dart';
+import 'facility_active_view_model.dart';
+import 'item_facility_active.dart';
+
+
+@RoutePage()
+class FacilityActiveScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(facilityActiveViewModelProvider.notifier);
+    final state = ref.watch(facilityActiveViewModelProvider);
+
+    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 FacilityActiveItem(index: index, item: state.datas[index]).onTap((){
+                      FacilityDetailPage.startInstance(context: context);
+                    });
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_facility/lib/modules/facility/active/facility_active_state.dart

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

+ 130 - 0
packages/cpt_facility/lib/modules/facility/active/facility_active_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 'facility_active_state.dart';
+
+part 'facility_active_view_model.g.dart';
+
+@riverpod
+class FacilityActiveViewModel extends _$FacilityActiveViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  FacilityActiveState build() {
+    return FacilityActiveState(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_facility/lib/modules/facility/active/facility_active_view_model.g.dart

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

+ 136 - 0
packages/cpt_facility/lib/modules/facility/active/item_facility_active.dart

@@ -0,0 +1,136 @@
+import 'package:cpt_facility/modules/facility/active/facility_active_screen.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_text_view.dart';
+
+///  设施的Active的Item
+class FacilityActiveItem extends StatelessWidget {
+  final int index;
+  final String item;
+
+  const FacilityActiveItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
+      padding: const EdgeInsets.only(left: 20, right: 15, top: 18, bottom: 25),
+      decoration: BoxDecoration(
+        color: context.appColors.whiteBG,
+        borderRadius: BorderRadius.circular(6.0), // 圆角
+      ),
+      child: Row(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              //设施
+              MyTextView(
+                "Kids party room",
+                fontSize: 16,
+                maxLines: 3,
+                textColor: context.appColors.textBlack,
+                isFontMedium: true,
+              ),
+
+              //分类
+              MyTextView(
+                "Blue room",
+                fontSize: 14,
+                marginTop: 3,
+                textColor: context.appColors.textBlack,
+                isFontRegular: true,
+              ),
+
+              //预订人
+              MyTextView(
+                S.current.booked_by_someone("Wu Bing Bing"),
+                fontSize: 14,
+                marginTop: 3,
+                textColor: context.appColors.textBlack,
+                isFontRegular: true,
+              ),
+
+              //日期
+              MyTextView(
+                "Tue,24 Oct 2023",
+                fontSize: 14,
+                marginTop: 16,
+                textColor: context.appColors.textBlack,
+                isFontRegular: true,
+              ),
+
+              //时间
+              MyTextView(
+                "05:00 PM-10:00 PM",
+                fontSize: 14,
+                marginBottom: 7,
+                marginTop: 3,
+                textColor: context.appColors.textBlack,
+                isFontRegular: true,
+              ),
+
+              //标签
+              Row(
+                children: [
+                  MyTextView(
+                    "Fee Paid",
+                    textColor: context.appColors.textPrimary,
+                    fontSize: 13,
+                    isFontRegular: true,
+                    backgroundColor: context.appColors.lightPurpleBg,
+                    cornerRadius: 3,
+                    paddingLeft: 7,
+                    marginRight: 6,
+                    paddingRight: 7,
+                    paddingTop: 3,
+                    paddingBottom: 3,
+                  ),
+                  MyTextView(
+                    "Deposit",
+                    textColor: context.appColors.textPrimary,
+                    fontSize: 13,
+                    isFontRegular: true,
+                    backgroundColor: context.appColors.lightPurpleBg,
+                    cornerRadius: 3,
+                    paddingLeft: 7,
+                    marginRight: 6,
+                    paddingRight: 7,
+                    paddingTop: 3,
+                    paddingBottom: 3,
+                  )
+                ],
+              )
+            ],
+          ).expanded(),
+          Column(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment:MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              //查看按钮
+              MyTextView(
+                S.current.view,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                cornerRadius: 7,
+                paddingTop: 9,
+                paddingBottom: 9,
+                textAlign: TextAlign.center,
+                boxWidth: 60,
+              )
+            ],
+          )
+        ],
+      ),
+    );
+  }
+}

+ 56 - 0
packages/cpt_facility/lib/modules/facility/book/facility_book_screen.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 '../../booking/facility_booking_page.dart';
+import 'facility_book_view_model.dart';
+import 'item_facility_book.dart';
+
+@RoutePage()
+class FacilityBookScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(facilityBookViewModelProvider.notifier);
+    final state = ref.watch(facilityBookViewModelProvider);
+
+    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 FacilityBookItem(index: index, item: state.datas[index]).onTap(() {
+                  FacilityBookingPage.startInstance(context: context);
+                });
+              },
+              childCount: state.datas.length,
+            ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 31 - 0
packages/cpt_facility/lib/modules/facility/book/facility_book_state.dart

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

+ 130 - 0
packages/cpt_facility/lib/modules/facility/book/facility_book_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 'facility_book_state.dart';
+
+part 'facility_book_view_model.g.dart';
+
+@riverpod
+class FacilityBookViewModel extends _$FacilityBookViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: true,   //允许加载
+  );
+
+  @override
+  FacilityBookState build() {
+    return FacilityBookState(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_facility/lib/modules/facility/book/facility_book_view_model.g.dart

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

+ 48 - 0
packages/cpt_facility/lib/modules/facility/book/item_facility_book.dart

@@ -0,0 +1,48 @@
+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';
+
+///  设施的Book的Item
+class FacilityBookItem extends StatelessWidget {
+  final int index;
+  final String item;
+
+  const FacilityBookItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      height: 80,
+      margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
+      padding: const EdgeInsets.symmetric(horizontal: 20),
+      decoration: BoxDecoration(
+        color: context.appColors.whiteBG,
+        borderRadius: BorderRadius.circular(6.0), // 圆角
+      ),
+      child: Row(
+        mainAxisSize: MainAxisSize.max,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        children: [
+          MyLoadImage(
+            "https://img0.baidu.com/it/u=2679587808,2501833998&fm=253&fmt=auto&app=120&f=JPEG?w=372&h=400",
+            width: 38.5,
+          ),
+
+          MyTextView(
+            "Function Room",
+            marginLeft: 17,
+            fontSize: 16,
+            textColor: context.appColors.textBlack,
+            isFontMedium: true,
+          ).expanded(),
+        ],
+      ),
+    );
+  }
+}

+ 147 - 0
packages/cpt_facility/lib/modules/facility/deposit/facility_deposit_screen.dart

@@ -0,0 +1,147 @@
+import 'package:auto_route/auto_route.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:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/widget_export.dart';
+
+import '../../detail/facility_detail_page.dart';
+import 'facility_deposit_view_model.dart';
+import 'item_facility_deposit.dart';
+
+@RoutePage()
+class FacilityDepositScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(facilityDepositViewModelProvider.notifier);
+    final state = ref.watch(facilityDepositViewModelProvider);
+
+    useEffect(() {
+      // 组件挂载时执行 - 执行接口请求
+      Future.microtask(() => viewModel.fetchList());
+      return () {
+        // 组件卸载时执行
+      };
+    }, []);
+
+    return SizedBox(
+      width: double.infinity,
+      height: double.infinity,
+      child: EasyRefresh(
+        controller: viewModel.refreshController,
+        onRefresh: viewModel.onRefresh,
+        child: LoadStateLayout(
+          state: state.loadingState,
+          errorMessage: state.errorMessage,
+          errorRetry: () {
+            viewModel.retryRequest();
+          },
+          successSliverWidget: [
+            // 头布局
+            _buildHeaderWidget(context, ref),
+
+            // 列表
+            SliverList(
+                delegate: SliverChildBuilderDelegate(
+              (context, index) {
+                return FacilityDepositItem(index: index, item: state.datas[index]).onTap((){
+                  FacilityDetailPage.startInstance(context: context);
+                });
+              },
+              childCount: state.datas.length,
+            )),
+
+            //脚布局
+            _buildFootWidget(context, ref),
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+
+  //头布局
+  _buildHeaderWidget(BuildContext context, WidgetRef ref) {
+    return SliverToBoxAdapter(
+      child: Container(
+        width: double.infinity,
+        margin: const EdgeInsets.only(top: 10, left: 10, right: 10, bottom: 5),
+        child: Column(
+          children: [
+            // 上半部分
+            Container(
+              width: double.infinity,
+              padding: const EdgeInsets.all(16),
+              decoration: BoxDecoration(
+                color: context.appColors.btnBgDefault,
+                borderRadius: const BorderRadius.only(
+                  topLeft: Radius.circular(5),
+                  topRight: Radius.circular(5),
+                ),
+              ),
+              child: MyTextView(
+                S.current.deposit_amount,
+                fontSize: 18,
+                textAlign: TextAlign.center,
+                isFontMedium: true,
+                textColor: Colors.white,
+              ),
+            ),
+            // 下半部分
+            Container(
+              width: double.infinity,
+              padding: const EdgeInsets.all(26),
+              decoration:  BoxDecoration(
+                color: context.appColors.whiteSecondBG,
+                borderRadius: const BorderRadius.only(
+                  bottomLeft: Radius.circular(5),
+                  bottomRight: Radius.circular(5),
+                ),
+              ),
+              child: MyTextView(
+                "\$ 200.00",
+                fontSize: 30,
+                isFontBold: true,
+                textAlign: TextAlign.center,
+                textColor: context.appColors.textBlack,
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  //底部的说明文本脚布局
+  _buildFootWidget(BuildContext context, WidgetRef ref) {
+    return SliverToBoxAdapter(
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            S.current.deposit_desc,
+            fontSize: 20,
+            marginTop: 14,
+            marginRight: 15,
+            marginLeft: 20,
+            isFontMedium: true,
+            textColor: context.appColors.textBlack,
+          ),
+          MyTextView(
+            S.current.deposit_desc_txt,
+            marginTop: 14,
+            marginBottom: 14,
+            marginRight: 15,
+            marginLeft: 20,
+            fontSize: 15,
+            isFontRegular: true,
+            textColor: context.appColors.textBlack,
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 31 - 0
packages/cpt_facility/lib/modules/facility/deposit/facility_deposit_state.dart

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

+ 125 - 0
packages/cpt_facility/lib/modules/facility/deposit/facility_deposit_view_model.dart

@@ -0,0 +1,125 @@
+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 'facility_deposit_state.dart';
+
+part 'facility_deposit_view_model.g.dart';
+
+@riverpod
+class FacilityDepositViewModel extends _$FacilityDepositViewModel {
+  var _curPage = 1; //请求参数当前的页面
+  var _needShowPlaceholder = true; //是否展示LoadingView
+
+  // Refresh 控制器
+  final EasyRefreshController refreshController = EasyRefreshController(
+    controlFinishRefresh: true,  //允许刷新
+    controlFinishLoad: false,   //不允许加载
+  );
+
+  @override
+  FacilityDepositState build() {
+    final state = FacilityDepositState(datas: []);
+    return state;
+  }
+
+  //刷新页面状态
+  void changeLoadingState(LoadState loadState, String? errorMsg) {
+    state = state.copyWith(loadingState: loadState, errorMessage: errorMsg);
+  }
+
+  // Refresh 刷新事件
+  Future onRefresh() async {
+    _curPage = 1;
+    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_facility/lib/modules/facility/deposit/facility_deposit_view_model.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'facility_deposit_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$facilityDepositViewModelHash() =>
+    r'2b35e0ffd671d3ab67217b51dc076475f7e2a00a';
+
+/// See also [FacilityDepositViewModel].
+@ProviderFor(FacilityDepositViewModel)
+final facilityDepositViewModelProvider = AutoDisposeNotifierProvider<
+    FacilityDepositViewModel, FacilityDepositState>.internal(
+  FacilityDepositViewModel.new,
+  name: r'facilityDepositViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$facilityDepositViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$FacilityDepositViewModel = AutoDisposeNotifier<FacilityDepositState>;
+// 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_facility/lib/modules/facility/deposit/item_facility_deposit.dart

@@ -0,0 +1,55 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+///  设施的Deposit的Item
+class FacilityDepositItem extends StatelessWidget {
+  final int index;
+  final String item;
+
+  const FacilityDepositItem({
+    required this.index,
+    required this.item,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: double.infinity,
+      color: context.appColors.whiteBG,
+      margin: const EdgeInsets.only(top: 5),
+      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 23),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          MyTextView(
+            "Function Room Orange Room",
+            fontSize: 16.5,
+            textColor: context.appColors.textPrimary,
+            isFontMedium: true,
+          ),
+          Row(
+            children: [
+              MyTextView(
+                S.current.deposit_hold,
+                fontSize: 14.5,
+                textColor: context.appColors.textBlack,
+                isFontMedium: true,
+              ),
+              const Spacer(),
+              MyTextView(
+                "\$100.00",
+                fontSize: 14.5,
+                textColor: context.appColors.textBlack,
+                isFontMedium: true,
+              ),
+            ],
+          ).marginOnly(top: 10),
+        ],
+      ).expanded(),
+    );
+  }
+}

+ 156 - 0
packages/cpt_facility/lib/modules/facility/facility_page.dart

@@ -0,0 +1,156 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:auto_route/auto_route.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+import '../../router/page/facility_page_router.dart';
+import 'facility_view_model.dart';
+
+@RoutePage()
+class FacilityPage extends HookConsumerWidget {
+  const FacilityPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const FacilityPageRoute());
+    } else {
+      appRouter.push(const FacilityPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(facilityViewModelProvider.notifier);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(
+        context,
+        S.current.facility,
+        backgroundColor: context.appColors.whiteBG,
+      ),
+      backgroundColor: context.appColors.backgroundDark,
+      body: AutoTabsRouter.pageView(
+        routes: const [
+          FacilityBookPageRoute(),
+          FacilityActivePageRoute(),
+          FacilityDepositPageRoute(),
+          FacilityHistoryPageRoute(),
+        ],
+        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.facilityBookIcon,
+                      48.5,
+                      40,
+                      S.current.book,
+                      tabsRouter.activeIndex == 0,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(0);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.facilityActiveIcon,
+                      39,
+                      47.5,
+                      S.current.facility_active,
+                      tabsRouter.activeIndex == 1,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(1);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.facilityDepositIcon,
+                      35.5,
+                      41.5,
+                      S.current.deposit,
+                      tabsRouter.activeIndex == 2,
+                    ).onTap(
+                      () {
+                        tabsRouter.setActiveIndex(2);
+                      },
+                    ),
+                    _buildFeedbackCategory(
+                      context,
+                      Assets.mainLatestPublish,
+                      47.5,
+                      45,
+                      S.current.history,
+                      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,
+        ),
+      ],
+    );
+  }
+}

packages/cpt_facility/lib/modules/facility/vm/facility_view_model.dart → packages/cpt_facility/lib/modules/facility/facility_view_model.dart


packages/cpt_facility/lib/modules/facility/vm/facility_view_model.g.dart → packages/cpt_facility/lib/modules/facility/facility_view_model.g.dart


+ 56 - 0
packages/cpt_facility/lib/modules/facility/history/facility_history_screen.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:widgets/ext/ex_widget.dart';
+import 'package:widgets/load_state_layout.dart';
+import 'package:widgets/widget_export.dart';
+import '../../detail/facility_detail_page.dart';
+import 'facility_history_view_model.dart';
+import 'item_facility_history.dart';
+
+
+@RoutePage()
+class FacilityHistoryScreen extends HookConsumerWidget {
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.read(facilityHistoryViewModelProvider.notifier);
+    final state = ref.watch(facilityHistoryViewModelProvider);
+
+    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 FacilityHistoryItem(index: index, item: state.datas[index]).onTap((){
+                      FacilityDetailPage.startInstance(context: context);
+                    });
+                  },
+                  childCount: state.datas.length,
+                ))
+          ],
+        ),
+      ).marginOnly(top: 5, bottom: 5),
+    );
+  }
+}

+ 0 - 0
packages/cpt_facility/lib/modules/facility/history/facility_history_state.dart


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików