Browse Source

update property module

glglove 4 months ago
parent
commit
8e666a2312
23 changed files with 1124 additions and 73 deletions
  1. 40 21
      packages/cpt_property/lib/modules/news/page/property_news_page.dart
  2. 49 0
      packages/cpt_property/lib/modules/news/page/property_news_state.dart
  3. 71 0
      packages/cpt_property/lib/modules/news/repository/property_news_repository.dart
  4. 29 0
      packages/cpt_property/lib/modules/news/repository/property_news_repository.g.dart
  5. 119 24
      packages/cpt_property/lib/modules/news/vm/property_news_vm.dart
  6. 26 0
      packages/cpt_property/lib/modules/news/vm/property_news_vm.g.dart
  7. 4 4
      packages/cpt_property/lib/modules/news_detail/property_news_detail_page.dart
  8. 126 2
      packages/cpt_property/lib/modules/rent/page/property_rent_page.dart
  9. 49 0
      packages/cpt_property/lib/modules/rent/page/property_rent_state.dart
  10. 70 0
      packages/cpt_property/lib/modules/rent/repository/property_rent_repository.dart
  11. 29 0
      packages/cpt_property/lib/modules/rent/repository/property_rent_repository.g.dart
  12. 92 3
      packages/cpt_property/lib/modules/rent/vm/property_rent_vm.dart
  13. 3 3
      packages/cpt_property/lib/modules/rent/vm/property_rent_vm.g.dart
  14. 106 2
      packages/cpt_property/lib/modules/sale/page/property_sale_page.dart
  15. 49 0
      packages/cpt_property/lib/modules/sale/page/property_sale_state.dart
  16. 70 0
      packages/cpt_property/lib/modules/sale/repository/property_sale_repository.dart
  17. 29 0
      packages/cpt_property/lib/modules/sale/repository/property_sale_repository.g.dart
  18. 90 3
      packages/cpt_property/lib/modules/sale/vm/property_sale_vm.dart
  19. 3 3
      packages/cpt_property/lib/modules/sale/vm/property_sale_vm.g.dart
  20. 2 1
      packages/cpt_property/lib/router/page/property_page_router.dart
  21. 7 7
      packages/cpt_property/lib/router/page/property_page_router.gr.dart
  22. 26 0
      packages/cs_shared/lib/utils/color_utils.dart
  23. 35 0
      packages/cs_shared/lib/utils/util.dart

+ 40 - 21
packages/cpt_property/lib/modules/news/page/property_news_page.dart

@@ -4,6 +4,7 @@ import 'package:auto_route/auto_route.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/widget_export.dart';
@@ -25,14 +26,15 @@ class PropertyNewsPage extends HookConsumerWidget {
     }
   }
 
