Browse Source

update community

glglove 3 months ago
parent
commit
763ce1226c
31 changed files with 623 additions and 211 deletions
  1. 22 6
      packages/cpt_community/lib/components/newsfeed_card_content.dart
  2. 67 59
      packages/cpt_community/lib/components/newsfeed_card_footer.dart
  3. 18 12
      packages/cpt_community/lib/modules/community/community_page.dart
  4. 17 0
      packages/cpt_community/lib/modules/community/community_vm.dart
  5. 15 5
      packages/cpt_community/lib/modules/garage/garagesale_detail/garagesale_detail_page.dart
  6. 2 0
      packages/cpt_community/lib/modules/garage/garagesale_detail/garagesale_detail_vm.dart
  7. 75 26
      packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_page.dart
  8. 19 0
      packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_state.dart
  9. 62 3
      packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_vm.dart
  10. 99 29
      packages/cpt_community/lib/modules/my_following/my_follow/my_follow_page.dart
  11. 10 0
      packages/cpt_community/lib/modules/my_following/my_follow/my_follow_vm.dart
  12. 20 0
      packages/cpt_community/lib/modules/my_following/my_follower/my_follower_page.dart
  13. 12 0
      packages/cpt_community/lib/modules/my_following/my_follower/my_follower_vm.dart
  14. 24 2
      packages/cpt_community/lib/modules/my_following/my_following_page.dart
  15. 6 2
      packages/cpt_community/lib/modules/my_following/my_following_state.dart
  16. 10 6
      packages/cpt_community/lib/modules/my_following/my_following_tabs.dart
  17. 29 4
      packages/cpt_community/lib/modules/my_following/my_following_vm.dart
  18. 4 2
      packages/cpt_community/lib/modules/my_posts/my_posts_forrent/my_posts_forrent_vm.dart
  19. 5 10
      packages/cpt_community/lib/modules/my_posts/my_posts_forsale/my_posts_forsale_vm.dart
  20. 43 25
      packages/cpt_community/lib/modules/my_posts/my_posts_newsfeed/my_posts_newsfeed_page.dart
  21. 2 2
      packages/cpt_community/lib/modules/my_posts/my_posts_newsfeed/my_posts_newsfeed_state.dart
  22. 7 0
      packages/cpt_community/lib/modules/my_posts/my_posts_newsfeed/my_posts_newsfeed_vm.dart
  23. 23 12
      packages/cpt_community/lib/modules/my_posts/my_posts_page.dart
  24. 4 0
      packages/cpt_community/lib/modules/my_posts/my_posts_state.dart
  25. 12 6
      packages/cpt_community/lib/modules/my_posts/my_posts_vm.dart
  26. 3 0
      packages/cpt_community/lib/router/component/community_component_service.dart
  27. BIN
      packages/cs_resources/assets/community/checkbox_selected.png
  28. BIN
      packages/cs_resources/assets/community/checkbox_unselected.png
  29. BIN
      packages/cs_resources/assets/community/fillter_icon.png
  30. 3 0
      packages/cs_resources/lib/generated/assets.dart
  31. 10 0
      packages/cs_widgets/lib/my_checkbox_group.dart

+ 22 - 6
packages/cpt_community/lib/components/newsfeed_card_content.dart

@@ -1,7 +1,13 @@
+import 'package:auto_route/src/route/page_route_info.dart';
 import 'package:cpt_community/components/comments_dialog.dart';
+import 'package:cpt_community/modules/community/community_page.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
+import 'package:plugin_basic/modules/global_web_page.dart';
+import 'package:plugin_basic/modules/preview_photo_page.dart';
+import 'package:router/componentRouter/component_service_manager.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';
@@ -19,15 +25,17 @@ import 'package:widgets/my_text_view.dart';
 
 class NewsFeedCardContent extends StatelessWidget {
   final String content;
-  final List? imageUrls;
+  final List<dynamic>? imageUrls;
   int? rowMaxImageNum=3;
   int? textMaxLines = 3;
+  bool? isPreviewImage = true;
   NewsFeedCardContent({
     Key? key,
     required this.content,
-    this.imageUrls,
+    required List<dynamic> this.imageUrls,
     this.rowMaxImageNum = 3,
-    this.textMaxLines = 3
+    this.textMaxLines = 3,
+    this.isPreviewImage = true,
   }) : super(key: key);
 
 
@@ -35,7 +43,7 @@ class NewsFeedCardContent extends StatelessWidget {
   Widget build(BuildContext context) {
     List imageUrlsList = [];
     if(imageUrls != null && imageUrls!.isNotEmpty){
-      // dart 取出 imageUrls 里面的前张图片
+      // dart 取出 imageUrls 里面的前 rowMaxImageNum 张图片
       imageUrlsList = imageUrls!.take(rowMaxImageNum!).toList();
     }
     int totalImageCount = imageUrls!.length;
@@ -61,7 +69,7 @@ class NewsFeedCardContent extends StatelessWidget {
                   ),
                   const SizedBox(height: 12),
                   // 图片
-                  _buildImageSection(context,maxWidth - 15, imageUrlsList, totalImageCount,otherImageCount),
+                  _buildImageSection(context, isPreviewImage!, maxWidth - 15, imageUrlsList, imageUrls, totalImageCount,otherImageCount),
                 ]
             )
           );
@@ -70,7 +78,7 @@ class NewsFeedCardContent extends StatelessWidget {
   }
 
 
-  Widget _buildImageSection(BuildContext context,double maxWidth, List? imageUrls, int totalImageCount, int otherImageCount) {
+  Widget _buildImageSection(BuildContext context,bool isPreviewImage, double maxWidth, List? imageUrls,List? totalImageUrls, int totalImageCount, int otherImageCount) {
     if (imageUrls != null && imageUrls!.isNotEmpty) {
       final imageCount = imageUrls.length;
       return SizedBox(
@@ -94,6 +102,14 @@ class NewsFeedCardContent extends StatelessWidget {
                         height: 87,
                         fit: BoxFit.cover,
                         cornerRadius: 5,
+                        onClick: (){
+                          if(isPreviewImage){
+                            // 点击图片预览
+                            // 过滤掉非字符串类型的元素
+                            List<String> filteredImages = totalImageUrls?.whereType<String>().toList() ?? [];
+                            PreviewPhotoPage.startInstance(context: context, images: filteredImages, position: index);
+                          }
+                        },
                       ),
                       otherImageCount > 0 && index == imageCount-1 ?
                         Positioned(

+ 67 - 59
packages/cpt_community/lib/components/newsfeed_card_footer.dart

@@ -42,71 +42,79 @@ class NewsFeedCardFooter extends StatelessWidget {
     return Container(
       height: 40,
       width: double.infinity,
-      padding: const EdgeInsets.symmetric(horizontal: 16),
-      // color: Colors.red,
+      // padding: const EdgeInsets.symmetric(horizontal: 16),
       child: Row(
         mainAxisAlignment: MainAxisAlignment.spaceBetween,
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
-          Container(
-            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(
-            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   ${tabsRouterKey.currentState?.controller?.activeIndex}");
-            // tabsRouterKey.currentState?.controller?.setActiveIndex(2);
-            onComment?.call();
-          }),
+          Expanded(
+            child: Container(
+              padding: const EdgeInsets.all(8),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.center,
+                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();
+            }),
+          ),
+          Expanded(
+            child: Container(
+              padding: const EdgeInsets.all(8),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.center,
+                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   ${tabsRouterKey.currentState?.controller?.activeIndex}");
+              // tabsRouterKey.currentState?.controller?.setActiveIndex(2);
+              onComment?.call();
+            }),
+          ),
           if(showShare)
-            Container(
-            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,
-                ),
-              ],
+            Expanded(
+              child: Container(
+              padding: const EdgeInsets.all(8),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.center,
+                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();
+                        }),
             ),
-          ).onTap((){
-            Log.d("点击了share");
-            onShare?.call();
-          }),
         ]
       )
     );

