From 0b17b3e1a37f27ae85ec17fc30bd7b97fc1820c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AD=90=E8=B4=A4?= Date: Fri, 9 Jan 2026 14:19:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E9=87=91=E7=89=8C=E7=BA=A2?= =?UTF-8?q?=E5=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/controller/home/home_controller.dart | 40 ++++++++ lib/model/home/matchmaker_data.dart | 84 +++++++++++++++++ lib/network/api_urls.dart | 3 + lib/network/home_api.dart | 7 ++ lib/network/home_api.g.dart | 38 ++++++++ lib/pages/discover/visitor_list_page.dart | 2 +- lib/pages/home/matchmaker_card.dart | 109 ++++++++++++++++++++++ lib/pages/home/matchmaker_item.dart | 11 ++- lib/pages/home/matchmaker_page.dart | 71 ++++++++++++-- lib/pages/home/nearby_tab.dart | 2 +- lib/pages/home/recommend_tab.dart | 2 +- 11 files changed, 355 insertions(+), 14 deletions(-) create mode 100644 lib/model/home/matchmaker_data.dart create mode 100644 lib/pages/home/matchmaker_card.dart diff --git a/lib/controller/home/home_controller.dart b/lib/controller/home/home_controller.dart index 060a524..1f62d8c 100644 --- a/lib/controller/home/home_controller.dart +++ b/lib/controller/home/home_controller.dart @@ -1,4 +1,6 @@ import 'package:dating_touchme_app/model/home/banner_data.dart'; +import 'package:dating_touchme_app/model/home/matchmaker_data.dart' as md; +import 'package:easy_refresh/easy_refresh.dart'; import 'package:get/get.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import '../../network/home_api.dart'; @@ -9,6 +11,8 @@ class HomeController extends GetxController { final recommendFeed = [].obs; // 推荐列表数据 final bannerLint = [].obs; + + final matchmakerList = [].obs; // 同城列表数据 final nearbyFeed = [].obs; @@ -35,14 +39,22 @@ class HomeController extends GetxController { // 从GetX依赖注入中获取HomeApi实例 late final HomeApi _homeApi; + late final EasyRefreshController listRefreshController; + @override void onInit() { super.onInit(); + + listRefreshController = EasyRefreshController( + controlFinishRefresh: true, + controlFinishLoad: true, + ); // 从全局依赖中获取HomeApi _homeApi = Get.find(); // 初始化时加载数据 loadInitialData(); getBannerList(); + getMatchmakerList(); } @@ -66,6 +78,34 @@ class HomeController extends GetxController { } } + getMatchmakerList() async { + try{ + final response = await _homeApi.userPageDongwoMatchmakerMarriageInformation( + pageNum: 1, + pageSize: 10 + ); + if (response.data.isSuccess && response.data.data != null) { + final data = response.data.data?.records ?? []; + + matchmakerList.addAll(data.toList()); + if((data.length ?? 0) == 10){ + + listRefreshController.finishLoad(IndicatorResult.success); + } else { + listRefreshController.finishLoad(IndicatorResult.noMore); + } + } else { + + // 响应失败,抛出异常 + throw Exception(response.data.message ?? '获取数据失败'); + } + } catch(e) { + print('玫瑰记录获取失败: $e'); + SmartDialog.showToast('玫瑰记录获取失败'); + rethrow; + } + } + /// 加载初始数据(同时加载两个标签页的数据) void loadInitialData() async { // 并行加载两个标签页的数据 diff --git a/lib/model/home/matchmaker_data.dart b/lib/model/home/matchmaker_data.dart new file mode 100644 index 0000000..2a3bd21 --- /dev/null +++ b/lib/model/home/matchmaker_data.dart @@ -0,0 +1,84 @@ +class MatchmakerData { + List? records; + int? total; + int? size; + int? current; + int? pages; + + MatchmakerData( + {this.records, this.total, this.size, this.current, this.pages}); + + MatchmakerData.fromJson(Map json) { + if (json['records'] != null) { + records = []; + json['records'].forEach((v) { + records!.add(new Records.fromJson(v)); + }); + } + total = json['total']; + size = json['size']; + current = json['current']; + pages = json['pages']; + } + + Map toJson() { + final Map data = new Map(); + if (this.records != null) { + data['records'] = this.records!.map((v) => v.toJson()).toList(); + } + data['total'] = this.total; + data['size'] = this.size; + data['current'] = this.current; + data['pages'] = this.pages; + return data; + } +} + +class Records { + String? miId; + String? userId; + String? matchmakerId; + String? profilePhoto; + String? nickName; + bool? isRealNameCertified; + String? birthYear; + String? birthDate; + int? age; + + Records( + {this.miId, + this.userId, + this.matchmakerId, + this.profilePhoto, + this.nickName, + this.isRealNameCertified, + this.birthYear, + this.birthDate, + this.age}); + + Records.fromJson(Map json) { + miId = json['miId']; + userId = json['userId']; + matchmakerId = json['matchmakerId']; + profilePhoto = json['profilePhoto']; + nickName = json['nickName']; + isRealNameCertified = json['isRealNameCertified']; + birthYear = json['birthYear']; + birthDate = json['birthDate']; + age = json['age']; + } + + Map toJson() { + final Map data = new Map(); + data['miId'] = this.miId; + data['userId'] = this.userId; + data['matchmakerId'] = this.matchmakerId; + data['profilePhoto'] = this.profilePhoto; + data['nickName'] = this.nickName; + data['isRealNameCertified'] = this.isRealNameCertified; + data['birthYear'] = this.birthYear; + data['birthDate'] = this.birthDate; + data['age'] = this.age; + return data; + } +} diff --git a/lib/network/api_urls.dart b/lib/network/api_urls.dart index 72dd05b..d04da87 100644 --- a/lib/network/api_urls.dart +++ b/lib/network/api_urls.dart @@ -149,6 +149,9 @@ class ApiUrls { static const String userPageBannerByCustomer = 'dating-agency-service/user/page/banner/by/customer'; + static const String userPageDongwoMatchmakerMarriageInformation = + 'dating-agency-service/user/page/dongwo/matchmaker-marriage-information'; + // 后续可以在此添加更多API端点 static const String listMatchmakerProduct = 'dating-agency-mall/user/page/product/by/matchmaker'; diff --git a/lib/network/home_api.dart b/lib/network/home_api.dart index 0e1a11b..78e306b 100644 --- a/lib/network/home_api.dart +++ b/lib/network/home_api.dart @@ -1,6 +1,7 @@ import 'package:dating_touchme_app/model/home/banner_data.dart' hide Records; import 'package:dating_touchme_app/model/home/event_data.dart'; import 'package:dating_touchme_app/model/home/event_list_data.dart' hide Records; +import 'package:dating_touchme_app/model/home/matchmaker_data.dart' hide Records; import 'package:dating_touchme_app/model/home/post_comment_data.dart' hide Records; import 'package:dating_touchme_app/model/home/post_data.dart'; import 'package:dating_touchme_app/model/home/trend_data.dart' hide Records; @@ -96,4 +97,10 @@ abstract class HomeApi { @GET(ApiUrls.userPageBannerByCustomer) Future>> userPageBannerByCustomer(); + + @GET(ApiUrls.userPageDongwoMatchmakerMarriageInformation) + Future>> userPageDongwoMatchmakerMarriageInformation({ + @Query('pageNum') required int pageNum, + @Query('pageSize') required int pageSize, + }); } \ No newline at end of file diff --git a/lib/network/home_api.g.dart b/lib/network/home_api.g.dart index 57dc8cd..f6b02af 100644 --- a/lib/network/home_api.g.dart +++ b/lib/network/home_api.g.dart @@ -522,6 +522,44 @@ class _HomeApi implements HomeApi { return httpResponse; } + @override + Future>> + userPageDongwoMatchmakerMarriageInformation({ + required int pageNum, + required int pageSize, + }) async { + final _extra = {}; + final queryParameters = { + r'pageNum': pageNum, + r'pageSize': pageSize, + }; + final _headers = {}; + const Map? _data = null; + final _options = _setStreamType>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-service/user/page/dongwo/matchmaker-marriage-information', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); + final _result = await _dio.fetch>(_options); + late BaseResponse _value; + try { + _value = BaseResponse.fromJson( + _result.data!, + (json) => MatchmakerData.fromJson(json as Map), + ); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + final httpResponse = HttpResponse(_value, _result); + return httpResponse; + } + RequestOptions _setStreamType(RequestOptions requestOptions) { if (T != dynamic && !(requestOptions.responseType == ResponseType.bytes || diff --git a/lib/pages/discover/visitor_list_page.dart b/lib/pages/discover/visitor_list_page.dart index 8964f6e..df7cee2 100644 --- a/lib/pages/discover/visitor_list_page.dart +++ b/lib/pages/discover/visitor_list_page.dart @@ -196,7 +196,7 @@ class VisitorItem extends StatelessWidget { ) ], ).onTap((){ - Get.to(() => UserInformationPage(miId: visitor.miId, userId: GlobalData().userId!)); + Get.to(() => UserInformationPage(miId: visitor.miId, userId: visitor.userId)); }); } diff --git a/lib/pages/home/matchmaker_card.dart b/lib/pages/home/matchmaker_card.dart new file mode 100644 index 0000000..f5d4728 --- /dev/null +++ b/lib/pages/home/matchmaker_card.dart @@ -0,0 +1,109 @@ + + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:dating_touchme_app/controller/global.dart'; +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/model/home/matchmaker_data.dart'; +import 'package:dating_touchme_app/pages/home/user_information_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +class MatchmakerCard extends StatelessWidget { + final Records visitor; + + const MatchmakerCard({Key? key, required this.visitor}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(10.w)), + child: CachedNetworkImage( + imageUrl: "${visitor.profilePhoto}?x-oss-process=image/format,webp/resize,w_240", + width: 173.w, + height: 173.w, + fit: BoxFit.cover, + placeholder: (context, url) => Container( + color: Colors.white38, + child: Center( + child: CircularProgressIndicator( + strokeWidth: 1.w, + color: Colors.grey, + ), + ), + ), + errorWidget: (context, url, error) => + Image.asset( + Assets.imagesUserAvatar, + width: 173.w, + height: 173.w, + fit: BoxFit.cover, + ), + ), + ), + Positioned( + left: 8.w, + bottom: 12.w, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if(visitor.nickName != "")SizedBox( + width: 156.w, + child: Text(visitor.nickName ?? "", + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ), + SizedBox(height: 2.w), + SizedBox( + width: 156.w, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "${visitor.age}岁", + style: TextStyle( + fontSize: 14.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ) + ], + ), + ) + ], + ).onTap((){ + Get.to(() => UserInformationPage(miId: visitor.miId ?? "", userId: visitor.userId!)); + }); + } + +// String _formatTime(String timestamp) { +// var time = DateTime.parse(timestamp); +// final now = DateTime.now(); +// final difference = now.difference(time); +// +// if (difference.inMinutes < 1) { +// return '刚刚'; +// } else if (difference.inHours < 1) { +// return '${difference.inMinutes}分钟前'; +// } else if (difference.inDays < 1) { +// return '${difference.inHours}小时前'; +// } else if (difference.inDays < 7) { +// return '${difference.inDays}天前'; +// } else { +// return '${time.month}/${time.day}'; +// } +// } + +} \ No newline at end of file diff --git a/lib/pages/home/matchmaker_item.dart b/lib/pages/home/matchmaker_item.dart index 31e53af..4f23d35 100644 --- a/lib/pages/home/matchmaker_item.dart +++ b/lib/pages/home/matchmaker_item.dart @@ -2,13 +2,14 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:dating_touchme_app/model/home/marriage_data.dart'; +import 'package:dating_touchme_app/model/home/matchmaker_data.dart'; import 'package:dating_touchme_app/pages/home/user_information_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; class MatchmakerItem extends StatefulWidget { - final MarriageData item; + final Records item; const MatchmakerItem({super.key, required this.item}); @override @@ -24,7 +25,7 @@ class _MatchmakerItemState extends State { ClipRRect( borderRadius: BorderRadius.all(Radius.circular(40.w)), child: widget.item.profilePhoto != "" ? CachedNetworkImage( - imageUrl: widget.item.profilePhoto, + imageUrl: widget.item.profilePhoto ?? "", width: 40.w, height: 40.w, fit: BoxFit.cover, @@ -35,7 +36,7 @@ class _MatchmakerItemState extends State { fit: BoxFit.cover, ), ), - Positioned( + if(false) Positioned( left: -3.w, bottom: -3.w, child: Container( @@ -48,7 +49,7 @@ class _MatchmakerItemState extends State { ), child: Center( child: Text( - widget.item.nickName, + widget.item.nickName ?? "", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( @@ -62,7 +63,7 @@ class _MatchmakerItemState extends State { ) ], ).onTap((){ - Get.to(() => UserInformationPage(miId: widget.item.miId, userId: widget.item.userId,)); + Get.to(() => UserInformationPage(miId: widget.item.miId ?? "", userId: widget.item.userId ?? "",)); }); } } diff --git a/lib/pages/home/matchmaker_page.dart b/lib/pages/home/matchmaker_page.dart index a488c80..b1624f9 100644 --- a/lib/pages/home/matchmaker_page.dart +++ b/lib/pages/home/matchmaker_page.dart @@ -1,7 +1,10 @@ import 'package:dating_touchme_app/components/page_appbar.dart'; import 'package:dating_touchme_app/controller/home/home_controller.dart'; +import 'package:dating_touchme_app/pages/home/matchmaker_card.dart'; import 'package:dating_touchme_app/pages/home/nearby_tab.dart'; +import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; class MatchmakerPage extends StatefulWidget { @@ -21,12 +24,68 @@ class _MatchmakerPageState extends State with AutomaticKeepAlive super.build(context); return Scaffold( appBar: PageAppbar(title: "金牌红娘"), - body: Column( - children: [ - Expanded( - child: NearbyTab(), - ) - ], + body: EasyRefresh( + controller: controller.listRefreshController, + header: const ClassicHeader( + dragText: '下拉刷新', + armedText: '释放刷新', + readyText: '刷新中...', + processingText: '刷新中...', + processedText: '刷新完成', + failedText: '刷新失败', + noMoreText: '没有更多数据', + showMessage: false + ), + footer: ClassicFooter( + dragText: '上拉加载', + armedText: '释放加载', + readyText: '加载中...', + processingText: '加载中...', + processedText: '加载完成', + failedText: '加载失败', + noMoreText: '没有更多数据', + showMessage: false + ), + // 下拉刷新 + onRefresh: () async { + print('推荐列表下拉刷新被触发'); + + controller.matchmakerList.clear(); + await controller.getMatchmakerList(); + controller.listRefreshController.finishRefresh(IndicatorResult.success); + controller.listRefreshController.finishLoad(IndicatorResult.none); + }, + // 上拉加载更多 + onLoad: () async { + print('推荐列表上拉加载被触发, hasMore: '); + + await controller.getMatchmakerList(); + }, + child: Container( + padding: EdgeInsets.symmetric( + vertical: 6.w, + horizontal: 15.w + ), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top, + ), + child: GridView.builder( + padding: EdgeInsets.only(top: 8.w, left: 10.w, right: 8.w, bottom: 0.w), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, // 每行2个 + crossAxisSpacing: 4.w, // 左右间距 + mainAxisSpacing: 4.w, // 上下间距 + childAspectRatio: 1, // 宽高比 + ), + itemCount: controller.matchmakerList.length, + itemBuilder: (context, index) { + final visitor = controller.matchmakerList[index]; + return MatchmakerCard(visitor: visitor); + }, + ), + ), + ), ), ); } diff --git a/lib/pages/home/nearby_tab.dart b/lib/pages/home/nearby_tab.dart index d82b14b..5ed44d3 100644 --- a/lib/pages/home/nearby_tab.dart +++ b/lib/pages/home/nearby_tab.dart @@ -38,7 +38,7 @@ class _NearbyTabState extends State with AutomaticKeepAliveClientMixi return Obx(() { return EasyRefresh( - controller: _refreshController, + controller: controller.listRefreshController, header: const ClassicHeader( dragText: '下拉刷新', armedText: '释放刷新', diff --git a/lib/pages/home/recommend_tab.dart b/lib/pages/home/recommend_tab.dart index 41bbeff..3456a75 100644 --- a/lib/pages/home/recommend_tab.dart +++ b/lib/pages/home/recommend_tab.dart @@ -244,7 +244,7 @@ class _RecommendTabState extends State spacing: 14.w, runSpacing: 8.w, children: [ - ...controller.nearbyFeed.take(6).toList().map((e){ + ...controller.matchmakerList.take(6).toList().map((e){ return MatchmakerItem(item: e); }) ],