-  Widget _buildItemLeftSection(BuildContext context,WidgetRef ref, String item, _vm) {
+  Widget _buildItemLeftSection(BuildContext context,WidgetRef ref, item, _vm) {
     return Container(
       // color: Colors.blue,
       width: 100,
       height: 117.5,
-      child: const Center(
-        child: MyAssetImage(
-          Assets.propertyNewsItemBg,
+      child: Center(
+        child: MyLoadImage(
+          item['pic'],
+          placeholderPath: Assets.propertyNewsItemBg,
           width: 60.5,
           height: 50.5,
         ),
@@ -40,14 +42,24 @@ class PropertyNewsPage extends HookConsumerWidget {
     ).marginOnly(right: 17.5);
   }
 
-  Widget _buildItemRightSection(BuildContext context,WidgetRef ref, String item, _vm) {
+  Widget _buildItemRightSection(BuildContext context,WidgetRef ref, item, _vm) {
+
+    // 使用 ref.select 监听 list 中 item 的 Map 对象中的 isCollection 字段
+    final isCollection = ref.watch(propertyNewsVmProvider.select((state) {
+      final curItem = state.list.firstWhere(
+            (valueItem) => valueItem['id'] == item['id'],
+        orElse: () => {'isCollection': false},
+      );
+      return curItem['isCollection'] as bool;
+    }));
+
     return Container(
       color: Colors.white,
-      padding: EdgeInsets.only(top: 10.5, bottom: 10.5),
+      padding: const EdgeInsets.only(top: 10.5, bottom: 10.5),
       child: Container(
         child: Stack(
           children: [
-            const Column(
+            Column(
               mainAxisAlignment: MainAxisAlignment.start,
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
@@ -55,36 +67,36 @@ class PropertyNewsPage extends HookConsumerWidget {
                   children: [
                     Expanded(
                       child: Text(
-                        "Developer'snew homesales shrink to lowest forthe",
+                        item['title'],
                         maxLines: 2, // 设置最大行数为2
                         overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
-                        style: TextStyle(fontSize: 16.0, color: Colors.black, fontWeight: FontWeight.w500), // 设置字体大小
+                        style: const TextStyle(fontSize: 16.0, color: Colors.black, fontWeight: FontWeight.w400), // 设置字体大小
                       ),
                     )
                   ],
                 ),
-                SizedBox(height: 10.5),
+                const SizedBox(height: 10.5),
                 Row(
                   children: [
                     Expanded(
                       child: Text(
-                        'New home sales in August shrank 64% and are downand are downand are downand are down and are down',
+                        item['description'],
                         maxLines: 2, // 设置最大行数为2
                         overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
-                        style: TextStyle(fontSize: 12.0, color: Colors.black), // 设置字体大小
+                        style: const TextStyle(fontSize: 12.0, color: Colors.black), // 设置字体大小
                       ),
                     )
                   ]
                 ),
-                SizedBox(height: 12.5),
+                const SizedBox(height: 12.5),
                 Row(
                     children: [
                       Expanded(
                         child: Text(
-                          '1H Ago',
+                          Utils.getTimeAgo(item['time']),
                           maxLines: 1, // 设置最大行数为2
                           overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
-                          style: TextStyle(fontSize: 12.0, color: Colors.black), // 设置字体大小
+                          style: const TextStyle(fontSize: 12.0, color: Colors.black), // 设置字体大小
                         ),
                       )
                     ]
@@ -94,8 +106,9 @@ class PropertyNewsPage extends HookConsumerWidget {
             Positioned(
               right: 5,
               bottom: 0,
-              child: const MyAssetImage(Assets.propertyCollection,width:22,height: 20.5,).onTap((){
+              child: MyAssetImage(isCollection? Assets.propertyCollectionActive:Assets.propertyCollection,width:22,height: 20.5,).onTap((){
                 Log.d("点击了收藏按钮");
+                _vm.handlerCollection(item, isCollection);
               }),
             ),
           ],
@@ -105,7 +118,7 @@ class PropertyNewsPage extends HookConsumerWidget {
   }
 
   // listitem
-  Widget _buildNewsItem(BuildContext context,WidgetRef ref, String item, _vm) {
+  Widget _buildNewsItem(BuildContext context,WidgetRef ref, item, _vm) {
     return Row(
       mainAxisAlignment: MainAxisAlignment.center,
       crossAxisAlignment: CrossAxisAlignment.center,
@@ -134,11 +147,13 @@ class PropertyNewsPage extends HookConsumerWidget {
 
   // list
   Widget _buildNewsList(BuildContext context, WidgetRef ref, _vm) {
-    List items = List.generate(20, (index) => "Item $index");
+    // List items = List.generate(20, (index) => "Item $index");
+    // List items = _vm.state.list.fromJson();
+    List itemsList = _vm.state.list.toList();
     return ListView.builder(
-      itemCount: items.length,
+      itemCount: itemsList.length,
       itemBuilder: (context, index) {
-        return _buildNewsItem(context, ref, items[index], _vm);
+        return _buildNewsItem(context, ref, itemsList[index], _vm);
       },
     );
   }
@@ -151,10 +166,14 @@ class PropertyNewsPage extends HookConsumerWidget {
       // appBar: AppBar(title: Text("资产")),
       body: Container(
         child: EasyRefresh(
+          // 上拉加载
           onLoad: () async{
-            _vm.initListData();
+            Log.d("----onLoad");
+            _vm.onLoadData();
           },
+          // 下拉刷新
           onRefresh: () async{
+            Log.d("----onRefresh");
             _vm.refreshListData();
           },
           child: _buildNewsList(context, ref, _vm),

+ 49 - 0
packages/cpt_property/lib/modules/news/page/property_news_state.dart

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

+ 71 - 0
packages/cpt_property/lib/modules/news/repository/property_news_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 '../page/property_news_state.dart';
+
+part 'property_news_repository.g.dart';
+
+@Riverpod(keepAlive: true)
+PropertyNewsRepository propertyNewsRepository(Ref ref) {
+  final dioEngine = ref.watch(dioEngineProvider);
+  return PropertyNewsRepository(dioEngine: dioEngine);
+}
+
+/*
+ * 数据仓库
+ */
+class PropertyNewsRepository {
+  DioEngine dioEngine;
+
+  PropertyNewsRepository({required this.dioEngine});
+
+  Future<HttpResult<Object>> fetchPropertyNewsList(
+      Map<String, dynamic>? data, {
+        CancelToken? cancelToken,
+      }) async {
+    Map<String, dynamic> params = {};
+
+    // if (!Utils.isEmpty(type)) {
+    //   params["type"] = type!;
+    // }
+
+    params = data!;
+
+
+    Map<String, String> headers = {};
+
+    headers["Content-Type"] = "application/x-www-form-urlencoded";
+    headers["Accept"] = "application/x.yyjobs-api.v1+json";
+
+    final result = await dioEngine.requestNetResult(
+      // ApiConstants.apiServerTime, // api 地址
+      '/index.php/api/employee/extra/time', // api 地址
+      params: params,
+      headers: headers,
+      method: HttpMethod.GET,
+      isShowLoadingDialog: true,  //是否展示默认的Loading弹窗
+      networkDebounce: true,   //是否防抖防止重复请求
+      cancelToken: cancelToken,
+    );
+
+    //根据返回的结果,封装原始数据为Bean/Entity对象
+    if (result.isSuccess) {
+      //重新赋值data或list
+      final json = result.getDataJson();
+      var data = PropertyNewsState.fromJson(json!);
+      //重新赋值data或list
+      return result.convert<PropertyNewsState>(data: data);
+    }
+    return result.convert();
+  }
+
+
+}

+ 29 - 0
packages/cpt_property/lib/modules/news/repository/property_news_repository.g.dart

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

+ 119 - 24
packages/cpt_property/lib/modules/news/vm/property_news_vm.dart

@@ -1,38 +1,133 @@
-
+import 'package:plugin_platform/http/http_result.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import '../page/property_news_state.dart';
-
+import '../repository/property_news_repository.dart';
 part 'property_news_vm.g.dart';
 
 @riverpod
 class PropertyNewsVm extends _$PropertyNewsVm {
-    PropertyNewsState initState() {
-      return PropertyNewsState();
-    }
+  late PropertyNewsRepository propertyNewsRepository;
+  PropertyNewsState initState() {
+    return PropertyNewsState(
+      curPage: 1,
+      pageSize: 10,
+      list: [
+        {
+          "id": 1,
+          "title": "fkladsfk fldask fldsakfllfkaslsd",
+          "description": "fsklfdsk罚款乱收费上课了发送卡",
+          "time": "2024-02-15 12:00:00",
+          "isCollection": true,
+          "pic": ""
+        },
+        {
+          "id": 2,
+          "title": "JHKFDSAJKjfkdsfjkasjkjklfajfkajifwoqirujweiqofjndsaikfniasdhfiasdhfiadshfifjadslfjkdlsafjlkadsj",
+          "description": "oifosjf fjdskafj hjiwehfriohjfiash",
+          "time": "2024-10-16 12:00:00",
+          "isCollection": false,
+          "pic": ""
+        },
+      ],
+      filterCount: 2,
+    );
+  }
 
-    @override
-    PropertyNewsState build(){
-       PropertyNewsState state = initState();
-       return state;
-    }
+  @override
+  PropertyNewsState build() {
+    // 引入数据仓库
+    propertyNewsRepository = ref.read(propertyNewsRepositoryProvider);
+    // 初始化状态
+    PropertyNewsState state = initState();
+    // 初始化列表数据
+    return state;
+  }
 
-    Future initListData() async {
-      Log.d("initListData");
-      await Future.delayed(const Duration(seconds: 2));
-      // items = List.generate(20, (index) => "Item $index");
-    }
+  // 初始化页面数据
+  initPageData() {
+    Log.d("----property_news_vm-----initPageData");
+    refreshListData();
+  }
+
+  // 上拉加载
+  Future onLoadData() async {
+    Log.d("----property_news_vm-----initListData");
+    // await Future.delayed(const Duration(seconds: 2));
+    // if(state.list.length >= state.filterCount){
+    //   return;
+    // }else {
+    //   int curPage = state.curPage + 1;
+    //   state = state.copyWith(curPage: curPage,);
+    //   getListData();
+    // }
+    getListData();
+  }
 
-    Future refreshListData() async {
-      await Future.delayed(const Duration(seconds: 2));
-      // setState(() {
-      //   items.addAll(List.generate(20, (index) => "Item ${items.length + index}"));
-      // });
+  // 获取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 propertyNewsRepository.fetchPropertyNewsList(params);
+      Log.d("请求完成结果------${result.data}");
+      //校验成功失败
+      if (result.isSuccess) {
+        // state = state.copyWith(serverTime: result.data);
+        state = state;
+        ToastEngine.show("获取数据成功");
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
     }
+  }
+
+
+  // 下拉刷新
+  Future refreshListData() async {
+    Log.d("----property_news_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(propertyNewsVmProvider);
+    getListData();
+
+  }
+
+  // 去新闻详情页
+  void goNewsDetail(String item) {
+    Log.d("goNewsDetail");
+    // PropertyPage.startInstance(context: context, item: item);
+  }
+
+  // 收藏/取消收藏
+  void handlerCollection(curItem, bool isCollection){
 
-    // 去新闻详情页
-    void goNewsDetail(String item) {
-      Log.d("goNewsDetail");
-      // PropertyPage.startInstance(context: context, item: item);
+    List<Map<String, dynamic>> newList = state.list.map((item) {
+        if(item['id'] == curItem['id']){
+          return {
+            ...item,
+            'isCollection': !isCollection
+          };
+        }
+        return item;
+    }).toList();
+    // Log.d("handlerCollection $newList");
+    state = state.copyWith(list: newList);
+    if(isCollection){
+      ToastEngine.show("取消收藏");
+    }else {
+      ToastEngine.show("收藏成功");
     }
+  }
 }

+ 26 - 0
packages/cpt_property/lib/modules/news/vm/property_news_vm.g.dart

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

+ 4 - 4
packages/cpt_property/lib/modules/news_detail/property_news_detail_page.dart

@@ -9,15 +9,15 @@ import '../../router/page/property_page_router.dart';
 import './property_news_detail_vm.dart';
 
 @RoutePage()
-class PropertyNewsDetailPageRoute extends HookConsumerWidget {
-  const PropertyNewsDetailPageRoute({Key? key}) : super(key: key);
+class PropertyNewsDetailPage extends HookConsumerWidget {
+  const PropertyNewsDetailPage({Key? key}) : super(key: key);
 
   //启动当前页面
   static void startInstance({BuildContext? context}) {
     if (context != null) {
-      context.router.push(const PropertyIoanPageRoute());
+      context.router.push(const PropertyNewsPageRoute());
     } else {
-      appRouter.push(const PropertyIoanPageRoute());
+      appRouter.push(const PropertyNewsPageRoute());
     }
   }
 

+ 126 - 2
packages/cpt_property/lib/modules/rent/page/property_rent_page.dart

@@ -1,7 +1,14 @@
+import 'package:cpt_property/modules/property/page/property_page.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:cs_resources/generated/assets.dart';
 
 import '../../../router/page/property_page_router.dart';
 import '../vm/property_rent_vm.dart';
@@ -19,14 +26,131 @@ class PropertyRentPage extends HookConsumerWidget {
     }
   }
 
+  Widget _buildItemLeftSection(BuildContext context,WidgetRef ref, item, _vm) {
+    return Container(
+      // color: Colors.blue,
+      child:
+      Text(item['title'],
+        style: const TextStyle(fontSize: 16.0, color: Colors.black, fontWeight: FontWeight.w400), // 设置字体大小
+      ),
+    ).marginOnly(right: 17.5);
+  }
+
+  Widget _buildItemRightSection(BuildContext context,WidgetRef ref, item, _vm) {
+
+    return Container(
+      color: Colors.white,
+      child: TextButton(
+        onPressed: (){},
+        style: TextButton.styleFrom(
+          foregroundColor: Colors.black,
+          backgroundColor: ColorUtils.string2Color('#EFF3FF'), // 背景颜色
+          // minimumSize: const Size(71, 30), // 最小宽度和高度
+          padding: const EdgeInsets.symmetric(horizontal: 17.5, vertical: 7.5), // 内边距
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(5), // 圆角
+            side: BorderSide(
+              color: ColorUtils.string2Color('#EFF3FF'),
+              width: 1.0,
+            ), // 边框
+          ),
+        ),
+        child: Container(
+          height: 44,
+          child: Column(
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: [
+              Text(
+                item['price'],
+                style: const TextStyle(
+                  fontSize: 17, // 字体大小
+                  fontWeight: FontWeight.bold, // 字体粗细
+                ),
+              ),
+              Text(
+                item['unit'],
+                style: const TextStyle(
+                  fontSize: 12, // 字体大小
+                  fontWeight: FontWeight.normal, // 字体粗细
+                ),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  // listitem
+  Widget _buildRentItem(BuildContext context,WidgetRef ref, item, _vm) {
+    return Container(
+      // color: Colors.red,
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.center,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        mainAxisSize: MainAxisSize.max,
+        children: [
+          Container(
+            width: MediaQuery.of(context).size.width - 30,
+            height: 100,
+            margin: const EdgeInsets.only(left: 15,right: 15,top: 12.5),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.start,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                Expanded(child: _buildItemLeftSection(context, ref, item, _vm)),
+                Container(
+                  width: 100,
+                  child: _buildItemRightSection(context, ref, item, _vm),
+                ),
+              ],
+            ),
+          ).constrained(
+            minHeight: 117.5,
+          ),
+        ],
+      ).onTap((){
+        // 去详情
+        _vm.goNewsDetail(item);
+      }),
+    ).border(color: ColorUtils.string2Color('C9C9C9FF'), bottom: 0.5);
+  }
+
+  // list
+  Widget _buildRentList(BuildContext context, WidgetRef ref, _vm) {
+    List itemsList = _vm.state.list.toList();
+    return ListView.builder(
+      itemCount: itemsList.length,
+      itemBuilder: (context, index) {
+        return _buildRentItem(context, ref, itemsList[index], _vm);
+      },
+    );
+  }
+
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final _vm = ref.read(propertyRentVmProvider.notifier);
 
     return Scaffold(
       // appBar: AppBar(title: Text("资产")),
-      body: Center(
-        child: Text("房屋rent的主页面"),
+      body: Container(
+          child: EasyRefresh(
+            // 上拉加载
+            onLoad: () async{
+              Log.d("----onLoad");
+              _vm.onLoadData();
+            },
+            // 下拉刷新
+            onRefresh: () async{
+              Log.d("----onRefresh");
+              _vm.refreshListData();
+            },
+            child: Container(
+                color: Colors.white,
+                margin: const EdgeInsets.only(top: 5),
+                child: _buildRentList(context, ref, _vm)
+            ),
+          )
       ),
     );
   }

+ 49 - 0
packages/cpt_property/lib/modules/rent/page/property_rent_state.dart

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

+ 70 - 0
packages/cpt_property/lib/modules/rent/repository/property_rent_repository.dart

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

+ 29 - 0
packages/cpt_property/lib/modules/rent/repository/property_rent_repository.g.dart

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

+ 92 - 3
packages/cpt_property/lib/modules/rent/vm/property_rent_vm.dart

@@ -1,13 +1,102 @@
-
+import 'package:plugin_platform/http/http_result.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
-
+import 'package:shared/utils/log_utils.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import '../page/property_rent_state.dart';
+import '../repository/property_rent_repository.dart';
 part 'property_rent_vm.g.dart';
 
 @riverpod
 class PropertyRentVm extends _$PropertyRentVm {
+  late PropertyRentRepository propertyRentRepository;
+  PropertyRentState initState() {
+    return PropertyRentState(
+      curPage: 1,
+      pageSize: 10,
+      list: [
+        {
+          "id": 1,
+          "title": "Jul 2024  Blk XX #XX to XX 1,100 - 1,200 sqft",
+          "price": "\$4000",
+          "unit": "per month",
+        },
+        {
+          "id": 2,
+          "title": "Jul 2024  Blk XX #XX to XX 1,100 - 1,200 sqft",
+          "price": "\$4000",
+          "unit": "per month",
+        },
+      ],
+      filterCount: 2,
+    );
+  }
 
   @override
-  void build(){
+  PropertyRentState build() {
+    // 引入数据仓库
+    propertyRentRepository = ref.read(propertyRentRepositoryProvider);
+    // 初始化状态
+    PropertyRentState state = initState();
+    // 初始化列表数据
+    return state;
+  }
+
+  // 初始化页面数据
+  initPageData() {
+    Log.d("----property_news_vm-----initPageData");
+    refreshListData();
+  }
+
+  // 上拉加载
+  Future onLoadData() async {
+    Log.d("----property_news_vm-----initListData");
+    // await Future.delayed(const Duration(seconds: 2));
+    // if(state.list.length >= state.filterCount){
+    //   return;
+    // }else {
+    //   int curPage = state.curPage + 1;
+    //   state = state.copyWith(curPage: curPage,);
+    //   getListData();
+    // }
+    getListData();
+  }
+
+  // 获取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 propertyRentRepository.fetchPropertyNewsList(params);
+      Log.d("请求完成结果------${result.data}");
+      //校验成功失败
+      if (result.isSuccess) {
+        // state = state.copyWith(serverTime: result.data);
+        state = state;
+        ToastEngine.show("获取数据成功");
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+  }
+
+
+  // 下拉刷新
+  Future refreshListData() async {
+    Log.d("----property_news_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(propertyNewsVmProvider);
+    getListData();
 
   }
 

+ 3 - 3
packages/cpt_property/lib/modules/rent/vm/property_rent_vm.g.dart

@@ -6,12 +6,12 @@ part of 'property_rent_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$propertyRentVmHash() => r'7746ebd091e4bfe92688f58d8fe1aa74eb7c09fc';
+String _$propertyRentVmHash() => r'559a07babdbac1dec99265f26e54369ace0b03ae';
 
 /// See also [PropertyRentVm].
 @ProviderFor(PropertyRentVm)
 final propertyRentVmProvider =
-    AutoDisposeNotifierProvider<PropertyRentVm, void>.internal(
+    AutoDisposeNotifierProvider<PropertyRentVm, PropertyRentState>.internal(
   PropertyRentVm.new,
   name: r'propertyRentVmProvider',
   debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
@@ -21,6 +21,6 @@ final propertyRentVmProvider =
   allTransitiveDependencies: null,
 );
 
-typedef _$PropertyRentVm = AutoDisposeNotifier<void>;
+typedef _$PropertyRentVm = AutoDisposeNotifier<PropertyRentState>;
 // 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

+ 106 - 2
packages/cpt_property/lib/modules/sale/page/property_sale_page.dart

@@ -1,7 +1,14 @@
+import 'package:cpt_property/modules/property/page/property_page.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/color_utils.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/widget_export.dart';
+import 'package:cs_resources/generated/assets.dart';
 
 import '../../../router/page/property_page_router.dart';
 import '../vm/property_sale_vm.dart';
@@ -19,14 +26,111 @@ class PropertySalePage extends HookConsumerWidget {
     }
   }
 
+  Widget _buildItemLeftSection(BuildContext context,WidgetRef ref, item, _vm) {
+    return Container(
+      // color: Colors.blue,
+        child:
+          Text(item['title'],
+          style: const TextStyle(fontSize: 16.0, color: Colors.black, fontWeight: FontWeight.w400), // 设置字体大小
+        ),
+    ).marginOnly(right: 17.5);
+  }
+
+  Widget _buildItemRightSection(BuildContext context,WidgetRef ref, item, _vm) {
+
+    return Container(
+      color: Colors.white,
+      child: TextButton(
+        onPressed: (){},
+        style: TextButton.styleFrom(
+          foregroundColor: Colors.black,
+          backgroundColor: ColorUtils.string2Color('#EFF3FF'), // 背景颜色
+          minimumSize: const Size(91.5, 44), // 最小宽度和高度
+          padding: const EdgeInsets.symmetric(horizontal: 11.0, vertical: 14), // 内边距
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(5), // 圆角
+            side: BorderSide(
+                color: ColorUtils.string2Color('#EFF3FF'),
+                width: 1.0,
+            ), // 边框
+          ),
+        ),
+        child: Text(item['price']),
+      ),
+    );
+  }
+
+  // listitem
+  Widget _buildSaleItem(BuildContext context,WidgetRef ref, item, _vm) {
+    return Container(
+      // color: Colors.red,
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.center,
+        crossAxisAlignment: CrossAxisAlignment.center,
+        mainAxisSize: MainAxisSize.max,
+        children: [
+          Container(
+            width: MediaQuery.of(context).size.width - 30,
+            height: 100,
+            margin: const EdgeInsets.only(left: 15,right: 15,top: 12.5),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.start,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                Expanded(child: _buildItemLeftSection(context, ref, item, _vm)),
+                Container(
+                  width: 100,
+                  child: _buildItemRightSection(context, ref, item, _vm),
+                  // child: TextButton(onPressed: (){}, child: Text("fdsfds")),
+                ),
+              ],
+            ),
+          ).constrained(
+            minHeight: 117.5,
+          ),
+        ],
+      ).onTap((){
+        // 去详情
+        _vm.goNewsDetail(item);
+      }),
+    ).border(color: ColorUtils.string2Color('C9C9C9FF'), bottom: 0.5);
+  }
+
+  // list
+  Widget _buildSaleList(BuildContext context, WidgetRef ref, _vm) {
+    List itemsList = _vm.state.list.toList();
+    return ListView.builder(
+      itemCount: itemsList.length,
+      itemBuilder: (context, index) {
+        return _buildSaleItem(context, ref, itemsList[index], _vm);
+      },
+    );
+  }
+
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final _vm = ref.read(propertySaleVmProvider.notifier);
 
     return Scaffold(
       // appBar: AppBar(title: Text("资产")),
-      body: Center(
-        child: Text("房屋sale的主页面"),
+      body: Container(
+          child: EasyRefresh(
+            // 上拉加载
+            onLoad: () async{
+              Log.d("----onLoad");
+              _vm.onLoadData();
+            },
+            // 下拉刷新
+            onRefresh: () async{
+              Log.d("----onRefresh");
+              _vm.refreshListData();
+            },
+            child: Container(
+                color: Colors.white,
+                margin: const EdgeInsets.only(top: 5),
+                child: _buildSaleList(context, ref, _vm)
+            ),
+          )
       ),
     );
   }

+ 49 - 0
packages/cpt_property/lib/modules/sale/page/property_sale_state.dart

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

+ 70 - 0
packages/cpt_property/lib/modules/sale/repository/property_sale_repository.dart

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

+ 29 - 0
packages/cpt_property/lib/modules/sale/repository/property_sale_repository.g.dart

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

+ 90 - 3
packages/cpt_property/lib/modules/sale/vm/property_sale_vm.dart

@@ -1,13 +1,100 @@
-
+import 'package:plugin_platform/http/http_result.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
-
+import 'package:shared/utils/log_utils.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import '../page/property_sale_state.dart';
+import '../repository/property_sale_repository.dart';
 part 'property_sale_vm.g.dart';
 
 @riverpod
 class PropertySaleVm extends _$PropertySaleVm {
+  late PropertySaleRepository propertySaleRepository;
+  PropertySaleState initState() {
+    return PropertySaleState(
+      curPage: 1,
+      pageSize: 10,
+      list: [
+        {
+          "id": 1,
+          "title": "18 Sep 2024 BIK 39#09-XX 1337 psd 1001 sqft",
+          "price": "\$1.338 M",
+        },
+        {
+          "id": 2,
+          "title": "18 Sep 2024 BIK 39#09-XX 1337 psd 1001 sqft",
+          "price": "\$1.338 M",
+        },
+      ],
+      filterCount: 2,
+    );
+  }
 
   @override
-  void build(){
+  PropertySaleState build() {
+    // 引入数据仓库
+    propertySaleRepository = ref.read(propertySaleRepositoryProvider);
+    // 初始化状态
+    PropertySaleState state = initState();
+    // 初始化列表数据
+    return state;
+  }
+
+  // 初始化页面数据
+  initPageData() {
+    Log.d("----property_news_vm-----initPageData");
+    refreshListData();
+  }
+
+  // 上拉加载
+  Future onLoadData() async {
+    Log.d("----property_news_vm-----initListData");
+    // await Future.delayed(const Duration(seconds: 2));
+    // if(state.list.length >= state.filterCount){
+    //   return;
+    // }else {
+    //   int curPage = state.curPage + 1;
+    //   state = state.copyWith(curPage: curPage,);
+    //   getListData();
+    // }
+    getListData();
+  }
+
+  // 获取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 propertySaleRepository.fetchPropertyNewsList(params);
+      Log.d("请求完成结果------${result.data}");
+      //校验成功失败
+      if (result.isSuccess) {
+        // state = state.copyWith(serverTime: result.data);
+        state = state;
+        ToastEngine.show("获取数据成功");
+      } else {
+        ToastEngine.show(result.errorMsg ?? "Network Load Error");
+      }
+    } catch (e) {
+      ToastEngine.show("Error: $e");
+    }
+  }
+
+
+  // 下拉刷新
+  Future refreshListData() async {
+    Log.d("----property_news_vm-----refreshListData ");
+
+    // await Future.delayed(const Duration(seconds: 2));
+
+    state = state.copyWith(curPage: 1, pageSize: 10);
+    // ref.invalidateSelf();
+    // ref.invalidate(propertyNewsVmProvider);
+    getListData();
 
   }
 

+ 3 - 3
packages/cpt_property/lib/modules/sale/vm/property_sale_vm.g.dart

@@ -6,12 +6,12 @@ part of 'property_sale_vm.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$propertySaleVmHash() => r'0f03c435057215656f637aef71c2458299f34fa3';
+String _$propertySaleVmHash() => r'f24b1a7b9cbe075d7ed60302ab0c1d170359729b';
 
 /// See also [PropertySaleVm].
 @ProviderFor(PropertySaleVm)
 final propertySaleVmProvider =
-    AutoDisposeNotifierProvider<PropertySaleVm, void>.internal(
+    AutoDisposeNotifierProvider<PropertySaleVm, PropertySaleState>.internal(
   PropertySaleVm.new,
   name: r'propertySaleVmProvider',
   debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
@@ -21,6 +21,6 @@ final propertySaleVmProvider =
   allTransitiveDependencies: null,
 );
 
-typedef _$PropertySaleVm = AutoDisposeNotifier<void>;
+typedef _$PropertySaleVm = AutoDisposeNotifier<PropertySaleState>;
 // ignore_for_file: type=lint
 // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 2 - 1
packages/cpt_property/lib/router/page/property_page_router.dart

@@ -49,9 +49,10 @@ class PropertyPageRouter extends _$PropertyPageRouter {
     ),
     // 新闻详情页面
     CustomRoute(
-      page: PropertyPageRoute.page,
+      page: PropertyNewsDetailPageRoute.page,
       path: RouterPath.propertyNewsDetail,
       transitionsBuilder: applySlideTransition,
+      children: const []
     ),
   ];
 }

+ 7 - 7
packages/cpt_property/lib/router/page/property_page_router.gr.dart

@@ -21,10 +21,10 @@ abstract class _$PropertyPageRouter extends RootStackRouter {
         child: const PropertyIoanPage(),
       );
     },
-    PropertyNewsDetailPageRouteRoute.name: (routeData) {
+    PropertyNewsDetailPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
-        child: const PropertyNewsDetailPageRoute(),
+        child: const PropertyNewsDetailPage(),
       );
     },
     PropertyNewsPageRoute.name: (routeData) {
@@ -69,15 +69,15 @@ class PropertyIoanPageRoute extends PageRouteInfo<void> {
 }
 
 /// generated route for
-/// [PropertyNewsDetailPageRoute]
-class PropertyNewsDetailPageRouteRoute extends PageRouteInfo<void> {
-  const PropertyNewsDetailPageRouteRoute({List<PageRouteInfo>? children})
+/// [PropertyNewsDetailPage]
+class PropertyNewsDetailPageRoute extends PageRouteInfo<void> {
+  const PropertyNewsDetailPageRoute({List<PageRouteInfo>? children})
       : super(
-          PropertyNewsDetailPageRouteRoute.name,
+          PropertyNewsDetailPageRoute.name,
           initialChildren: children,
         );
 
-  static const String name = 'PropertyNewsDetailPageRouteRoute';
+  static const String name = 'PropertyNewsDetailPageRoute';
 
   static const PageInfo<void> page = PageInfo<void>(name);
 }

+ 26 - 0
packages/cs_shared/lib/utils/color_utils.dart

@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+class ColorUtils {
+  // 颜色值转换
+  static Color string2Color(String colorString) {
+    int? value = 0x00000000;
+    if (colorString.isNotEmpty) {
+      if (colorString[0] == '#') {
+        colorString = colorString.substring(1);
+      }
+      value = int.tryParse(colorString, radix: 16);
+      if (value != null) {
+        if (value < 0xFF000000) {
+          value += 0xFF000000;
+        }
+      }
+    }
+    return Color(value!);
+  }
+
+  static Color hexToColor(String hex) {
+    assert(RegExp(r'^#([0-9a-fA-F]{6})|([0-9a-fA-F]{8})$').hasMatch(hex), 'hex color must be #rrggbb or #rrggbbaa');
+    return Color(
+      int.parse(hex.substring(1), radix: 16) + (hex.length == 7 ? 0xff000000 : 0x00000000),
+    );
+  }
+}

+ 35 - 0
packages/cs_shared/lib/utils/util.dart

@@ -136,4 +136,39 @@ class Utils {
     return greeting;
   }
 
+  /// 将时间转化为 多久之前
+  static String getTimeAgo(String? dateTimeStr) {
+    if (dateTimeStr == null || dateTimeStr.isEmpty) {
+      return 'Unknown time'; // 或者返回其他默认值
+    }
+
+    DateTime? dateTime;
+    try {
+      dateTime = DateTime.parse(dateTimeStr);
+    } catch (e) {
+      return 'Invalid date format'; // 或者返回其他默认值
+    }
+
+    if (dateTime == null) {
+      return 'Unknown time'; // 或者返回其他默认值
+    }
+
+    final now = DateTime.now();
+    final difference = now.difference(dateTime);
+
+    if (difference.inHours < 1) {
+      return "${difference.inMinutes} minutes ago";
+    } else if (difference.inHours < 24) {
+      return "${difference.inHours} hours ago";
+    } else if (difference.inDays < 7) {
+      return "${difference.inDays} days ago";
+    } else if (difference.inDays < 30) {
+      return "${(difference.inDays / 7).floor()} weeks ago";
+    } else if (difference.inDays < 365) {
+      return "${(difference.inDays / 30).floor()} months ago";
+    } else {
+      return "${(difference.inDays / 365).floor()} years ago";
+    }
+  }
+
 }