From 9eb52933c460ff1d20d54d59aa9203d02f4deaf8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 18 Jul 2023 16:54:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8A=A8=E6=80=81=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E4=BA=8C=E7=BA=A7=E8=AF=84=E8=AE=BA=E6=9F=A5=E7=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/reply.dart | 3 +- lib/models/common/reply_type.dart | 2 + lib/pages/dynamics/deatil/view.dart | 43 ++++++++++--- lib/pages/video/detail/controller.dart | 3 + lib/pages/video/detail/reply/view.dart | 22 +++++-- .../detail/reply/widgets/reply_item.dart | 63 ++++++++++--------- lib/pages/video/detail/replyNew/view.dart | 4 +- .../video/detail/replyReply/controller.dart | 9 ++- lib/pages/video/detail/replyReply/view.dart | 61 ++++++++++-------- lib/router/app_pages.dart | 3 + 10 files changed, 140 insertions(+), 73 deletions(-) diff --git a/lib/http/reply.dart b/lib/http/reply.dart index 51c9b8fe..aec1f96b 100644 --- a/lib/http/reply.dart +++ b/lib/http/reply.dart @@ -23,7 +23,7 @@ class ReplyHttp { Map errMap = { -400: '请求错误', -404: '无此项', - 12002: '评论区已关闭', + 12002: '当前页面评论功能已关闭"', 12009: '评论主体的type不合法', 12061: 'UP主已关闭评论区', }; @@ -48,6 +48,7 @@ class ReplyHttp { 'pn': pageNum, 'type': type, 'sort': 1, + 'csrf': await Request.getCsrf(), }); if (res.data['code'] == 0) { return { diff --git a/lib/models/common/reply_type.dart b/lib/models/common/reply_type.dart index a6e8bdb1..eef9c202 100644 --- a/lib/models/common/reply_type.dart +++ b/lib/models/common/reply_type.dart @@ -4,6 +4,8 @@ enum ReplyType { video, // 话题 topic, + // + unset2, // 活动 activity, // 小视频 diff --git a/lib/pages/dynamics/deatil/view.dart b/lib/pages/dynamics/deatil/view.dart index 17df4cec..43c40d57 100644 --- a/lib/pages/dynamics/deatil/view.dart +++ b/lib/pages/dynamics/deatil/view.dart @@ -4,9 +4,11 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/skeleton/video_reply.dart'; import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/pages/dynamics/deatil/index.dart'; import 'package:pilipala/pages/dynamics/widgets/author_panel.dart'; import 'package:pilipala/pages/video/detail/reply/widgets/reply_item.dart'; +import 'package:pilipala/pages/video/detail/replyReply/index.dart'; import '../widgets/dynamic_panel.dart'; @@ -25,19 +27,20 @@ class _DynamicDetailPageState extends State { final ScrollController scrollController = ScrollController(); bool _visibleTitle = false; String? action; + // 回复类型 + late int type; @override void initState() { super.initState(); int oid = 0; - int type = 0; + // floor 1原创 2转发 if (Get.arguments['floor'] == 1) { oid = int.parse(Get.arguments['item'].basic!['comment_id_str']); - type = Get.arguments['item'].basic!['comment_type']; } else { oid = Get.arguments['item'].modules.moduleDynamic.major.draw.id; - type = 11; } + type = Get.arguments['item'].basic!['comment_type']; action = Get.arguments.containsKey('action') ? Get.arguments['action'] : null; _dynamicDetailController = Get.put(DynamicDetailController(oid, type)); @@ -68,6 +71,26 @@ class _DynamicDetailPageState extends State { } } + void replyReply(replyItem, paddingTop) { + int oid = replyItem.replies!.first.oid; + int rpid = replyItem.rpid!; + Get.to( + () => Scaffold( + appBar: AppBar( + title: const Text('评论详情'), + centerTitle: false, + ), + body: VideoReplyReplyPanel( + oid: oid, + rpid: rpid, + paddingTop: paddingTop, + source: 'dynamic', + replyType: ReplyType.values[type], + ), + ), + ); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -189,10 +212,14 @@ class _DynamicDetailPageState extends State { ); } else { return ReplyItem( - replyItem: _dynamicDetailController! - .replyList[index], - showReplyRow: true, - replyLevel: '1'); + replyItem: + _dynamicDetailController!.replyList[index], + showReplyRow: true, + replyLevel: '1', + replyReply: (replyItem, paddingTop) => + replyReply(replyItem, paddingTop), + replyType: ReplyType.album, + ); } }, childCount: @@ -212,7 +239,7 @@ class _DynamicDetailPageState extends State { return SliverList( delegate: SliverChildBuilderDelegate((context, index) { return const VideoReplySkeleton(); - }, childCount: 5), + }, childCount: 8), ); } }, diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 4d0cba91..fad0ea59 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -7,6 +7,7 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/constants.dart'; import 'package:pilipala/http/video.dart'; +import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/play/url.dart'; import 'package:pilipala/models/video/reply/item.dart'; import 'package:pilipala/pages/video/detail/replyReply/index.dart'; @@ -87,6 +88,8 @@ class VideoDetailController extends GetxController }, firstFloor: firstFloor, paddingTop: paddingTop, + replyType: ReplyType.video, + source: 'videoDetail', ); }); ctr?.closed.then((value) { diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index c3a5271d..852dc022 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -6,6 +6,7 @@ import 'package:get/get.dart'; import 'package:pilipala/common/skeleton/video_reply.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/models/video/reply/item.dart'; +import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/replyNew/index.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'controller.dart'; @@ -113,6 +114,16 @@ class _VideoReplyPanelState extends State _videoReplyController.wakeUpReply(); } + // 展示二级回复 + void replyReply(replyItem, paddingTop) { + VideoDetailController videoDetailCtr = + Get.find(tag: Get.arguments['heroTag']); + videoDetailCtr.oid = replyItem.replies!.first.oid; + videoDetailCtr.fRpid = replyItem.rpid!; + videoDetailCtr.firstFloor = replyItem; + videoDetailCtr.showReplyReplyPanel(paddingTop); + } + @override void dispose() { super.dispose(); @@ -164,10 +175,13 @@ class _VideoReplyPanelState extends State ); } else { return ReplyItem( - replyItem: - _videoReplyController.replyList[index], - showReplyRow: true, - replyLevel: replyLevel); + replyItem: + _videoReplyController.replyList[index], + showReplyRow: true, + replyLevel: replyLevel, + replyReply: (replyItem, paddingTop) => + replyReply(replyItem, paddingTop), + ); } }, childCount: diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 40335eba..ce6b9590 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -6,6 +6,7 @@ import 'package:flutter_meedu_media_kit/meedu_player.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/item.dart'; import 'package:pilipala/pages/video/detail/controller.dart'; import 'package:pilipala/pages/video/detail/reply/index.dart'; @@ -14,16 +15,21 @@ import 'package:pilipala/pages/video/detail/replyReply/index.dart'; import 'package:pilipala/utils/utils.dart'; class ReplyItem extends StatelessWidget { - ReplyItem( - {super.key, - this.replyItem, - this.addReply, - this.replyLevel, - this.showReplyRow}); + ReplyItem({ + super.key, + this.replyItem, + this.addReply, + this.replyLevel, + this.showReplyRow, + this.replyReply, + this.replyType, + }); ReplyItemModel? replyItem; Function? addReply; String? replyLevel; bool? showReplyRow = true; + Function? replyReply; + ReplyType? replyType; @override Widget build(BuildContext context) { @@ -212,6 +218,7 @@ class ReplyItem extends StatelessWidget { replyControl: replyItem!.replyControl, f_rpid: replyItem!.rpid, replyItem: replyItem, + replyReply: replyReply, ), ), ], @@ -272,11 +279,13 @@ class ReplyItem extends StatelessWidget { isScrollControlled: true, builder: (builder) { return VideoReplyNewDialog( - replyLevel: replyLevel, - oid: replyItem!.oid, - root: replyItem!.rpid, - parent: replyItem!.rpid, - paddingTop: paddingTop); + replyLevel: replyLevel, + oid: replyItem!.oid, + root: replyItem!.rpid, + parent: replyItem!.rpid, + paddingTop: paddingTop, + replyType: replyType, + ); }, ).then((value) => { // 完成评论,数据添加 @@ -320,21 +329,25 @@ class ReplyItem extends StatelessWidget { // ignore: must_be_immutable class ReplyItemRow extends StatelessWidget { - ReplyItemRow( - {super.key, - this.replies, - this.replyControl, - this.f_rpid, - this.replyItem}); + ReplyItemRow({ + super.key, + this.replies, + this.replyControl, + this.f_rpid, + this.replyItem, + this.replyReply, + }); List? replies; ReplyControl? replyControl; int? f_rpid; ReplyItemModel? replyItem; + Function? replyReply; @override Widget build(BuildContext context) { bool isShow = replyControl!.isShow!; int extraRow = replyControl != null && isShow ? 1 : 0; + double paddingTop = MediaQuery.of(context).padding.top; return Container( margin: const EdgeInsets.only(left: 42, right: 4, top: 0), child: Material( @@ -347,8 +360,7 @@ class ReplyItemRow extends StatelessWidget { children: [ for (var i = 0; i < replies!.length; i++) ...[ InkWell( - onTap: () => - replyReply(replyItem, MediaQuery.of(context).padding.top), + onTap: () => replyReply!(replyItem, paddingTop), child: Container( width: double.infinity, padding: EdgeInsets.fromLTRB( @@ -398,8 +410,7 @@ class ReplyItemRow extends StatelessWidget { ], if (extraRow == 1) InkWell( - onTap: () => - replyReply(replyItem, MediaQuery.of(context).padding.top), + onTap: () => replyReply!(replyItem, paddingTop), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8), @@ -428,16 +439,6 @@ class ReplyItemRow extends StatelessWidget { ), ); } - - void replyReply(replyItem, paddingTop) { - // replyItem 楼主评论 - VideoDetailController videoDetailCtr = - Get.find(tag: Get.arguments['heroTag']); - videoDetailCtr.oid = replies!.first.oid; - videoDetailCtr.fRpid = f_rpid!; - videoDetailCtr.firstFloor = replyItem; - videoDetailCtr.showReplyReplyPanel(paddingTop); - } } InlineSpan buildContent(BuildContext context, content) { diff --git a/lib/pages/video/detail/replyNew/view.dart b/lib/pages/video/detail/replyNew/view.dart index 53b910ff..4d1a52c9 100644 --- a/lib/pages/video/detail/replyNew/view.dart +++ b/lib/pages/video/detail/replyNew/view.dart @@ -13,6 +13,7 @@ class VideoReplyNewDialog extends StatefulWidget { String? replyLevel; int? parent; double? paddingTop; + ReplyType? replyType; VideoReplyNewDialog({ this.oid, @@ -20,6 +21,7 @@ class VideoReplyNewDialog extends StatefulWidget { this.replyLevel, this.parent, this.paddingTop, + this.replyType, }); @override @@ -64,7 +66,7 @@ class _VideoReplyNewDialogState extends State Future submitReplyAdd() async { String message = _replyContentController.text; var result = await VideoHttp.replyAdd( - type: ReplyType.video, + type: widget.replyType!, oid: widget.oid!, root: widget.root!, parent: widget.parent!, diff --git a/lib/pages/video/detail/replyReply/controller.dart b/lib/pages/video/detail/replyReply/controller.dart index 26653d41..9f7c7a94 100644 --- a/lib/pages/video/detail/replyReply/controller.dart +++ b/lib/pages/video/detail/replyReply/controller.dart @@ -1,16 +1,18 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/http/reply.dart'; +import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/data.dart'; import 'package:pilipala/models/video/reply/item.dart'; class VideoReplyReplyController extends GetxController { - VideoReplyReplyController(this.aid, this.rpid); + VideoReplyReplyController(this.aid, this.rpid, this.replyType); final ScrollController scrollController = ScrollController(); // 视频aid 请求时使用的oid int? aid; // rpid 请求楼中楼回复 String? rpid; + ReplyType replyType = ReplyType.video; RxList replyList = [ReplyItemModel()].obs; // 当前页 int currentPage = 0; @@ -41,7 +43,10 @@ class VideoReplyReplyController extends GetxController { } isLoadingMore = true; var res = await ReplyHttp.replyReplyList( - oid: aid!, root: rpid!, pageNum: currentPage + 1, type: 1); + oid: aid!, + root: rpid!, + pageNum: currentPage + 1, + type: replyType.index); if (res['status']) { res['data'] = ReplyData.fromJson(res['data']); if (res['data'].replies.isNotEmpty) { diff --git a/lib/pages/video/detail/replyReply/view.dart b/lib/pages/video/detail/replyReply/view.dart index 49662879..bfda7f76 100644 --- a/lib/pages/video/detail/replyReply/view.dart +++ b/lib/pages/video/detail/replyReply/view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/skeleton/video_reply.dart'; import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/item.dart'; import 'package:pilipala/pages/video/detail/reply/widgets/reply_item.dart'; @@ -13,6 +14,8 @@ class VideoReplyReplyPanel extends StatefulWidget { Function? closePanel; ReplyItemModel? firstFloor; double? paddingTop; + String? source; + ReplyType? replyType; VideoReplyReplyPanel({ this.oid, @@ -20,6 +23,8 @@ class VideoReplyReplyPanel extends StatefulWidget { this.closePanel, this.firstFloor, this.paddingTop, + this.source, + this.replyType, super.key, }); @@ -34,7 +39,8 @@ class _VideoReplyReplyPanelState extends State { @override void initState() { _videoReplyReplyController = Get.put( - VideoReplyReplyController(widget.oid, widget.rpid.toString()), + VideoReplyReplyController( + widget.oid, widget.rpid.toString(), widget.replyType!), tag: widget.rpid.toString()); super.initState(); @@ -62,34 +68,37 @@ class _VideoReplyReplyPanelState extends State { @override Widget build(BuildContext context) { return Container( - height: MediaQuery.of(context).size.height - - MediaQuery.of(context).size.width * 9 / 16 - - widget.paddingTop!, + height: widget.source == 'videoDetail' + ? MediaQuery.of(context).size.height - + MediaQuery.of(context).size.width * 9 / 16 - + widget.paddingTop! + : null, color: Theme.of(context).colorScheme.background, child: Column( children: [ - Container( - height: 45, - padding: const EdgeInsets.only(left: 14, right: 14), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '评论详情', - style: Theme.of(context).textTheme.titleMedium, - ), - IconButton( - icon: const Icon(Icons.close), - onPressed: () { - _videoReplyReplyController.currentPage = 0; - _videoReplyReplyController.rPid = 0; - widget.closePanel!(); - Navigator.pop(context); - }, - ), - ], + if (widget.source == 'videoDetail') + Container( + height: 45, + padding: const EdgeInsets.only(left: 14, right: 14), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '评论详情', + style: Theme.of(context).textTheme.titleMedium, + ), + IconButton( + icon: const Icon(Icons.close), + onPressed: () { + _videoReplyReplyController.currentPage = 0; + _videoReplyReplyController.rPid = 0; + widget.closePanel!(); + Navigator.pop(context); + }, + ), + ], + ), ), - ), Divider( height: 1, color: Theme.of(context).dividerColor.withOpacity(0.1), @@ -188,7 +197,7 @@ class _VideoReplyReplyPanelState extends State { delegate: SliverChildBuilderDelegate((context, index) { return const VideoReplySkeleton(); - }, childCount: 5), + }, childCount: 8), ); } }, diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index 5474607c..3d0f4fb9 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -15,6 +15,7 @@ import 'package:pilipala/pages/preview/index.dart'; import 'package:pilipala/pages/search/index.dart'; import 'package:pilipala/pages/searchResult/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; +import 'package:pilipala/pages/video/detail/replyReply/index.dart'; import 'package:pilipala/pages/webview/index.dart'; import 'package:pilipala/pages/setting/index.dart'; import 'package:pilipala/pages/media/index.dart'; @@ -65,5 +66,7 @@ class Routes { GetPage(name: '/liveRoom', page: () => const LiveRoomPage()), // 用户中心 GetPage(name: '/member', page: () => const MemberPage()), + // 二级回复 + GetPage(name: '/replyReply', page: () => VideoReplyReplyPanel()), ]; }