diff --git a/assets/images/no_more_timeline.png b/assets/images/no_more_timeline.png new file mode 100644 index 0000000..32e96f7 Binary files /dev/null and b/assets/images/no_more_timeline.png differ diff --git a/lib/controller/home/user_information_controller.dart b/lib/controller/home/user_information_controller.dart index e9e492e..5ac9a78 100644 --- a/lib/controller/home/user_information_controller.dart +++ b/lib/controller/home/user_information_controller.dart @@ -1,9 +1,12 @@ import 'package:dating_touchme_app/controller/global.dart'; import 'package:dating_touchme_app/model/home/user_info_data.dart'; import 'package:dating_touchme_app/network/user_api.dart'; +import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import '../../model/home/post_data.dart'; + class UserInformationController extends GetxController { final String miId; @@ -27,9 +30,24 @@ class UserInformationController extends GetxController { late UserApi _userApi; + + final page = 1.obs; + final size = 10.obs; + + final postList = [].obs; + + + late final EasyRefreshController listRefreshController; + + @override void onInit() { super.onInit(); + + listRefreshController = EasyRefreshController( + controlFinishRefresh: true, + controlFinishLoad: true, + ); myUserData.value = GlobalData().userData; // 验证参数 if (miId.isEmpty) { @@ -67,6 +85,37 @@ class UserInformationController extends GetxController { final myUserData = GlobalData().userData.obs; + + + getPostList() async { + try{ + final response = await _userApi.userPageAuthorPost( + pageNum: page.value, + pageSize: size.value, + authorUserId: userData.value.miUserId ?? "" + ); + if (response.data.isSuccess && response.data.data != null) { + final data = response.data.data?.records ?? []; + + postList.addAll(data.toList()); + if((data.length ?? 0) == size.value){ + + listRefreshController.finishLoad(IndicatorResult.success); + } else { + listRefreshController.finishLoad(IndicatorResult.noMore); + } + } else { + + // 响应失败,抛出异常 + throw Exception(response.data.message ?? '获取数据失败'); + } + } catch(e) { + print('活动列表获取失败: $e'); + SmartDialog.showToast('活动列表获取失败'); + rethrow; + } + } + getUserData() async { try { isLoading.value = true; @@ -76,6 +125,7 @@ class UserInformationController extends GetxController { if (response.data.isSuccess && response.data.data != null) { userData.value = response.data.data!; isLoading.value = false; + getPostList(); } else { // 响应失败,设置错误信息 final errorMsg = response.data.message ?? '获取数据失败'; diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 41676bd..5cc4e57 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -171,6 +171,7 @@ class Assets { static const String imagesMore = 'assets/images/more.png'; static const String imagesMoreIcon = 'assets/images/more_icon.png'; static const String imagesMyWalletBg = 'assets/images/my_wallet_bg.png'; + static const String imagesNoMoreTimeline = 'assets/images/no_more_timeline.png'; static const String imagesOnlineIcon = 'assets/images/online_icon.png'; static const String imagesOnlineMsgIcon = 'assets/images/online_msg_icon.png'; static const String imagesPhoneChecked = 'assets/images/phone_checked.png'; diff --git a/lib/network/user_api.dart b/lib/network/user_api.dart index 341ff7f..33cae6f 100644 --- a/lib/network/user_api.dart +++ b/lib/network/user_api.dart @@ -1,5 +1,6 @@ import 'package:dating_touchme_app/model/common/oss_data.dart'; import 'package:dating_touchme_app/model/discover/task_data.dart'; +import 'package:dating_touchme_app/model/home/post_data.dart'; import 'package:dating_touchme_app/model/home/user_info_data.dart'; import 'package:dating_touchme_app/model/mine/bank_card_data.dart'; import 'package:dating_touchme_app/model/mine/bank_card_ocr_data.dart'; @@ -303,4 +304,13 @@ abstract class UserApi { @Query('pageNum') required int pageNum, @Query('pageSize') required int pageSize, }); + + + + @GET(ApiUrls.userPageAuthorPost) + Future>> userPageAuthorPost({ + @Query('pageNum') required int pageNum, + @Query('pageSize') required int pageSize, + @Query('authorUserId') required String authorUserId, + }); } diff --git a/lib/network/user_api.g.dart b/lib/network/user_api.g.dart index d149fd0..7979581 100644 --- a/lib/network/user_api.g.dart +++ b/lib/network/user_api.g.dart @@ -1857,6 +1857,45 @@ class _UserApi implements UserApi { return httpResponse; } + @override + Future>> userPageAuthorPost({ + required int pageNum, + required int pageSize, + required String authorUserId, + }) async { + final _extra = {}; + final queryParameters = { + r'pageNum': pageNum, + r'pageSize': pageSize, + r'authorUserId': authorUserId, + }; + final _headers = {}; + const Map? _data = null; + final _options = _setStreamType>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-service/user/page/author-post', + 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) => PostData.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/home/user_information_page.dart b/lib/pages/home/user_information_page.dart index 2879dce..cb1615f 100644 --- a/lib/pages/home/user_information_page.dart +++ b/lib/pages/home/user_information_page.dart @@ -4,7 +4,9 @@ import 'package:dating_touchme_app/controller/home/user_information_controller.d import 'package:dating_touchme_app/generated/assets.dart'; import 'package:dating_touchme_app/model/home/marriage_data.dart'; import 'package:dating_touchme_app/pages/home/report_page.dart'; +import 'package:dating_touchme_app/pages/home/timeline_item.dart'; import 'package:dating_touchme_app/pages/message/chat_page.dart'; +import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -139,249 +141,299 @@ class UserInformationPage extends StatelessWidget { ), ), ), - DraggableScrollableSheet( - initialChildSize: 0.55, // 初始露出高度(占屏幕比例) - minChildSize: 0.55, // 最小(不想下滑回去就设成一样) - maxChildSize: 0.95, - builder: (context, scrollController){ - return Stack( - clipBehavior: Clip.none, - children: [ - Container( - height: 812.h - 361.w - 50, - width: 375.w, - padding: EdgeInsets.only( - top: 31.w, - left: 15.w, - right: 24.w - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.vertical( - top: Radius.circular(23.w) + 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.page.value = 1; + controller.postList.clear(); + await controller.getPostList(); + controller.listRefreshController.finishRefresh(IndicatorResult.success); + controller.listRefreshController.finishLoad(IndicatorResult.none); + }, + // 上拉加载更多 + onLoad: () async { + print('推荐列表上拉加载被触发, hasMore: '); + controller.page.value += 1; + await controller.getPostList(); + }, + child: DraggableScrollableSheet( + initialChildSize: 0.55, // 初始露出高度(占屏幕比例) + minChildSize: 0.55, // 最小(不想下滑回去就设成一样) + maxChildSize: 0.95, + builder: (context, scrollController){ + return SingleChildScrollView( + clipBehavior: Clip.none, + controller: scrollController, + child: Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: 375.w, + constraints: BoxConstraints( + minHeight: 812.h, ), - color: Colors.white - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + padding: EdgeInsets.only( + top: 31.w, + left: 15.w, + right: 24.w + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.vertical( + top: Radius.circular(23.w) + ), + color: Colors.white + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - controller.userData.value.nickName ?? "", - style: TextStyle( - fontSize: 22.w, - color: const Color.fromRGBO(51, 51, 51, 1), - fontWeight: FontWeight.w600 - ), - ), - SizedBox(width: 13.w,), - if(controller.userData.value?.genderCode == 1) Container( - width: 33.w, - height: 13.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(13.w)), - color: const Color.fromRGBO(255, 237, 255, 1) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - Assets.imagesFemale, - width: 8.w, - height: 8.w, - ), - SizedBox(width: 2.w,), - Text( - "${ - controller.calculateAge( - (controller.userData.value.birthDate != null && controller.userData.value.birthDate!.isNotEmpty) ? - (controller.userData.value.birthDate ?? "") : controller.userData.value.birthYear != null && controller.userData.value.birthYear!.isNotEmpty ? - "${controller.userData.value.birthYear}-01-01" : "") - }", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(255, 66, 236, 1) - ), - ) - ], - ), - ), - SizedBox(width: 3.w,), - Container( - width: 33.w, - height: 13.w, - margin: EdgeInsets.only(right: 2.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(13.w)), - color: const Color.fromRGBO(234, 255, 219, 1) - ), - child: Center( - child: Text( - "在线", + Row( + children: [ + Text( + controller.userData.value.nickName ?? "", style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(38, 199, 124, 1) + fontSize: 22.w, + color: const Color.fromRGBO(51, 51, 51, 1), + fontWeight: FontWeight.w600 ), ), - ), - ), - SizedBox(width: 4.w,), - if (controller.userData.value.identityCard != "" && controller.userData.value.identityCard != null) Container( - width: 43.w, - height: 13.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(13.w)), - color: const Color.fromRGBO(246, 237, 255, 1) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - Assets.imagesRealName, - width: 8.w, - height: 7.w, + SizedBox(width: 13.w,), + if(controller.userData.value?.genderCode == 1) Container( + width: 33.w, + height: 13.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(13.w)), + color: const Color.fromRGBO(255, 237, 255, 1) ), - SizedBox(width: 2.w,), - Text( - "实名", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(160, 92, 255, 1) - ), - ) - ], - ), - ), - SizedBox(width: 4.w,), - if(controller.userData.value?.genderCode == 0) Container( - width: 33.w, - height: 13.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(13.w)), - color: const Color.fromRGBO(237, 245, 255, 1) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - Assets.imagesMale, - width: 8.w, - height: 8.w, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + Assets.imagesFemale, + width: 8.w, + height: 8.w, + ), + SizedBox(width: 2.w,), + Text( + "${ + controller.calculateAge( + (controller.userData.value.birthDate != null && controller.userData.value.birthDate!.isNotEmpty) ? + (controller.userData.value.birthDate ?? "") : controller.userData.value.birthYear != null && controller.userData.value.birthYear!.isNotEmpty ? + "${controller.userData.value.birthYear}-01-01" : "") + }", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(255, 66, 236, 1) + ), + ) + ], + ), + ), + SizedBox(width: 3.w,), + Container( + width: 33.w, + height: 13.w, + margin: EdgeInsets.only(right: 2.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(13.w)), + color: const Color.fromRGBO(234, 255, 219, 1) ), - SizedBox(width: 2.w,), - Text( - "${controller.calculateAge(controller.userData.value.birthDate ?? (controller.userData.value.birthYear != null && controller.userData.value.birthYear!.isNotEmpty ? "${controller.userData.value.birthYear}-01-01" : ""))}", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(120, 140, 255, 1) + child: Center( + child: Text( + "在线", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(38, 199, 124, 1) + ), ), - ) - ], - ), + ), + ), + SizedBox(width: 4.w,), + if (controller.userData.value.identityCard != "" && controller.userData.value.identityCard != null) Container( + width: 43.w, + height: 13.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(13.w)), + color: const Color.fromRGBO(246, 237, 255, 1) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + Assets.imagesRealName, + width: 8.w, + height: 7.w, + ), + SizedBox(width: 2.w,), + Text( + "实名", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(160, 92, 255, 1) + ), + ) + ], + ), + ), + SizedBox(width: 4.w,), + if(controller.userData.value?.genderCode == 0) Container( + width: 33.w, + height: 13.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(13.w)), + color: const Color.fromRGBO(237, 245, 255, 1) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + Assets.imagesMale, + width: 8.w, + height: 8.w, + ), + SizedBox(width: 2.w,), + Text( + "${controller.calculateAge(controller.userData.value.birthDate ?? (controller.userData.value.birthYear != null && controller.userData.value.birthYear!.isNotEmpty ? "${controller.userData.value.birthYear}-01-01" : ""))}", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(120, 140, 255, 1) + ), + ) + ], + ), + ), + ], ), ], ), - // 语音介绍功能暂时隐藏(为了通过苹果审核) - // Container( - // width: 63.w, - // height: 27.w, - // decoration: BoxDecoration( - // borderRadius: BorderRadius.all(Radius.circular(27.w)), - // color: const Color.fromRGBO(117, 98, 249, .1) - // ), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Image.asset( - // Assets.imagesPlayer, - // width: 15.w, - // height: 15.w, - // ), - // SizedBox(width: 4.w,), - // Image.asset( - // Assets.imagesVoice, - // width: 15.w, - // height: 13.w, - // ), - // SizedBox(width: 4.w,), - // Text( - // "6'", - // style: TextStyle( - // fontSize: 11.w, - // color: const Color.fromRGBO(117, 98, 249, 1) - // ), - // ) - // ], - // ), - // ) - ], - ), - SizedBox(height: 8.w,), - Text( - (miId == GlobalData().userData!.id && GlobalData().userData!.auditDescribeInfo != null && GlobalData().userData!.auditDescribeInfo != "") ? (GlobalData().userData!.auditDescribeInfo ?? "") : (controller.userData.value.describeInfo ?? "我想找一个有缘的异性,快来联系我吧。"), - style: TextStyle( - fontSize: 14.w, - color: const Color.fromRGBO(144, 144, 144, 1) - ), - ), - SizedBox(height: 11.w,), - Wrap( - spacing: 12.w, - runSpacing: 12.w, - children: [ - ...controller.tagList.map((e){ - return TagItem(label: e); - }), + SizedBox(height: 8.w,), + Text( + (miId == GlobalData().userData!.id && GlobalData().userData!.auditDescribeInfo != null && GlobalData().userData!.auditDescribeInfo != "") ? (GlobalData().userData!.auditDescribeInfo ?? "") : (controller.userData.value.describeInfo ?? "我想找一个有缘的异性,快来联系我吧。"), + style: TextStyle( + fontSize: 14.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ), + SizedBox(height: 11.w,), + Wrap( + spacing: 12.w, + runSpacing: 12.w, + children: [ + ...controller.tagList.map((e){ + return TagItem(label: e); + }), + ], + ), + SizedBox(height: 16.w,), + if ((controller.userData.value.provinceName?.isNotEmpty ?? false)) Text( + "IP属地:${controller.userData.value.provinceName}", + style: TextStyle( + fontSize: 12.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ), + Text( + "趣恋恋ID:${controller.userData.value.miUserId}", + style: TextStyle( + fontSize: 12.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ), + Container( + height: 1, + color: const Color.fromRGBO(0, 0, 0, .3), + margin: EdgeInsets.symmetric(vertical: 15.w), + ), + Obx( + () { + return Column( + children: [ + ...[ + ...controller.postList.map((e){ + return TimelineItem(item: e); + }), + if(controller.postList.isEmpty) Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + Assets.imagesNoMoreTimeline, + width: 90.w, + height: 112.w, + ), + SizedBox(height: 5.w,), + Text( + "暂无动态", + style: TextStyle( + fontSize: 14.w, + color: const Color.fromRGBO(186, 186, 186, 1) + ), + ) + ], + ), + ) + ], + ], + ); + } + ), ], ), - SizedBox(height: 16.w,), - if ((controller.userData.value.provinceName?.isNotEmpty ?? false)) Text( - "IP属地:${controller.userData.value.provinceName}", - style: TextStyle( - fontSize: 12.w, - color: const Color.fromRGBO(144, 144, 144, 1) - ), - ), - Text( - "趣恋恋ID:${controller.userData.value.miUserId}", - style: TextStyle( - fontSize: 12.w, - color: const Color.fromRGBO(144, 144, 144, 1) - ), - ), - ], - ), - ), - Positioned( - left: 15.w, - top: -60.w, - child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(90.w)), - child: Container( - width: 90.w, - height: 90.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(90.w)), - border: Border.all(width: 3.w, color: Colors.white) - ), + ), + Positioned( + left: 15.w, + top: -60.w, child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(84.w)), - child: CachedNetworkImage( - imageUrl: "${controller.userData.value.profilePhoto}?x-oss-process=image/format,webp", - width: 84.w, - height: 84.w, - fit: BoxFit.cover, + borderRadius: BorderRadius.all(Radius.circular(90.w)), + child: Container( + width: 90.w, + height: 90.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(90.w)), + border: Border.all(width: 3.w, color: Colors.white) + ), + child: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(84.w)), + child: CachedNetworkImage( + imageUrl: "${controller.userData.value.profilePhoto}?x-oss-process=image/format,webp", + width: 84.w, + height: 84.w, + fit: BoxFit.cover, + ), + ), ), ), - ), - ), - ) - ], - ); - }, + ) + ], + ), + ); + }, + ), ), Positioned( left: 0,