+ 18 - 12
packages/cpt_community/lib/modules/community/community_page.dart

@@ -60,20 +60,26 @@ class CommunityPage extends HookConsumerWidget {
         },[tabsRouterKey.currentState?.controller]);
 
         return Scaffold(
-            appBar: state.currentCategoryIdx == 0 ? MyAppBar.appBar(
-              context,
-              "Community",
-              backgroundColor: context.appColors.whiteBG,
-            ): MyAppBar.searchAppBar(
+            appBar: MyAppBar.searchAppBar(
               context,
               actions: [
-                IconButton(
-                  icon: const Icon(Icons.search),
-                  onPressed: () {
-                    // do something
-                    vm.handlerChooseGarageCategory(context);
-                  },
-                ),
+                 const MyAssetImage(
+                  Assets.communityLikeActive,
+                  width: 21.5,
+                  height: 21.5,
+                ).onTap((){
+                  vm.handlerClickNavbarLikeBtn(context);
+                 }),
+                SizedBox(width: state.currentCategoryIdx ==0 ? 15:20),
+                state.currentCategoryIdx ==1 ?
+                  const MyAssetImage(
+                    Assets.communityFillterIcon,
+                    width: 21,
+                    height: 21,
+                  ).onTap((){
+                    vm.handlerClickNavbarFilterBtn(context);
+                  }) : const SizedBox.shrink(),
+                const SizedBox(width: 15),
               ],
               backgroundColor: context.appColors.whiteBG,
             ),

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

@@ -175,6 +175,23 @@ class CommunityVm extends _$CommunityVm {
     );
   }
 
+  // 点击了导航栏的 like btn
+  handlerClickNavbarLikeBtn(BuildContext? context){
+    if(state.currentCategoryIdx ==0){
+      //
+      ToastEngine.show("点击了 newsfeed like");
+    }else if(state.currentCategoryIdx == 1){
+      //
+      ToastEngine.show("点击了 garagesale like");
+
+    }
+  }
+
+  // 点击了导航栏的 filter btn
+  handlerClickNavbarFilterBtn(BuildContext? context,){
+    ToastEngine.show("点击 filter");
+    handlerChooseGarageCategory(context!);
+  }
 
   // 点击发布的按钮 跳转到 newsfeed 发布的页面
   void handlerGotoNewsfeedPost(context){

+ 15 - 5
packages/cpt_community/lib/modules/garage/garagesale_detail/garagesale_detail_page.dart

@@ -33,7 +33,7 @@ class GaragesaleDetailPage extends HookConsumerWidget {
   Widget build(BuildContext context, WidgetRef ref) {
     final state = ref.watch(garagesaleDetailVmProvider);
     final vm = ref.read(garagesaleDetailVmProvider.notifier);
-    final String pageTitle = (type == 'forsale') ? 'For Sale' :'For Rent';
+    final String pageTitle = (type == 'forSale') ? 'For Sale' :'For Rent';
 
     useEffect((){
       // 组件挂载时执行 - 执行接口请求
@@ -69,7 +69,7 @@ class GaragesaleDetailPage extends HookConsumerWidget {
                   ),
                 ),
                 Visibility(
-                  visible: state.loadingState == LoadState.State_Success,
+                  visible: state.loadingState == LoadState.State_Success && state.datas!['contactType'] == 'WhatsApp',
                   child: _buildWhatsApp(context, ref),
                 ),
               ]
@@ -105,6 +105,7 @@ class GaragesaleDetailPage extends HookConsumerWidget {
     final state = ref.watch(garagesaleDetailVmProvider);
     String title = state.datas!['title'] ?? '';
     String price = state.datas!['price'] ?? '';
+    String contactType = state.datas!['contactType'] ?? '';
     String description = state.datas!['description'] ?? '';
     return Column(
       crossAxisAlignment: CrossAxisAlignment.start,
@@ -145,6 +146,8 @@ class GaragesaleDetailPage extends HookConsumerWidget {
   Widget _buildBottomConcatInfo(BuildContext context, WidgetRef ref) {
     final state = ref.watch(garagesaleDetailVmProvider);
     String publisher = state.datas!['publisher'] ?? '';
+    String contactType = state.datas!['contactType'] ?? '';
+    String contactInfo = state.datas!['contactInfo'] ?? '';
     String publisherAvatar = state.datas!['publisher_avatar'] ?? '';
     String publisherTime = state.datas!['publisher_time'] ?? '';
     int collectionNum = state.datas!['collection_num'] ?? 0;
@@ -191,9 +194,16 @@ class GaragesaleDetailPage extends HookConsumerWidget {
                   marginLeft: 5,
                   marginRight: 15,
                 ),
-                const SizedBox(width: 4,),
-                const MyAssetImage(Assets.communityPhone, width: 21.5,height: 18,),
-                const SizedBox(width: 15,),
+                Visibility(
+                  visible: contactType == 'Mobile Phone',
+                  child: const Row(
+                    children: [
+                      SizedBox(width: 4,),
+                      MyAssetImage(Assets.communityPhone, width: 21.5,height: 18,),
+                      SizedBox(width: 15,),
+                    ],
+                  ),
+                ),
               ],
             ),
           ),

+ 2 - 0
packages/cpt_community/lib/modules/garage/garagesale_detail/garagesale_detail_vm.dart

@@ -83,6 +83,8 @@ class GaragesaleDetailVm extends _$GaragesaleDetailVm {
       'price': '\$66',
       'description':'Electronic keyboards for sale. I will attend together with the booth.\$10 per day usage Negotiable usage',
       'isCollection': true,
+      'contactType': 'WhatsApp',
+      'contactInfo': '+1 123456789',
       'collection_num': 12,
       'publisher': 'William Jefferson',
       'publisher_avatar': 'https://img1.baidu.com/it/u=3890726495,1572750319&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',

+ 75 - 26
packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_page.dart

@@ -66,31 +66,70 @@ class GaragesalePostPage extends HookConsumerWidget {
                           ),
                           // 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['price']!['focusNode']);
-                                  },
-                                ),
-                              ]
-                            )
+                              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',
+                                      textInputType: TextInputType.text,
+                                      textInputAction: TextInputAction.next,
+                                      errorText: state.titleErrorText,
+                                      onSubmit: (formKey, value) {
+                                        state!.formData[formKey]!['focusNode'].unfocus();
+                                        FocusScope.of(context).requestFocus(state.formData['contactInfo']!['focusNode']);
+                                      },
+                                    ),
+                                  ]
+                              )
+                          ),
+                          // contact information
+                          Container(
+                              margin: const EdgeInsets.only(left:15, right:15, top: 15),
+                              child: Column(
+                                  crossAxisAlignment: CrossAxisAlignment.start,
+                                  children: [
+                                    FormRequireText(
+                                      text: "Contact Information",
+                                      textColor: context.appColors.textBlack,
+                                      fontSize: 17,
+                                    ).marginOnly(bottom: 14.5),
+                                    Row(
+                                      mainAxisSize: MainAxisSize.max,
+                                      crossAxisAlignment: CrossAxisAlignment.center,
+                                      children: [
+                                        SizedBox(
+                                          width: 160,
+                                          child: _buildContactTypeSelectCmp(context, ref),
+                                        ),
+                                        const SizedBox(width: 15),
+                                        Expanded(
+                                          child: _buildInputLayout(
+                                            context,
+                                            ref,
+                                            state,
+                                            'contactInfo',
+                                            textInputType: TextInputType.text,
+                                            textInputAction: TextInputAction.next,
+                                            errorText: state.contactInfoErrorText,
+                                            onSubmit: (formKey, value) {
+                                              state!.formData[formKey]!['focusNode'].unfocus();
+                                              FocusScope.of(context).requestFocus(state.formData['price']!['focusNode']);
+                                            },
+                                          ),
+                                        ),
+                                      ],
+                                    ),
+                                  ]
+                              )
                           ),
                           // price
                           Container(
@@ -108,7 +147,6 @@ class GaragesalePostPage extends HookConsumerWidget {
                                       ref,
                                       state,
                                       'price',
-                                      marginTop: 16,
                                       textInputType: TextInputType.text,
                                       textInputAction: TextInputAction.next,
                                       errorText: state.priceErrorText,
@@ -267,6 +305,17 @@ class GaragesalePostPage extends HookConsumerWidget {
     );
   }
 
+  /// contact Information 的select 选择
+  Widget _buildContactTypeSelectCmp(BuildContext context, WidgetRef ref, ){
+    final vm = ref.read(garagesalePostVmProvider.notifier);
+    final state = ref.watch(garagesalePostVmProvider);
+    return PickerContainer(
+      content: state.contactTypeSelectedOption ?? "",
+      hint: S.current.choose_category,
+      onClick: vm.pickContactTypeCallback,
+    );
+  }
+
   /// sale 选择
   Widget _buildSaleInputSelectCmp(BuildContext context, WidgetRef ref, ){
     final vm = ref.read(garagesalePostVmProvider.notifier);

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

@@ -4,6 +4,9 @@ class GaragesalePostPageState {
   //title 字段的错误信息展示
   String? titleErrorText;
 
+  //contactInfo 字段的错误信息展示
+  String? contactInfoErrorText;
+
   //price 字段的错误信息展示
   String? priceErrorText;
 
@@ -18,6 +21,13 @@ class GaragesalePostPageState {
   // 描述
   final String? description;
 
+  // contact type 类型选项
+  final List<String> contactTypeOptionsList = ["Mobile Phone", "WhatsApp", "Email"];
+  String? contactTypeSelectedOption;
+
+  // contact information
+  final String? contactInformation;
+
   //sale 类型选项
   final List<String> saleOptionsList = ["For Sale", "For Rent",];
   String? saleSelectedOption;
@@ -33,10 +43,13 @@ class GaragesalePostPageState {
     formData,
     required this.imgList,
     this.titleErrorText,
+    this.contactInfoErrorText,
     this.priceErrorText,
     this.descriptionErrorText,
     this.title,
     this.description,
+    this.contactInformation,
+    this.contactTypeSelectedOption,
     this.saleSelectedOption,
     this.categorySelectedOption,
   }): formData = formData ?? {
@@ -81,8 +94,11 @@ class GaragesalePostPageState {
     Map<String, Map<String, dynamic>>? formData,
     List<String>? imgList,
     String? titleErrorText,
+    String? contactInfoErrorText,
     String? priceErrorText,
     String? descriptionErrorText,
+    String? contactInformation,
+    String? contactTypeSelectedOption,
     String? saleSelectedOption,
     String? categorySelectedOption,
     String? title,
@@ -93,9 +109,12 @@ class GaragesalePostPageState {
       title: title ?? this.title,
       description: description ?? this.description,
       imgList: imgList ?? this.imgList,
+      contactInformation: contactInformation ?? this.contactInformation,
+      contactTypeSelectedOption: contactTypeSelectedOption ?? this.contactTypeSelectedOption,
       saleSelectedOption: saleSelectedOption ?? this.saleSelectedOption,
       categorySelectedOption: categorySelectedOption ?? this.categorySelectedOption,
       titleErrorText: titleErrorText ,
+      contactInfoErrorText: contactInfoErrorText,
       priceErrorText: priceErrorText ,
       descriptionErrorText: descriptionErrorText,
     );

+ 62 - 3
packages/cpt_community/lib/modules/garage/garagesale_post/garagesale_post_vm.dart

@@ -22,6 +22,7 @@ class GaragesalePostVm extends _$GaragesalePostVm {
   GaragesalePostPageState initState() {
     return GaragesalePostPageState(
       titleErrorText: null,
+      contactInfoErrorText: null,
       priceErrorText: null,
       descriptionErrorText: '',
       formData: {
@@ -46,6 +47,20 @@ class GaragesalePostVm extends _$GaragesalePostVm {
           'focusNode': FocusNode(),
           'obsecure': false,
         },
+        'contactInfoType': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': '',
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
+        'contactInfo': {
+          'value': '',
+          'controller': TextEditingController(),
+          'hintText': '',
+          'focusNode': FocusNode(),
+          'obsecure': false,
+        },
         'price': {
           'value': '',
           'controller': TextEditingController(),
@@ -85,6 +100,8 @@ class GaragesalePostVm extends _$GaragesalePostVm {
   //catogery 选择选项
   void pickCategoryCallback() {
     _dismissKeyboard(keyStr: 'title');
+    _dismissKeyboard(keyStr: 'price');
+    _dismissKeyboard(keyStr: 'contactInfo');
     _dismissKeyboard(keyStr: 'description');
 
     OptionPickerUtil.showCupertinoOptionPicker(
@@ -100,6 +117,7 @@ class GaragesalePostVm extends _$GaragesalePostVm {
   void pickSaleCallback() {
     _dismissKeyboard(keyStr: 'title');
     _dismissKeyboard(keyStr: 'price');
+    _dismissKeyboard(keyStr: 'contactInfo');
     _dismissKeyboard(keyStr: 'description');
 
     OptionPickerUtil.showCupertinoOptionPicker(
@@ -111,6 +129,22 @@ class GaragesalePostVm extends _$GaragesalePostVm {
     );
   }
 
+  //sale 选择选项
+  void pickContactTypeCallback() {
+    _dismissKeyboard(keyStr: 'title');
+    _dismissKeyboard(keyStr: 'price');
+    _dismissKeyboard(keyStr: 'contactInfo');
+    _dismissKeyboard(keyStr: 'description');
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.contactTypeOptionsList,
+      initialSelectIndex: 0,
+      onPickerChanged: (_, index) {
+        state = state.copyWith(contactTypeSelectedOption: state.contactTypeOptionsList[index]);
+      },
+    );
+  }
+
   // 获取聚焦的node
   FocusNode getFocusNode(Map<String, dynamic> formData, String keyStr) {
     return formData![keyStr]!['focusNode'];
@@ -163,18 +197,28 @@ class GaragesalePostVm extends _$GaragesalePostVm {
     // 获取表单的值
     String  saleValue= state.saleSelectedOption ?? "";
     String  categoryValue= state.categorySelectedOption ?? "";
+    String  contactTypeValue= state.contactTypeSelectedOption ?? "";
 
     String  titleValue= _getFormFieldValue(keyStr: 'title');
+    String  contactInfoValue= _getFormFieldValue(keyStr: 'contactInfo');
     String  priceValue= _getFormFieldValue(keyStr: 'price');
     String  descriptionValue= _getFormFieldValue(keyStr: 'description');
 
-    Log.d('当前待提交的 sale:$saleValue category:$categoryValue title:$titleValue price:$priceValue  description:$descriptionValue  imgList:${state.imgList}');
+    Log.d('当前待提交的 sale:$saleValue category:$categoryValue contactTypeValue:$contactTypeValue title:$titleValue  contactInfoValue:$contactInfoValue  price:$priceValue  description:$descriptionValue  imgList:${state.imgList}');
 
 
     if (Utils.isEmpty(saleValue)) {
       ToastEngine.show('Sale is empty');
       return;
     }
+    if (Utils.isEmpty(categoryValue)) {
+      ToastEngine.show('Category is empty');
+      return;
+    }
+    if (Utils.isEmpty(contactTypeValue)) {
+      ToastEngine.show('ContactType is empty');
+      return;
+    }
 
     if (Utils.isEmpty(titleValue)) {
       state = state.copyWith(titleErrorText: 'Title is empty',);
@@ -184,6 +228,14 @@ class GaragesalePostVm extends _$GaragesalePostVm {
       state = state.copyWith(titleErrorText: null);
     }
 
+    if (Utils.isEmpty(contactInfoValue)) {
+      state = state.copyWith(contactInfoErrorText: 'ContactInfo is empty',);
+      return;
+    }else {
+      state.contactInfoErrorText = null;
+      state = state.copyWith(contactInfoErrorText: null);
+    }
+
     if (Utils.isEmpty(priceValue)) {
       state = state.copyWith(priceErrorText: 'Price is empty',);
       return;
@@ -215,18 +267,25 @@ class GaragesalePostVm extends _$GaragesalePostVm {
 
     // 获取表单的焦点节点
     final FocusNode focusNode = getFocusNode(state.formData, 'title');
+    final FocusNode focusNodeContactInfo = getFocusNode(state.formData, 'contactInfo');
     final FocusNode focusNodePrice = getFocusNode(state.formData, 'price');
 
     focusNode.addListener(() {
       // 获取焦点的时候清空错误文本
       if (focusNode.hasFocus) {
-        state = state.copyWith(titleErrorText: null, priceErrorText:null, descriptionErrorText: null);
+        state = state.copyWith(contactInfoErrorText: null, titleErrorText: null, priceErrorText:null, descriptionErrorText: null);
+      }
+    });
+    focusNodeContactInfo.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (focusNodeContactInfo.hasFocus) {
+        state = state.copyWith(contactInfoErrorText: null, titleErrorText: null, priceErrorText:null, descriptionErrorText: null);
       }
     });
     focusNodePrice.addListener(() {
       // 获取焦点的时候清空错误文本
       if(focusNodePrice.hasFocus){
-        state = state.copyWith(titleErrorText: null,priceErrorText: null, descriptionErrorText: null);
+        state = state.copyWith(contactInfoErrorText: null, titleErrorText: null, priceErrorText:null, descriptionErrorText: null);
       }
     });
   }

+ 99 - 29
packages/cpt_community/lib/modules/my_following/my_follow/my_follow_page.dart

@@ -37,19 +37,36 @@ class MyFollowPage extends HookConsumerWidget {
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(myFollowVmProvider.notifier);
     final state = ref.watch(myFollowVmProvider);
+    final useSearchBar = useState(false);
+    // 用于存储前一次的滚动位置
+    final previousOffset = useState(0.0);
 
     useEffect(() {
       // 组件挂载时执行 - 执行接口请求
       Future.microtask(() => vm.initPageData());
+
+      // // 添加滚动监听器
+      // vm.refreshController!.addListener(() {
+      //   final scrollOffset = vm.refreshController.verticalOffset;
+      //   Log.d("Current scroll offset: $scrollOffset");
+      //
+      //   // 你可以在这里处理滚动事件
+      //   // 例如,当滚动到底部时加载更多数据
+      //   if (scrollOffset >= vm.refreshController.totalExtent - 100) {
+      //     vm.loadMore();
+      //   }
+      // });
+
       return () {
         // 组件卸载时执行
+        // vm.refreshController.removeListener(() {});
       };
     }, []);
 
     return  Scaffold(
         // appBar: MyAppBar.appBar(
         //   context,
-        //   "following",
+        //   '${useSearchBar.value}',
         //   backgroundColor: context.appColors.whiteBG,
         // ),
         backgroundColor: ColorUtils.string2Color("#F2F3F6"),
@@ -57,36 +74,89 @@ class MyFollowPage extends HookConsumerWidget {
           height: double.infinity,
           width: double.infinity,
           color: context.appColors.whiteBG,
-          child: EasyRefresh(
-            controller: vm.refreshController,
-            // 上拉加载
-            onLoad: () async{
-              Log.d("----onLoad");
-              vm.loadMore();
-            },
-            // 下拉刷新
-            onRefresh: () async{
-              Log.d("----onRefresh");
-              vm.onRefresh();
+          child: NotificationListener<ScrollNotification>(
+            onNotification: (ScrollNotification notification) {
+              if (notification is ScrollUpdateNotification) {
+                final ScrollMetrics metrics = notification.metrics;
+                final double currentOffset = metrics.pixels;
+                final double prevOffset = previousOffset.value;
+
+                Log.d("---最大滚动距离-----${metrics.maxScrollExtent}-------");
+
+                if (currentOffset > prevOffset) {
+                  // 向上滚动
+                  // 日志输出当前滚动偏移量和前一次滚动偏移量
+                  Log.d('--向上滚动---当前currentOffset: $currentOffset, previousOffset: $prevOffset---------');
+                  if(useSearchBar.value == false && metrics.maxScrollExtent >=0 && currentOffset >= 110){
+                    // 滚动到110 时 将 titlebar 换成 searchbar
+                    useSearchBar.value = true;
+                  }
+                } else if (currentOffset < prevOffset) {
+                  // 向下滚动
+                  // 日志输出当前滚动偏移量和前一次滚动偏移量
+                  Log.d('--向下滚动---当前currentOffset: $currentOffset, previousOffset: $prevOffset---------');
+                  if(useSearchBar.value == true && metrics.maxScrollExtent >=0 && currentOffset <= 110){
+                    // 滚动到110 时 将 searchbar 换成 titlebar
+                    useSearchBar.value = false;
+                  }
+                }
+                // 更新前一次的滚动位置
+                previousOffset.value = currentOffset;
+              }
+
+              // 返回 true 表示通知被消耗
+              return false;
             },
-            child: LoadStateLayout(
-              state: state.loadingState,
-              errorMessage: state.errorMessage,
-              errorRetry: () {
-                vm.retryRequest();
+            child: EasyRefresh(
+              controller: vm.refreshController,
+              // 上拉加载
+              onLoad: () async{
+                Log.d("----onLoad");
+                vm.loadMore();
+              },
+              // 下拉刷新
+              onRefresh: () async{
+                Log.d("----onRefresh");
+                vm.onRefresh();
               },
-              successSliverWidget:[
-                SliverList(
-                    delegate: SliverChildBuilderDelegate(
-                            (context, index){
-                          return _buildFollowItem(context, ref, state.list![index], vm, index, state.list.length);
-                        },
-                        childCount: state.list!.length
-                    )
-                )
-              ],
-            ),
-          ).marginOnly(left: 15,right: 15,top: 15,bottom: 15),
+              child: LoadStateLayout(
+                state: state.loadingState,
+                errorMessage: state.errorMessage,
+                errorRetry: () {
+                  vm.retryRequest();
+                },
+                successSliverWidget:[
+                  SliverList(
+                      delegate: SliverChildBuilderDelegate(
+                              (context, index){
+                            return Padding(
+                              padding: const EdgeInsets.only(top: 10, bottom: 10, left: 10),
+                              child: SearchAppBar(
+                                hintText: 'Search',
+                                onChanged: (String value){
+                                  vm.handlerSearchChange(value);
+                                },
+                                onSearch: (String value){
+                                  vm.handlerSubmitSearch(value);
+                                },
+                              ),
+                            );
+                          },
+                          childCount: 1
+                      )
+                  ),
+                  SliverList(
+                      delegate: SliverChildBuilderDelegate(
+                              (context, index){
+                            return _buildFollowItem(context, ref, state.list![index], vm, index, state.list.length);
+                          },
+                          childCount: state.list!.length
+                      )
+                  )
+                ],
+              ),
+            ).marginOnly(left: 15,right: 15,top: 15,bottom: 15),
+          ),
         )
     );
   }

+ 10 - 0
packages/cpt_community/lib/modules/my_following/my_follow/my_follow_vm.dart

@@ -6,6 +6,7 @@ import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../my_following_vm.dart';
 import 'my_follow_state.dart';
 
 part 'my_follow_vm.g.dart';
@@ -148,6 +149,15 @@ class MyFollowVm extends _$MyFollowVm {
 
     // 最后赋值
     _needShowPlaceholder = false;
+
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      // 需要更新 my_posts_tabs 里面的数字
+      ref.read(myFollowingVmProvider.notifier)
+          .updateMyFollowingTabsNum( 'followCount', state.list!.length, 0);
+    });
   }
 
+  handlerSearchChange(String value){}
+
+  handlerSubmitSearch(String value){}
 }

+ 20 - 0
packages/cpt_community/lib/modules/my_following/my_follower/my_follower_page.dart

@@ -46,6 +46,7 @@ class MyFollowerPage extends HookConsumerWidget {
       };
     }, []);
 
+
     return  Scaffold(
       // appBar: MyAppBar.appBar(
       //   context,
@@ -79,6 +80,25 @@ class MyFollowerPage extends HookConsumerWidget {
                 SliverList(
                     delegate: SliverChildBuilderDelegate(
                             (context, index){
+                          return Padding(
+                            padding: const EdgeInsets.only(top: 10, bottom: 10, left: 10),
+                            child: SearchAppBar(
+                              hintText: 'Search',
+                              onChanged: (String value){
+                                vm.handlerSearchChange(value);
+                              },
+                              onSearch: (String value){
+                                vm.handlerSubmitSearch(value);
+                              },
+                            ),
+                          );
+                        },
+                        childCount: 1
+                    )
+                ),
+                SliverList(
+                    delegate: SliverChildBuilderDelegate(
+                            (context, index){
                           return _buildFollowItem(context, ref, state.list![index], vm, index, state.list.length);
                         },
                         childCount: state.list!.length

+ 12 - 0
packages/cpt_community/lib/modules/my_following/my_follower/my_follower_vm.dart

@@ -1,3 +1,4 @@
+import 'package:cpt_community/modules/my_following/my_following_vm.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
@@ -148,6 +149,17 @@ class MyFollowerVm extends _$MyFollowerVm {
 
     // 最后赋值
     _needShowPlaceholder = false;
+
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      // 需要更新 my_posts_tabs 里面的数字
+      ref.read(myFollowingVmProvider.notifier)
+          .updateMyFollowingTabsNum( 'followerCount', state.list!.length, 1);
+    });
+
   }
 
+  handlerSearchChange(String value){}
+
+  handlerSubmitSearch(String value){}
+
 }

+ 24 - 2
packages/cpt_community/lib/modules/my_following/my_following_page.dart

@@ -6,6 +6,7 @@ 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: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';
@@ -26,6 +27,8 @@ import 'my_following_tabs.dart';
 import 'my_following_vm.dart';
 
 
+final myFollowingPageTabsRouterKey = GlobalKey<AutoTabsRouterState>();
+
 @RoutePage()
 class MyFollowingPage extends HookConsumerWidget {
   const MyFollowingPage({Key? key}) : super(key: key);
@@ -59,10 +62,29 @@ class MyFollowingPage extends HookConsumerWidget {
   Widget build(BuildContext context, WidgetRef ref) {
     final vm = ref.read(myFollowingVmProvider.notifier);
     final state = ref.watch(myFollowingVmProvider);
+
+    useEffect((){
+      Log.d("CommunityPage initState");
+      // 延迟监听
+      WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
+        if(myFollowingPageTabsRouterKey.currentState?.controller != null){
+          myFollowingPageTabsRouterKey.currentState?.controller?.addListener((){
+            vm.tabsRouterChange();
+          });
+        }
+      });
+
+      return (){
+        Log.d("CommunityPage dispose");
+        myFollowingPageTabsRouterKey.currentState?.controller?.removeListener(vm.tabsRouterChange);
+      };
+    },[myFollowingPageTabsRouterKey.currentState?.controller]);
+
+
     return Scaffold(
       appBar: MyAppBar.appBar(
         context,
-        "My Following",
+        myFollowingPageTabsRouterKey.currentState?.controller!.activeIndex == 0 ? "My Follow" : "My Follower",
         backgroundColor: context.appColors.whiteBG,
       ),
       backgroundColor: ColorUtils.string2Color("#F2F3F6"),
@@ -70,7 +92,7 @@ class MyFollowingPage extends HookConsumerWidget {
         children:[
           Expanded(
             child: AutoTabsRouter.pageView(
-              key: UniqueKey(),
+              key: myFollowingPageTabsRouterKey,
               routes: const [
                 MyFollowPageRoute(),
                 MyFollowerPageRoute(),

+ 6 - 2
packages/cpt_community/lib/modules/my_following/my_following_state.dart

@@ -1,12 +1,14 @@
 class MyFollowingState {
-  final List<String>? tabsList;
-  int? activeTabIdx;
+  List<String>? tabsList;
+  int? currentPageViewIdx = 0;
+  int? activeTabIdx = 0;
   int? followerCount;
   int? followCount;
 
   MyFollowingState({
     tabsList,
     activeTabIdx = 0,
+    currentPageViewIdx = 0,
     this.followerCount = 0,
     this.followCount = 0,
   }) : tabsList = tabsList ?? [
@@ -16,12 +18,14 @@ class MyFollowingState {
 
   MyFollowingState copyWith({
     List<String>? tabsList,
+    int? currentPageViewIdx,
     int? activeTabIdx,
     int? followerCount,
     int? followCount,
   }) {
     return MyFollowingState(
       tabsList: tabsList ?? this.tabsList,
+      currentPageViewIdx: currentPageViewIdx ?? this.currentPageViewIdx,
       activeTabIdx: activeTabIdx ?? this.activeTabIdx,
       followerCount: followerCount ?? this.followerCount,
       followCount: followCount ?? this.followCount,

+ 10 - 6
packages/cpt_community/lib/modules/my_following/my_following_tabs.dart

@@ -27,13 +27,13 @@ class MyFollowingTabs extends HookConsumerWidget {
     this.tabItemBuilder
   }) : super(key: key);
 
-  Widget _buildTabItem(BuildContext context, WidgetRef ref, vm, item, index) {
-    // 监听 activeIndex 的变化
+  Widget _buildTabItem(BuildContext context, WidgetRef ref, vm,state, item, index, int activeTabCounter) {
     final activeTabIdx = tabsRouter!.activeIndex;
 
-    final activeTabCounter = ref.watch(myFollowingVmProvider.select((state) =>
-      state.tabsList![index] == 'follow'? state.followerCount: state.followerCount
-    ));
+    // final activeTabCounter = ref.watch(myFollowingVmProvider.select((state) =>
+    //   state.tabsList![index] == 'follow'? state.followerCount: state.followerCount
+    // ));
+
 
     return Container(
       width: MediaQuery.of(context).size.width / vm.state.tabsList.length - 30,
@@ -68,6 +68,7 @@ class MyFollowingTabs extends HookConsumerWidget {
                     textColor: index == activeTabIdx ? Colors.white :ColorUtils.string2Color("#000000"),
                   ),
                   MyTextView(
+                    // '(${activeTabCounter.toString()})',
                     '(${activeTabCounter.toString()})',
                     fontSize: 16,
                     textAlign: TextAlign.center,
@@ -92,7 +93,10 @@ class MyFollowingTabs extends HookConsumerWidget {
     int tabsLength = tabsList.length;
 
     return List.generate(tabsLength, (index) {
-      return _buildTabItem(context, ref, vm, tabsList[index], index);
+      final followCount = state.followCount;
+      final followerCount = state.followerCount;
+      final activeTabCounter = (index == 0? followCount: followerCount);
+      return _buildTabItem(context, ref, vm, state, tabsList[index], index, activeTabCounter);
     });
   }
 

+ 29 - 4
packages/cpt_community/lib/modules/my_following/my_following_vm.dart

@@ -5,6 +5,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:auto_route/auto_route.dart';
 
+import 'my_following_page.dart';
 import 'my_following_state.dart';
 
 part 'my_following_vm.g.dart';
@@ -24,10 +25,34 @@ class MyFollowingVm extends _$MyFollowingVm {
     return state;
   }
 
-  handlerChangeTab(int activeTabIdx, TabsRouter tabsRouter){
-    Log.d("handlerChangeTab: $activeTabIdx");
-    state.activeTabIdx = activeTabIdx;
-    tabsRouter.setActiveIndex(activeTabIdx);
+  tabsRouterChange(){
+    Log.d("----tabsRouterChange---${myFollowingPageTabsRouterKey.currentState?.controller?.activeIndex}-");
+    state = state.copyWith(currentPageViewIdx: myFollowingPageTabsRouterKey.currentState?.controller?.activeIndex ?? 0);
   }
 
+  // 切换tab
+  handlerChangeTab(int tabIndex, TabsRouter? tabsRouter,) {
+    tabsRouter = (tabsRouter?? myFollowingPageTabsRouterKey.currentState?.controller)!;
+    tabsRouter.setActiveIndex(tabIndex);
+  }
+
+  setCurrentTabIndex(int activeTabIdx){
+    state = state.copyWith(
+      activeTabIdx: activeTabIdx,
+    );
+  }
+
+  updateMyFollowingTabsNum(String code, int num, int activeTabIdx){
+    if(code == 'followerCount'){
+      state = state.copyWith(
+        followerCount: num,
+        activeTabIdx: activeTabIdx,
+      );
+    } else if(code == 'followCount'){
+      state = state.copyWith(
+        followCount: num,
+        activeTabIdx: activeTabIdx,
+      );
+    }
+  }
 }

+ 4 - 2
packages/cpt_community/lib/modules/my_posts/my_posts_forrent/my_posts_forrent_vm.dart

@@ -173,8 +173,10 @@ class MyPostsForRentVm extends _$MyPostsForRentVm {
       refreshController.finishLoad();
     }
 
-    // 需要更新 my_posts_tabs 里面的数字
-    // ref.read(myPostsVmProvider.notifier).updateMyPostsTabsNum( 'forSale', state.list.length, 1);
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      // 需要更新 my_posts_tabs 里面的数字
+      ref.read(myPostsVmProvider.notifier).updateMyPostsTabsNum( 'forRent', state.list.length, 2);
+    });
 
     // 最后赋值
     _needShowPlaceholder = false;

+ 5 - 10
packages/cpt_community/lib/modules/my_posts/my_posts_forsale/my_posts_forsale_vm.dart

@@ -213,16 +213,11 @@ class MyPostsForSaleVm extends _$MyPostsForSaleVm {
     }
 
 
-    // if(_currentPageContext != null){
-    //   Log.d("994444  $_currentPageContext");
-    //   WidgetsBinding.instance.addPostFrameCallback((_) {
-    //     if (_currentPageContext != null) {
-    //       // 需要更新 my_posts_tabs 里面的数字
-    //       // ref.read(myPostsVmProvider.notifier).updateMyPostsTabsNum( 'forSale', state.list.length, 1);
-    //       // AutoTabsRouter.of(_currentPageContext!).setActiveIndex(1);
-    //     }
-    //   });
-    // }
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+        // 需要更新 my_posts_tabs 里面的数字
+      ref.read(myPostsVmProvider.notifier)
+          .updateMyPostsTabsNum( 'forSale', state.list.length, 1);
+    });
 
     // 最后赋值
     _needShowPlaceholder = false;

+ 43 - 25
packages/cpt_community/lib/modules/my_posts/my_posts_newsfeed/my_posts_newsfeed_page.dart

@@ -5,11 +5,13 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_basic/provider/app_config/app_config_service.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/load_state_layout.dart';
 import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
 
 import '../../../components/newsfeed_card_content.dart';
@@ -107,9 +109,9 @@ class MyPostsNewsfeedPage extends HookConsumerWidget {
                   delegate: SliverChildBuilderDelegate(
                         (context, index) {
                       return StickyHeader(
-                        header: _buildHeaderContent(state.list![index]),
+                        header: _buildHeaderContent(state.list![index], context),
                         content: Column(
-                          children: _buildGroupContent(state.list![index].itemgroupDatas , index, vm),
+                          children: _buildGroupContent(state.list![index].itemgroupDatas , index, vm, context),
                         ),
                       );
                     },
@@ -122,49 +124,65 @@ class MyPostsNewsfeedPage extends HookConsumerWidget {
     );
   }
 
-  Widget _buildHeaderContent(NewsFeedItemGroupState itemGroupDatas) {
+  Widget _buildHeaderContent(NewsFeedItemGroupState itemGroupDatas, BuildContext context,) {
     String groupId = itemGroupDatas.groupId;
     return Container(
       padding: const EdgeInsets.only(left: 15, right: 15,),
+      // color: context.appColors.backgroundDefault,
+      color: ColorUtils.string2Color('#F2F3F6'),
       child: NewsFeedStickyHeader(title: groupId,),
     );
   }
 
-  List<Widget> _buildGroupContent(List<Map<String, dynamic>> list, int groupIndex,  vm) {
+  List<Widget> _buildGroupContent(List<Map<String, dynamic>> list, int groupIndex,  vm, BuildContext context) {
     return list.asMap().entries.map((entry) {
       int childIndex = entry.key;
       Map<String, dynamic> item = entry.value;
       return Container(
         margin: const EdgeInsets.only(left: 15, right: 15, top: 14, bottom: 14),
-        color: Colors.white,
+        color: context.appColors.textWhite,
         padding: const EdgeInsets.only(left: 15, right: 15, top: 17, bottom: 17),
-        height: 280,
+        // height: 280,
         child: Column(
           mainAxisAlignment: MainAxisAlignment.center,
           crossAxisAlignment: CrossAxisAlignment.start,
           children: [
+            MyTextView(
+              item['time'],
+              textColor: context.appColors.textDarkGray,
+              fontSize: 12,
+              paddingLeft: 15,
+              marginBottom: 12.5,
+              isFontMedium: true,
+            ),
             // 卡片中间 (文字和图片)
-            Expanded(
-              child: NewsFeedCardContent(
-                key: UniqueKey(),
-                content: item['content'],
-                imageUrls: item["imageUrls"],
-              ),
+            NewsFeedCardContent(
+              key: UniqueKey(),
+              content: item['content'],
+              imageUrls: item["imageUrls"],
             ),
-            const SizedBox(height: 26),
+            const SizedBox(height: 15),
             // 卡片底部 (点赞 评论 分享)
-            NewsFeedCardFooter(
-              key: UniqueKey(),
-              isLike: true,
-              onLike: () {
-                vm.handlerClickActionBtn('like', item);
-              },
-              onComment: () {
-                vm.handlerClickActionBtn('comments', item);
-              },
-              onShare: () {
-                vm.handlerClickActionBtn('share', item);
-              },
+            Container(
+              decoration: BoxDecoration(
+                // color: Colors.white,
+                  border: Border(
+                    top: BorderSide(color: ColorUtils.string2Color('#EAEAEA'), width: 0.5),
+                  )
+              ),
+              child: NewsFeedCardFooter(
+                key: UniqueKey(),
+                isLike: true,
+                onLike: () {
+                  vm.handlerClickActionBtn('like', item);
+                },
+                onComment: () {
+                  vm.handlerClickActionBtn('comments', item);
+                },
+                onShare: () {
+                  vm.handlerClickActionBtn('share', item);
+                },
+              ),
             ),
           ],
         ),

+ 2 - 2
packages/cpt_community/lib/modules/my_posts/my_posts_newsfeed/my_posts_newsfeed_state.dart

@@ -31,12 +31,12 @@ class MyPostsNewsfeedState {
     {
       'code': 'forSale',
       'title': 'For Sale',
-      'publish_num': 28,
+      'publish_num': 0,
     },
     {
       'code': 'forRent',
       'title': 'For Rent',
-      'publish_num': 35,
+      'publish_num': 0,
     },
   ];
 

+ 7 - 0
packages/cpt_community/lib/modules/my_posts/my_posts_newsfeed/my_posts_newsfeed_vm.dart

@@ -11,6 +11,7 @@ import 'package:auto_route/auto_route.dart';
 import '../../../router/page/community_page_router.dart';
 
 import '../../community/newsfeed_detail/newsfeed_detail_page.dart';
+import '../my_posts_vm.dart';
 import 'my_posts_newsfeed_state.dart';
 import '../my_posts_repository.dart';
 import 'newsfeed_itemgroup_state.dart';
@@ -185,6 +186,12 @@ class MyPostsNewsfeedVm extends _$MyPostsNewsfeedVm {
 
     // 最后赋值
     _needShowPlaceholder = false;
+
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      // 需要更新 my_posts_tabs 里面的数字
+      ref.read(myPostsVmProvider.notifier)
+          .updateMyPostsTabsNum( 'newsFeed', state.list!.length, 0);
+    });
   }
 
 

+ 23 - 12
packages/cpt_community/lib/modules/my_posts/my_posts_page.dart

@@ -3,6 +3,7 @@ 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/log_utils.dart';
@@ -13,6 +14,8 @@ import '../my_posts/my_posts_newsfeed/my_posts_newsfeed_page.dart';
 import 'my_posts_tabs.dart';
 
 
+final myPostsPageTabsRouterKey = GlobalKey<AutoTabsRouterState>();
+
 @RoutePage()
 class MyPostsPage extends HookConsumerWidget {
   const MyPostsPage({Key? key}) : super(key: key);
@@ -31,7 +34,24 @@ class MyPostsPage extends HookConsumerWidget {
     BuildContext pageContext = context;
     final vm = ref.watch(myPostsVmProvider.notifier);
     final state = ref.watch(myPostsVmProvider);
-    var _pageController = null;
+
+    useEffect((){
+      Log.d("CommunityPage initState");
+      // 延迟监听
+      WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
+        if(myPostsPageTabsRouterKey.currentState?.controller != null){
+          myPostsPageTabsRouterKey.currentState?.controller?.addListener((){
+            vm.tabsRouterChange();
+          });
+        }
+      });
+
+      return (){
+        Log.d("CommunityPage dispose");
+        myPostsPageTabsRouterKey.currentState?.controller?.removeListener(vm.tabsRouterChange);
+      };
+    },[myPostsPageTabsRouterKey.currentState?.controller]);
+
     // // 创建 GlobalKey
     // final GlobalKey<AutoTabsRouterState> _tabsRouterKey = GlobalKey<AutoTabsRouterState>();
     return Scaffold(
@@ -45,7 +65,7 @@ class MyPostsPage extends HookConsumerWidget {
         children: [
           Expanded(
             child: AutoTabsRouter.pageView(
-              key: UniqueKey(),
+              key: myPostsPageTabsRouterKey,
               routes: const [
                 MyPostsNewsfeedPageRoute(),
                 MyPostsForSalePageRoute(),
@@ -53,15 +73,6 @@ class MyPostsPage extends HookConsumerWidget {
               ],
               builder: (context, child, pageController) {
                 final tabsRouter = AutoTabsRouter.of(context);
-                tabsRouter.addListener((){
-                  int currentIndex = tabsRouter.activeIndex;
-                  Log.d("MyPostsPage onPageChanged: $currentIndex");
-                  // vm.handlerChangeTab(context, currentIndex);
-                  // vm.setCurrentTabIndex(currentIndex);
-                });
-                // 恢复页面索引
-                // vm.restorePageViewIndex(pageController);
-
                 return Column(
                   children: [
                     // tab 标签
@@ -90,7 +101,7 @@ class MyPostsPage extends HookConsumerWidget {
         tabsRouter: null,
         onClickAction:(activeTabIdx){
           Log.d("点击的tab index: $activeTabIdx");
-          vm.handlerChangeTab(context, activeTabIdx);
+          vm.handlerChangeTab(activeTabIdx, null);
         },
       ),
     );

+ 4 - 0
packages/cpt_community/lib/modules/my_posts/my_posts_state.dart

@@ -1,18 +1,22 @@
 class MyPostsState {
   int activeTabIdx = 0;
   List<Map<String, dynamic>>? tabsList;
+  int currentPageViewIdx = 0;
 
   MyPostsState({
     this.activeTabIdx = 0,
     this.tabsList,
+    required this.currentPageViewIdx,
   });
 
   MyPostsState copyWith({
     int? activeTabIdx,
     List<Map<String, dynamic>>? tabsList,
+    int? currentPageViewIdx,
   }) {
     return MyPostsState(
       activeTabIdx: activeTabIdx ?? this.activeTabIdx,
+      currentPageViewIdx: currentPageViewIdx ?? this.currentPageViewIdx,
       tabsList: tabsList ?? this.tabsList,
     );
   }

+ 12 - 6
packages/cpt_community/lib/modules/my_posts/my_posts_vm.dart

@@ -9,6 +9,7 @@ import 'package:widgets/widget_export.dart';
 import 'package:auto_route/auto_route.dart';
 
 import '../../../router/page/community_page_router.dart';
+import 'my_posts_page.dart';
 import 'my_posts_state.dart';
 
 
@@ -29,6 +30,7 @@ class MyPostsVm extends _$MyPostsVm {
 
   MyPostsState initState() {
     return MyPostsState(
+        currentPageViewIdx: 0,
         tabsList: [
           {
             'code': 'newsFeed',
@@ -59,11 +61,15 @@ class MyPostsVm extends _$MyPostsVm {
   }
 
 
-  // 设置当前的 tabsRouter 和 pageController
-  handlerChangeTab(BuildContext context, int activeTabIdx) {
-    Log.d("handlerChangeTab: $activeTabIdx");
-    final tabsRouter = AutoTabsRouter.of(context);
-    tabsRouter.setActiveIndex(activeTabIdx);
+  tabsRouterChange(){
+    Log.d("----tabsRouterChange---${myPostsPageTabsRouterKey.currentState?.controller?.activeIndex}-");
+    state = state.copyWith(currentPageViewIdx: myPostsPageTabsRouterKey.currentState?.controller?.activeIndex ?? 0);
+  }
+
+  // 切换tab
+  handlerChangeTab(int tabIndex, TabsRouter? tabsRouter,) {
+    tabsRouter = (tabsRouter?? myPostsPageTabsRouterKey.currentState?.controller)!;
+    tabsRouter.setActiveIndex(tabIndex);
   }
 
   setCurrentTabIndex(int activeTabIdx){
@@ -80,7 +86,7 @@ class MyPostsVm extends _$MyPostsVm {
         }
         return e;
       }).toList(),
-      activeTabIdx: 1,
+      activeTabIdx: activeTabIdx,
     );
   }
 

+ 3 - 0
packages/cpt_community/lib/router/component/community_component_service.dart

@@ -26,14 +26,17 @@ class CommunityComponentService extends CommunityService {
     CommunityPage.startInstance();
   }
 
+  @override
   void startMyPostsPage() {
     MyPostsPage.startInstance();
   }
 
+  @override
   void startMyFollowPage() {
     MyFollowPage.startInstance();
   }
 
+  @override
   void startMyFollowerPage() {
     MyFollowerPage.startInstance();
   }

BIN
packages/cs_resources/assets/community/checkbox_selected.png


BIN
packages/cs_resources/assets/community/checkbox_unselected.png


BIN
packages/cs_resources/assets/community/fillter_icon.png


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

@@ -43,9 +43,12 @@ class Assets {
   static const String baseServiceTriangleDropDown = 'assets/base_service/triangle_drop_down.webp';
   static const String baseServiceTriangleDropDownIcon = 'assets/base_service/triangle_drop_down_icon.webp';
   static const String communityCamera = 'assets/community/camera.webp';
+  static const String communityCheckboxSelected = 'assets/community/checkbox_selected.png';
+  static const String communityCheckboxUnselected = 'assets/community/checkbox_unselected.png';
   static const String communityCollection = 'assets/community/collection.png';
   static const String communityComments = 'assets/community/comments.webp';
   static const String communityEdit = 'assets/community/edit.png';
+  static const String communityFillterIcon = 'assets/community/fillter_icon.png';
   static const String communityFollowAdd = 'assets/community/follow_add.webp';
   static const String communityGarageSale = 'assets/community/garage_sale.webp';
   static const String communityLike = 'assets/community/like.webp';

+ 10 - 0
packages/cs_widgets/lib/my_checkbox_group.dart

@@ -1,3 +1,4 @@
+import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 
 class MyCheckboxGroup extends StatefulWidget {
@@ -8,6 +9,8 @@ class MyCheckboxGroup extends StatefulWidget {
   final ValueChanged<List<Map<String, dynamic>>> onChanged;
   final List<Map<String, dynamic>>? defaultSelectedItems;
   final TextStyle? labelStyle;
+  final Color? acviteColor;
+  final Color? borderSideColor;
 
   MyCheckboxGroup({
     required this.items,
@@ -16,6 +19,8 @@ class MyCheckboxGroup extends StatefulWidget {
     this.nameStr = 'label',
     required this.onChanged,
     this.defaultSelectedItems,
+    this.acviteColor = const Color(0xFF4161D0),
+    this.borderSideColor = const Color(0xFF4161D0),
     this.labelStyle = const TextStyle(
       fontSize: 14,
       fontWeight: FontWeight.w500,
@@ -32,6 +37,7 @@ class _MyCheckboxGroupState extends State<MyCheckboxGroup> {
   @override
   void initState() {
     super.initState();
+
     if (widget.defaultSelectedItems != null) {
       _selectedItemKeys.addAll(widget.defaultSelectedItems!.map((item) => item[widget.valueStr] as String));
       widget.onChanged(widget.items.where((item) => _selectedItemKeys.contains(item[widget.valueStr] as String)).toList());
@@ -66,6 +72,10 @@ class _MyCheckboxGroupState extends State<MyCheckboxGroup> {
           child: Row(
             children: [
               Checkbox(
+                activeColor: widget.acviteColor ?? context.appColors.textPrimary,
+                side: BorderSide(
+                  color: widget.borderSideColor ?? context.appColors.textPrimary,
+                ),
                 value: _selectedItemKeys.contains(key),
                 onChanged: (bool? checked) {
                   if (checked != null) {