import 'package:cs_resources/generated/assets.dart'; import 'package:cs_resources/theme/app_colors_theme.dart'; import 'package:domain/entity/garage_sale_rent_entity.dart'; import 'package:domain/entity/newsfeed_detail_entity.dart'; import 'package:domain/entity/paid_service_entity.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:plugin_basic/constants/app_constant.dart'; import 'package:plugin_platform/engine/dialog/dialog_engine.dart'; import 'package:plugin_platform/engine/sp/sp_util.dart'; import 'package:plugin_platform/engine/toast/toast_engine.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:router/ext/auto_router_extensions.dart'; import 'package:shared/utils/log_utils.dart'; import 'package:widgets/dialog/app_custom_dialog.dart'; import 'package:widgets/load_state_layout.dart'; import 'package:widgets/my_checkbox_group.dart'; import 'package:widgets/picker/option_pick_util.dart'; import 'package:widgets/widget_export.dart'; import '../../../constants_services.dart'; import '../../../respository/services_respository.dart'; import '../../../router/page/services_page_router.dart'; import '../services_vm.dart'; import 'home_service_state.dart'; part 'home_service_vm.g.dart'; @riverpod class HomeServiceVm extends _$HomeServiceVm { late ServicesRespository servicesRespositoryInstance; bool _needShowPlaceholder = false; //是否展示LoadingView int _page = 1; // 当前页 int _limit = 10; // 每页数量 int _count = 0; // 总条数 bool _isSingleSelect = true; List> _currentSelectedCategory = []; Map _queryParams = { 'category_id': null, 'keyword': null, 'is_liked': null, }; // Refresh 控制器 final EasyRefreshController refreshController = EasyRefreshController( controlFinishRefresh: true, //允许刷新 controlFinishLoad: true, //允许加载 ); HomeServiceState initState() { return HomeServiceState( list: [] ); } @override HomeServiceState build(){ // 引入数据仓库 servicesRespositoryInstance = ref.read(servicesRespositoryProvider); final state = initState(); Log.d("--------------------------build---------------------"); return state; } //刷新页面状态 void changeLoadingState(LoadState loadState, String? errorMsg) { state = state.copyWith( loadingState: loadState, errorMessage: errorMsg ); } // 初始化页面数据 initPageData() { Log.d("----home_service_vm-----initPageData ${state.loadingState}"); onRefresh(); } // 上拉加载 更多 Future loadMore() async { Log.d("----home_service_vm-----loadMore"); _page++; getListData(); } // 下拉刷新 Future onRefresh() async { // 当前pageView 页面正处于显示状态 Log.d("----forsale_vm-----onRefresh "); // await Future.delayed(const Duration(seconds: 2)); _page = 1; getListData(); } // 手动进行刷新 Future triggerRefresh() async { Log.d("trggerRefresh"); refreshController.callRefresh(); } // 手动进行刷新 Future directRefresh() async { state = state.copyWith(list:[]); // 注意:由于 nestedscrollview 嵌套easyfresh 组件 refreshController.callRefresh() 自动刷新只能滚动顶部但是不会触发下拉刷新,这里调用是 用到了将其滚动到顶部的作用,进而刷新操作主动掉接口 // https://github.com/xuelongqy/flutter_easy_refresh/issues/692 refreshController.callRefresh(); refreshController.resetFooter(); _page = 1; _needShowPlaceholder = true; getListData(); } // 重试请求 Future retryRequest() async { _page = 1; _needShowPlaceholder = true; getListData(); } // 获取list 列表数据 Future getListData({bool? isLoadMore}) async { if (_needShowPlaceholder) { changeLoadingState(LoadState.State_Loading, null); } // List> list = [ // { // 'id':1, // 'service_type': 0, // 0 房屋保洁 1 空调保洁 2 维修 // 'cover_img': 'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500', // 'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'], // 'title': 'House Cleaning Services', // 'price': 30, // 'unit': '/hr', // 'liked': true, // 'likes_count': 12, // 'company_name': 'HONG YE GROUP PTE LTD', // }, // { // 'id':2, // 'service_type': 1, // 0 房屋保洁 1 空调保洁 2 维修 // 'cover_img': 'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500', // 'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'], // 'title': 'Air Conditioning Cleaning', // 'price': 10, // 'unit': '/unit', // 'liked': false, // 'likes_count': 10, // 'company_name': 'HONG YE GROUP PTE LTD', // }, // { // 'id':3, // 'service_type': 1, // 0 房屋保洁 1 空调保洁 2 维修 // 'cover_img': 'https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500', // 'resources': ['https://img2.baidu.com/it/u=3489233687,2364672159&fm=253&fmt=auto&app=120&f=JPEG?w=507&h=500'], // 'title': 'Cleaning Services', // 'price': 200, // 'unit': '/hr', // 'liked': true, // 'likes_count': 1212, // 'company_name': 'HONG YE GROUP PTE LTD', // }, // ]; // handlerResultData(true, list:list); try { //请求网络 Map params = { "sort": null, // 排序(desc=降序,asc=升序) "sort_by": null, // 排序(likes_count=点赞量,orders_count=下单量,clicks_count=点击量) "category_id": _queryParams['category_id'], "keyword": _queryParams['keyword'], "page": _page, "limit": _limit, }; Log.d("请求参数------$params"); final result = await servicesRespositoryInstance.fetchPaidServiceDataList(params); //校验成功失败 if (result.isSuccess) { handlerResultList((result.data as PaidServiceEntity)?.list as List?, isLoadMore ?? false); } else { String errorMessage = result.errorMsg!; changeLoadingState(LoadState.State_Error, errorMessage); ToastEngine.show(result.errorMsg ?? "Network Load Error"); } } catch (e) { ToastEngine.show("Error: $e"); } // 最后赋值 _needShowPlaceholder = false; } handlerResultData(bool isList, {List? list, dynamic? data}){ Future.delayed(const Duration(seconds: 1)).then((value) { if(isList){ // list 数据模式 if(list != null && list.isNotEmpty){ if(_page == 1){ state.list.clear(); state.list!.addAll(list); refreshController.finishRefresh(); changeLoadingState(LoadState.State_Success, null); }else { final allList = state.list; allList!.addAll(list); state = state.copyWith(list: allList); refreshController.finishLoad(); } }else { if(_page == 1){ state.list.clear(); changeLoadingState(LoadState.State_Empty, null); refreshController.finishRefresh(); }else { refreshController.finishLoad(IndicatorResult.noMore); } } }else { // 单个数据模式 if(data!=null){ if(_page == 1){ refreshController.finishRefresh(); }else{ refreshController.finishLoad(); } changeLoadingState(LoadState.State_Success, null); }else { if(_page == 1){ refreshController.finishRefresh(); }else{ refreshController.finishLoad(); } changeLoadingState(LoadState.State_Empty, null); } } }); } void handlerResultList(List? list, bool isLoadMore) { if (list != null && list.isNotEmpty) { //有数据,判断是刷新还是加载更多的数据 if (_page == 1) { //刷新的方式 state.list!.clear(); state.list!.addAll(list); refreshController.finishRefresh(); //更新展示的状态 changeLoadingState(LoadState.State_Success, null); } else { //加载更多 final allList = state.list; allList!.addAll(list); state = state.copyWith(list: allList); refreshController.finishLoad(); } } else { if (_page == 1) { //展示无数据的布局 state.list!.clear(); changeLoadingState(LoadState.State_Empty, null); refreshController.finishRefresh(); } else { //展示加载完成,没有更多数据了 if (_page == 1) { //展示无数据的布局 state.list!.clear(); changeLoadingState(LoadState.State_Empty, null); refreshController.finishRefresh(); } else { //展示加载完成,没有更多数据了 if(state.list!.length == 0){ changeLoadingState(LoadState.State_Empty, null); refreshController.finishLoad(); }else { if(_needShowPlaceholder){ changeLoadingState(LoadState.State_Success, null); } } //更新展示的状态 refreshController.finishLoad(IndicatorResult.noMore); } } } } // 获取 homeservice 的分类选项 Future>> getHomeServiceCategoryOptions() async{ // await Future.delayed(const Duration(milliseconds: 300)); // ToastEngine.dismiss(); List> serviceCategoryList = [ // { // 'id': 1, // 'name': 'House Cleaning Serivces', // }, // { // 'id': 2, // 'name': 'Household Appliance Cleaning', // }, ]; // 获取分类列表 try { // 加入有缓存 就取缓存 List>? StorageCategoryList = SPUtil.getObjectList( AppConstant.storagePaidServiceCategoryList)?.cast>(); if (StorageCategoryList != null && StorageCategoryList.isNotEmpty) { Log.d("取StorageCategoryList 缓存: $StorageCategoryList "); serviceCategoryList = StorageCategoryList; } else { final paidServiceLayoutVm = ref.watch(servicesVmProvider.notifier); Map params = { 'parent_id': paidServiceLayoutVm?.state.parentCategoryId, }; final result = await servicesRespositoryInstance.fetchServiceCateGoryList(params); if (result.isSuccess) { final listJson = result.getListJson(); // 将 listJson 转换为 List> serviceCategoryList = (listJson as List?) ?.map((item) => item as Map) .toList() ?? []; // 将 serviceCategoryList 存入缓存 Log.d("设置StorageCategoryList 缓存"); SPUtil.putObjectList( AppConstant.storagePaidServiceCategoryList, serviceCategoryList); } } } catch(error){ Log.d("获取分类列表失败: $error"); } return serviceCategoryList; } // 点击了filter icon handlerClickFilterIcon(BuildContext context) async{ List> serviceCategoryList = await getHomeServiceCategoryOptions(); // 显示弹框 handlerShowChooseServiceCategoryDialog(context, serviceCategoryList); } Future handlerShowChooseServiceCategoryDialog(BuildContext context, List> categoryList) async{ await DialogEngine.show( tag: "chooseServiceCategory", position: DialogPosition.center, widget: AppCustomDialog( message: '', title: 'Choose a Category', dialogWidth: MediaQuery.of(context).size.width * 0.8, // contentBoxMaxHeight: 350, // contentBoxMinHeight: 300, isShowConfirmBtn: categoryList!.length > 0 ? true: false, confirmTxt: "Ok", messageBuilder: (BuildContext context){ return Container( color: context.appColors.textWhite, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: categoryList!.length > 0 ? [ MyCheckboxGroup( isSingleSelect: _isSingleSelect, labelStyle: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500, ), items: categoryList!, defaultSelectedItems: [], onChanged: (List> selectedItems){ Log.d("----MyCheckboxGroup onChanged $selectedItems"); _currentSelectedCategory = selectedItems; } ) ]: [ Container( child: CircularProgressIndicator( strokeWidth: 3, valueColor: AlwaysStoppedAnimation(context.appColors.textDarkGray), ), ) ], ), ); }, isShowCancelBtn:false, confirmAction: (){ // 点击了确定 Log.d("----点击了确定按钮"); int? categoryId; if(_isSingleSelect){ if(_currentSelectedCategory.length > 0){ categoryId = _currentSelectedCategory[0]['id']; } } setCurrentQueryParams({ "category_id": _queryParams?['categoryId'], }); directRefresh(); }, ) ); } // 点击 收藏/取消收藏 Future handlerClickCollection(int id, bool? isCollection) async{ try { //请求网络 Map params = { "id": id, "type": 'paid', // 类型(paid=付费服务,inquiry=询价服务) }; Log.d("请求参数------$params"); final result = await servicesRespositoryInstance.fetchServiceLiked(params); //校验成功失败 if (result.isSuccess) { // 修改 该id 的 liked 和 likes_count 字段 state.list!.forEach((PaidServiceList elementEntity) { if(elementEntity.id == id){ elementEntity.liked = !elementEntity.liked!; elementEntity.likesCount = elementEntity.liked! ? (elementEntity.likesCount! + 1) : (elementEntity.likesCount! - 1); } }); return true; } else { String errorMessage = result.errorMsg!; changeLoadingState(LoadState.State_Error, errorMessage); ToastEngine.show(result.errorMsg ?? "Network Load Error"); } } catch (e) { Log.e("Error: $e"); ToastEngine.show("Error: $e"); } } // 设置当前的 _queryParams setCurrentQueryParams(Map params){ _queryParams.addAll(params); } // 获取当前的 _queryParams Map getCurrentQueryParams(String? key){ if(key!=null && key!.isNotEmpty){ return _queryParams[key]; } return _queryParams; } // 点击 sort icon handlerClickSortIcon(BuildContext context) async{ // await SmartDialog.showAttach( // targetContext: context, // alignment: Alignment.bottomCenter, // highlightBuilder: (Offset targetOffset, Size targetSize) { // Log.d("666 ${targetOffset} ${targetSize}"); // return Positioned( // right: 0, // top: 0, // child: Container(height: targetOffset.dy + 50, width: targetSize.width, color: Colors.white), // ); // }, // builder: (_) => _listDialog(), // ); // DialogEngine.showAttach( // targetContext: context, // position: DialogPosition.top, // clickMaskDismiss:false, // usePenetrate: true, // widget: _listDialog() // ); OptionPickerUtil.showCupertinoOptionPicker( items: state.sortByOptionsList, initialSelectIndex: 0, onPickerChanged: (_, index) { state = state.copyWith(sortBySelectedOption: state.sortByOptionsList?[index]); // 调用list 接口 }, ); } Widget _listDialog() { return Container( width: 200, height: 200, color: Colors.white, child: Column( children: [ Text("排序方式"), Text("价格从低到高"), Text("价格从高到低"), Text("距离最近"), Text("距离最远"), ], ), ); } // 去详情页面 void handlerGotoDetail({ BuildContext? context, required int id, required PaidServiceListCategory paidServiceCategory, liked, likesCount, }){ final cleanServiceType = paidServiceCategory.name!; Log.d("去详情页面: $id $cleanServiceType"); if(cleanServiceType == servicesConstants.servicesType['houseCleaning']!['code'] || cleanServiceType == servicesConstants.servicesType['airConditioner']!['code']){ // clean service 跳转到 clean 详情页 appRouter.push(ServiceCleanDetailPageRoute(id: id, cleanServiceType: cleanServiceType,liked: liked,likesCount: likesCount)); }else { // other service 跳转到 other 详情页 ToastEngine.show("${cleanServiceType} 类型的详情暂未开放"); } } }