From f440edf43b0fcaff63be3caf93bb4bc44d4338c2 Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Thu, 19 Jun 2025 10:14:46 +0800 Subject: [PATCH] feat: msg like detail Signed-off-by: bggRGjQaUbCoE --- lib/http/api.dart | 2 + lib/http/msg.dart | 24 +++ lib/models_new/msg/msg_like_detail/card.dart | 51 ++++++ lib/models_new/msg/msg_like_detail/data.dart | 24 +++ lib/models_new/msg/msg_like_detail/item.dart | 16 ++ lib/models_new/msg/msg_like_detail/page.dart | 10 ++ lib/models_new/msg/msg_like_detail/user.dart | 27 ++++ .../msg_feed_top/like_detail/controller.dart | 37 +++++ lib/pages/msg_feed_top/like_detail/view.dart | 145 ++++++++++++++++++ lib/pages/msg_feed_top/like_me/view.dart | 16 +- lib/router/app_pages.dart | 2 + 11 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 lib/models_new/msg/msg_like_detail/card.dart create mode 100644 lib/models_new/msg/msg_like_detail/data.dart create mode 100644 lib/models_new/msg/msg_like_detail/item.dart create mode 100644 lib/models_new/msg/msg_like_detail/page.dart create mode 100644 lib/models_new/msg/msg_like_detail/user.dart create mode 100644 lib/pages/msg_feed_top/like_detail/controller.dart create mode 100644 lib/pages/msg_feed_top/like_detail/view.dart diff --git a/lib/http/api.dart b/lib/http/api.dart index 5b32ad6a5..200d4b70c 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -894,4 +894,6 @@ class Api { static const String matchInfo = '/x/esports/match/info'; static const String dynPic = '/x/polymer/web-dynamic/v1/detail/pic'; + + static const String msgLikeDetail = '/x/msgfeed/like_detail'; } diff --git a/lib/http/msg.dart b/lib/http/msg.dart index 2035d6c16..619a89434 100644 --- a/lib/http/msg.dart +++ b/lib/http/msg.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/models_new/msg/im_user_infos/datum.dart'; import 'package:PiliPlus/models_new/msg/msg_at/data.dart'; import 'package:PiliPlus/models_new/msg/msg_dnd/uid_setting.dart'; import 'package:PiliPlus/models_new/msg/msg_like/data.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/data.dart'; import 'package:PiliPlus/models_new/msg/msg_reply/data.dart'; import 'package:PiliPlus/models_new/msg/msg_sys/data.dart'; import 'package:PiliPlus/models_new/msg/session_ss/data.dart'; @@ -77,6 +78,29 @@ class MsgHttp { } } + static Future> msgLikeDetail({ + required dynamic cardId, + required int pn, + }) async { + var res = await Request().get( + Api.msgLikeDetail, + queryParameters: { + 'card_id': cardId, + 'pn': pn, + 'last_view_at': 0, + 'platform': 'web', + 'build': 0, + 'mobi_app': 'web', + 'web_location': 333.40164, + }, + ); + if (res.data['code'] == 0) { + return Success(MsgLikeDetailData.fromJson(res.data['data'])); + } else { + return Error(res.data['message']); + } + } + static Future?>> msgFeedNotify( {int? cursor, int pageSize = 20}) async { var res = await Request().get( diff --git a/lib/models_new/msg/msg_like_detail/card.dart b/lib/models_new/msg/msg_like_detail/card.dart new file mode 100644 index 000000000..fdd9f39e2 --- /dev/null +++ b/lib/models_new/msg/msg_like_detail/card.dart @@ -0,0 +1,51 @@ +class MsgLikeDetailCard { + int? itemId; + int? pid; + String? type; + String? business; + int? businessId; + int? replyBusinessId; + int? likeBusinessId; + String? title; + String? desc; + String? image; + String? uri; + String? detailName; + String? nativeUri; + int? ctime; + + MsgLikeDetailCard({ + this.itemId, + this.pid, + this.type, + this.business, + this.businessId, + this.replyBusinessId, + this.likeBusinessId, + this.title, + this.desc, + this.image, + this.uri, + this.detailName, + this.nativeUri, + this.ctime, + }); + + factory MsgLikeDetailCard.fromJson(Map json) => + MsgLikeDetailCard( + itemId: json['item_id'] as int?, + pid: json['pid'] as int?, + type: json['type'] as String?, + business: json['business'] as String?, + businessId: json['business_id'] as int?, + replyBusinessId: json['reply_business_id'] as int?, + likeBusinessId: json['like_business_id'] as int?, + title: json['title'] as String?, + desc: json['desc'] as String?, + image: json['image'] as String?, + uri: json['uri'] as String?, + detailName: json['detail_name'] as String?, + nativeUri: json['native_uri'] as String?, + ctime: json['ctime'] as int?, + ); +} diff --git a/lib/models_new/msg/msg_like_detail/data.dart b/lib/models_new/msg/msg_like_detail/data.dart new file mode 100644 index 000000000..12b326fda --- /dev/null +++ b/lib/models_new/msg/msg_like_detail/data.dart @@ -0,0 +1,24 @@ +import 'package:PiliPlus/models_new/msg/msg_like_detail/card.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/item.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/page.dart'; + +class MsgLikeDetailData { + MsgLikeDetailPage? page; + MsgLikeDetailCard? card; + List? items; + + MsgLikeDetailData({this.page, this.card, this.items}); + + factory MsgLikeDetailData.fromJson(Map json) => + MsgLikeDetailData( + page: json['page'] == null + ? null + : MsgLikeDetailPage.fromJson(json['page'] as Map), + card: json['card'] == null + ? null + : MsgLikeDetailCard.fromJson(json['card'] as Map), + items: (json['items'] as List?) + ?.map((e) => MsgLikeDetailItem.fromJson(e as Map)) + .toList(), + ); +} diff --git a/lib/models_new/msg/msg_like_detail/item.dart b/lib/models_new/msg/msg_like_detail/item.dart new file mode 100644 index 000000000..d0bf670ef --- /dev/null +++ b/lib/models_new/msg/msg_like_detail/item.dart @@ -0,0 +1,16 @@ +import 'package:PiliPlus/models_new/msg/msg_like_detail/user.dart'; + +class MsgLikeDetailItem { + MsgLikeDetailUser? user; + int? likeTime; + + MsgLikeDetailItem({this.user, this.likeTime}); + + factory MsgLikeDetailItem.fromJson(Map json) => + MsgLikeDetailItem( + user: json['user'] == null + ? null + : MsgLikeDetailUser.fromJson(json['user'] as Map), + likeTime: json['like_time'] as int?, + ); +} diff --git a/lib/models_new/msg/msg_like_detail/page.dart b/lib/models_new/msg/msg_like_detail/page.dart new file mode 100644 index 000000000..124ec0997 --- /dev/null +++ b/lib/models_new/msg/msg_like_detail/page.dart @@ -0,0 +1,10 @@ +class MsgLikeDetailPage { + bool? isEnd; + + MsgLikeDetailPage({this.isEnd}); + + factory MsgLikeDetailPage.fromJson(Map json) => + MsgLikeDetailPage( + isEnd: json['is_end'] as bool?, + ); +} diff --git a/lib/models_new/msg/msg_like_detail/user.dart b/lib/models_new/msg/msg_like_detail/user.dart new file mode 100644 index 000000000..273362a89 --- /dev/null +++ b/lib/models_new/msg/msg_like_detail/user.dart @@ -0,0 +1,27 @@ +class MsgLikeDetailUser { + int? mid; + int? fans; + String? nickname; + String? avatar; + String? midLink; + bool? follow; + + MsgLikeDetailUser({ + this.mid, + this.fans, + this.nickname, + this.avatar, + this.midLink, + this.follow, + }); + + factory MsgLikeDetailUser.fromJson(Map json) => + MsgLikeDetailUser( + mid: json['mid'] as int?, + fans: json['fans'] as int?, + nickname: json['nickname'] as String?, + avatar: json['avatar'] as String?, + midLink: json['mid_link'] as String?, + follow: json['follow'] as bool?, + ); +} diff --git a/lib/pages/msg_feed_top/like_detail/controller.dart b/lib/pages/msg_feed_top/like_detail/controller.dart new file mode 100644 index 000000000..b1f414981 --- /dev/null +++ b/lib/pages/msg_feed_top/like_detail/controller.dart @@ -0,0 +1,37 @@ +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/msg.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/card.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/data.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/item.dart'; +import 'package:PiliPlus/pages/common/common_list_controller.dart'; +import 'package:get/get.dart'; + +class LikeDetailController + extends CommonListController { + final cardId = Get.parameters['id']; + final uri = Get.parameters['uri']; + + @override + void onInit() { + super.onInit(); + queryData(); + } + + MsgLikeDetailCard? card; + + @override + List? getDataList(MsgLikeDetailData response) { + if (response.page?.isEnd == true) { + isEnd = true; + } + card = response.card; + return response.items; + } + + @override + Future> customGetData() => + MsgHttp.msgLikeDetail( + cardId: cardId, + pn: page, + ); +} diff --git a/lib/pages/msg_feed_top/like_detail/view.dart b/lib/pages/msg_feed_top/like_detail/view.dart new file mode 100644 index 000000000..42e2202e8 --- /dev/null +++ b/lib/pages/msg_feed_top/like_detail/view.dart @@ -0,0 +1,145 @@ +import 'package:PiliPlus/common/skeleton/msg_feed_top.dart'; +import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; +import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/card.dart'; +import 'package:PiliPlus/models_new/msg/msg_like_detail/item.dart'; +import 'package:PiliPlus/pages/msg_feed_top/like_detail/controller.dart'; +import 'package:PiliPlus/utils/app_scheme.dart'; +import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class LikeDetailPage extends StatefulWidget { + const LikeDetailPage({super.key}); + + @override + State createState() => _LikeDetailPageState(); +} + +class _LikeDetailPageState extends State { + final LikeDetailController _controller = + Get.put(LikeDetailController(), tag: Utils.generateRandomString(8)); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Scaffold( + appBar: AppBar(title: const Text('点赞详情')), + body: refreshIndicator( + onRefresh: _controller.onRefresh, + child: CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverPadding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 80), + sliver: + Obx(() => _buildBody(theme, _controller.loadingState.value)), + ), + ], + ), + ), + ); + } + + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState) { + late final divider = Divider( + indent: 72, + endIndent: 20, + height: 6, + color: Colors.grey.withValues(alpha: 0.1), + ); + return switch (loadingState) { + Loading() => SliverList.builder( + itemCount: 12, + itemBuilder: (context, index) { + return const MsgFeedTopSkeleton(); + }, + ), + Success(:var response) => SliverMainAxisGroup( + slivers: [ + if (_controller.card != null) ...[ + _buildCard(_controller.card!), + SliverToBoxAdapter( + child: Divider( + height: 1, + color: Colors.grey.withValues(alpha: 0.1), + ), + ), + ], + SliverList.separated( + itemCount: response!.length, + itemBuilder: (context, index) { + if (index == response.length - 1) { + _controller.onLoadMore(); + } + return _buildItem(theme, response[index]); + }, + separatorBuilder: (context, index) => divider, + ), + ], + ), + Error(:var errMsg) => HttpError( + errMsg: errMsg, + onReload: _controller.onReload, + ), + }; + } + + Widget _buildCard(MsgLikeDetailCard card) { + return SliverToBoxAdapter( + child: ListTile( + onTap: () { + if (_controller.uri != null) { + PiliScheme.routePushFromUrl(_controller.uri!); + } + }, + title: Text('${card.business}: ${card.title}'), + ), + ); + } + + Widget _buildItem(ThemeData theme, MsgLikeDetailItem item) { + return ListTile( + onTap: () => Get.toNamed('/member?mid=${item.user!.mid}'), + leading: NetworkImgLayer( + width: 45, + height: 45, + type: ImageType.avatar, + src: item.user!.avatar, + ), + title: Text.rich( + TextSpan( + children: [ + TextSpan( + text: "${item.user!.nickname}", + style: theme.textTheme.titleSmall! + .copyWith(height: 1.5, color: theme.colorScheme.primary), + ), + TextSpan( + text: " 赞了我", + style: TextStyle( + fontSize: 13, + color: theme.colorScheme.onSurfaceVariant, + ), + ), + ], + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + subtitle: Text( + DateUtil.dateFormat(item.likeTime), + style: theme.textTheme.bodyMedium!.copyWith( + fontSize: 13, + color: theme.colorScheme.outline, + ), + ), + ); + } +} diff --git a/lib/pages/msg_feed_top/like_me/view.dart b/lib/pages/msg_feed_top/like_me/view.dart index ea1838fb6..8491562d0 100644 --- a/lib/pages/msg_feed_top/like_me/view.dart +++ b/lib/pages/msg_feed_top/like_me/view.dart @@ -170,9 +170,19 @@ class _LikeMePageState extends State { return ListTile( onTap: () { String? nativeUri = item.item?.nativeUri; - if (nativeUri == null || - nativeUri.isEmpty || - nativeUri.startsWith('?')) { + bool isInvalid = + nativeUri == null || nativeUri.isEmpty || nativeUri.startsWith('?'); + if (item.counts! > 1) { + Get.toNamed( + 'msgLikeDetail', + parameters: { + 'id': item.id!.toString(), + if (!isInvalid) 'uri': nativeUri, + }, + ); + return; + } + if (isInvalid) { return; } PiliScheme.routePushFromUrl(nativeUri); diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index 06baf2583..d44df5569 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -31,6 +31,7 @@ import 'package:PiliPlus/pages/member_profile/view.dart'; import 'package:PiliPlus/pages/member_search/view.dart'; import 'package:PiliPlus/pages/member_upower_rank/view.dart'; import 'package:PiliPlus/pages/msg_feed_top/at_me/view.dart'; +import 'package:PiliPlus/pages/msg_feed_top/like_detail/view.dart'; import 'package:PiliPlus/pages/msg_feed_top/like_me/view.dart'; import 'package:PiliPlus/pages/msg_feed_top/reply_me/view.dart'; import 'package:PiliPlus/pages/msg_feed_top/sys_msg/view.dart'; @@ -181,6 +182,7 @@ class Routes { CustomGetPage(name: '/spaceSetting', page: () => const SpaceSettingPage()), CustomGetPage(name: '/dynTopicRcmd', page: () => const DynTopicRcmdPage()), CustomGetPage(name: '/matchInfo', page: () => const MatchInfoPage()), + CustomGetPage(name: '/msgLikeDetail', page: () => const LikeDetailPage()), ]; }