diff --git a/lib/http/api.dart b/lib/http/api.dart index 086c2aa0..4f01f21a 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -865,4 +865,8 @@ class Api { static const String pgcReviewDislike = '/pgc/review/action/dislike'; static const String pgcReviewPost = '/pgc/review/short/post'; + + static const String pgcReviewMod = '/pgc/review/short/modify'; + + static const String pgcReviewDel = '/pgc/review/short/del'; } diff --git a/lib/http/bangumi.dart b/lib/http/bangumi.dart index 3f489068..b0802755 100644 --- a/lib/http/bangumi.dart +++ b/lib/http/bangumi.dart @@ -200,4 +200,48 @@ class BangumiHttp { return {'status': false, 'msg': res.data['message']}; } } + + static Future pgcReviewMod({ + required mediaId, + required int score, + required String content, + required reviewId, + }) async { + var res = await Request().post( + Api.pgcReviewMod, + data: { + 'media_id': mediaId, + 'score': score, + 'content': content, + 'review_id': reviewId, + 'csrf': Accounts.main.csrf, + }, + options: Options(contentType: Headers.formUrlEncodedContentType), + ); + if (res.data['code'] == 0) { + return {'status': true}; + } else { + return {'status': false, 'msg': res.data['message']}; + } + } + + static Future pgcReviewDel({ + required mediaId, + required reviewId, + }) async { + var res = await Request().post( + Api.pgcReviewDel, + data: { + 'media_id': mediaId, + 'review_id': reviewId, + 'csrf': Accounts.main.csrf, + }, + options: Options(contentType: Headers.formUrlEncodedContentType), + ); + if (res.data['code'] == 0) { + return {'status': true}; + } else { + return {'status': false, 'msg': res.data['message']}; + } + } } diff --git a/lib/pages/pgc_review/child/controller.dart b/lib/pages/pgc_review/child/controller.dart index 15231c6f..3c6cc3aa 100644 --- a/lib/pages/pgc_review/child/controller.dart +++ b/lib/pages/pgc_review/child/controller.dart @@ -79,6 +79,9 @@ class PgcReviewController final item = loadingState.value.data![index]; item.stat?.disliked = isDislike ? 0 : 1; if (!isDislike) { + if (item.stat?.liked == 1) { + item.stat!.likes = item.stat!.likes! - 1; + } item.stat?.liked = 0; } loadingState.refresh(); @@ -86,4 +89,19 @@ class PgcReviewController SmartDialog.showToast(res['msg']); } } + + Future onDel(int index, int? reviewId) async { + var res = await BangumiHttp.pgcReviewDel( + mediaId: mediaId, + reviewId: reviewId, + ); + if (res['status']) { + loadingState + ..value.data!.removeAt(index) + ..refresh(); + SmartDialog.showToast('删除成功'); + } else { + SmartDialog.showToast(res['msg']); + } + } } diff --git a/lib/pages/pgc_review/child/view.dart b/lib/pages/pgc_review/child/view.dart index dda1c0d8..c2e48e60 100644 --- a/lib/pages/pgc_review/child/view.dart +++ b/lib/pages/pgc_review/child/view.dart @@ -9,7 +9,9 @@ import 'package:PiliPlus/models/bangumi/pgc_review/list.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/common/pgc_review_type.dart'; import 'package:PiliPlus/pages/pgc_review/child/controller.dart'; +import 'package:PiliPlus/pages/pgc_review/post/view.dart'; import 'package:PiliPlus/utils/extension.dart'; +import 'package:PiliPlus/utils/storage.dart' show Accounts; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -19,10 +21,12 @@ class PgcReviewChildPage extends StatefulWidget { const PgcReviewChildPage({ super.key, required this.type, + required this.name, required this.mediaId, }); final PgcReviewType type; + final String name; final dynamic mediaId; @override @@ -113,15 +117,74 @@ class _PgcReviewChildPageState extends State : null, onLongPress: isLongReview ? null - : () => showConfirmDialog( + : () => showDialog( context: context, - title: '确定举报该点评?', - onConfirm: () => Get.toNamed( - '/webview', - parameters: { - 'url': - 'https://www.bilibili.com/appeal/?reviewId=${item.reviewId}&type=shortComment&mediaId=${widget.mediaId}' - }, + builder: (context) => AlertDialog( + clipBehavior: Clip.hardEdge, + contentPadding: const EdgeInsets.symmetric(vertical: 12), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (item.author!.mid == Accounts.main.mid) ...[ + ListTile( + dense: true, + title: const Text( + '编辑', + style: TextStyle(fontSize: 14), + ), + onTap: () { + Get.back(); + showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + builder: (context) { + return PgcReviewPostPanel( + name: widget.name, + mediaId: widget.mediaId, + reviewId: item.reviewId, + content: item.content, + score: item.score, + ); + }, + ); + }, + ), + ListTile( + dense: true, + title: const Text( + '删除', + style: TextStyle(fontSize: 14), + ), + onTap: () { + Get.back(); + showConfirmDialog( + context: context, + title: '删除短评,同时删除评分?', + onConfirm: () => + _controller.onDel(index, item.reviewId), + ); + }, + ), + ], + ListTile( + dense: true, + title: const Text( + '举报', + style: TextStyle(fontSize: 14), + ), + onTap: () => Get + ..back() + ..toNamed( + '/webview', + parameters: { + 'url': + 'https://www.bilibili.com/appeal/?reviewId=${item.reviewId}&type=shortComment&mediaId=${widget.mediaId}' + }, + ), + ), + ], + ), ), ), child: Padding( diff --git a/lib/pages/pgc_review/post/view.dart b/lib/pages/pgc_review/post/view.dart index 86d01eca..3dde8e9a 100644 --- a/lib/pages/pgc_review/post/view.dart +++ b/lib/pages/pgc_review/post/view.dart @@ -12,10 +12,17 @@ class PgcReviewPostPanel extends CommonCollapseSlidePage { super.key, required this.name, required this.mediaId, + this.reviewId, + this.score, + this.content, }); final String name; final dynamic mediaId; + // modify + final dynamic reviewId; + final int? score; + final String? content; @override State createState() => _PgcReviewPostPanelState(); @@ -23,10 +30,11 @@ class PgcReviewPostPanel extends CommonCollapseSlidePage { class _PgcReviewPostPanelState extends CommonCollapseSlidePageState { - final _controller = TextEditingController(); - final RxInt _score = 0.obs; - final RxBool _shareFeed = false.obs; - final RxBool _enablePost = false.obs; + late final _controller = TextEditingController(text: widget.content); + late final RxInt _score = (widget.score ?? 0).obs; + late final RxBool _shareFeed = false.obs; + late final RxBool _enablePost = _isMod.obs; + late final _isMod = widget.reviewId != null; @override void dispose() { @@ -134,36 +142,37 @@ class _PgcReviewPostPanelState textInputAction: TextInputAction.done, ), ), - Padding( - padding: const EdgeInsets.only(left: 12, right: 12, bottom: 12), - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => _shareFeed.value = !_shareFeed.value, - child: Obx( - () { - Color color = _shareFeed.value - ? theme.colorScheme.primary - : theme.colorScheme.outline; - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - size: 22, - _shareFeed.value - ? Icons.check_box_outlined - : Icons.check_box_outline_blank_outlined, - color: color, - ), - Text( - ' 分享到动态', - style: TextStyle(color: color), - ), - ], - ); - }, + if (!_isMod) + Padding( + padding: const EdgeInsets.only(left: 12, right: 12, bottom: 12), + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => _shareFeed.value = !_shareFeed.value, + child: Obx( + () { + Color color = _shareFeed.value + ? theme.colorScheme.primary + : theme.colorScheme.outline; + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 22, + _shareFeed.value + ? Icons.check_box_outlined + : Icons.check_box_outline_blank_outlined, + color: color, + ), + Text( + ' 分享到动态', + style: TextStyle(color: color), + ), + ], + ); + }, + ), ), ), - ), Container( padding: EdgeInsets.only( left: 12, @@ -192,31 +201,46 @@ class _PgcReviewPostPanelState borderRadius: BorderRadius.all(Radius.circular(6)), ), ), - onPressed: _enablePost.value - ? () async { - if (!Accounts.main.isLogin) { - SmartDialog.showToast('账号未登录'); - return; - } - var res = await BangumiHttp.pgcReviewPost( - mediaId: widget.mediaId, - score: _score.value * 2, - content: _controller.text, - shareFeed: _shareFeed.value, - ); - if (res['status']) { - Get.back(); - SmartDialog.showToast('点评成功'); - } else { - SmartDialog.showToast(res['msg']); - } - } - : null, - child: const Text('发布'), + onPressed: _enablePost.value ? _onPost : null, + child: _isMod ? const Text('编辑') : const Text('发布'), ), ), ), ], ); } + + Future _onPost() async { + if (_isMod) { + var res = await BangumiHttp.pgcReviewMod( + mediaId: widget.mediaId, + score: _score.value * 2, + content: _controller.text, + reviewId: widget.reviewId, + ); + if (res['status']) { + Get.back(); + SmartDialog.showToast('编辑成功'); + } else { + SmartDialog.showToast(res['msg']); + } + return; + } + if (!Accounts.main.isLogin) { + SmartDialog.showToast('账号未登录'); + return; + } + var res = await BangumiHttp.pgcReviewPost( + mediaId: widget.mediaId, + score: _score.value * 2, + content: _controller.text, + shareFeed: _isMod ? false : _shareFeed.value, + ); + if (res['status']) { + Get.back(); + SmartDialog.showToast('点评成功'); + } else { + SmartDialog.showToast(res['msg']); + } + } } diff --git a/lib/pages/pgc_review/view.dart b/lib/pages/pgc_review/view.dart index 998dcb60..15c2aa52 100644 --- a/lib/pages/pgc_review/view.dart +++ b/lib/pages/pgc_review/view.dart @@ -87,8 +87,11 @@ class _PgcReviewPageState extends State controller: _tabController, physics: const NeverScrollableScrollPhysics(), children: PgcReviewType.values - .map((e) => - PgcReviewChildPage(type: e, mediaId: widget.mediaId)) + .map((e) => PgcReviewChildPage( + type: e, + name: widget.name, + mediaId: widget.mediaId, + )) .toList(), ), ), diff --git a/lib/pages/video/introduction/pgc/controller.dart b/lib/pages/video/introduction/pgc/controller.dart index 63655896..e6132edc 100644 --- a/lib/pages/video/introduction/pgc/controller.dart +++ b/lib/pages/video/introduction/pgc/controller.dart @@ -39,7 +39,7 @@ class BangumiIntroController extends GetxController { ? '追番' : '追剧'; - BangumiInfoModel bangumiItem = Get.arguments['bangumiItem']; + final BangumiInfoModel bangumiItem = Get.arguments['bangumiItem']; // 是否点赞 RxBool hasLike = false.obs; diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index 9933de71..6d5d9798 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -108,6 +108,8 @@ class _VideoDetailPageVState extends State final GlobalKey relatedVideoPanelKey = GlobalKey(); final GlobalKey videoPlayerKey = GlobalKey(); final GlobalKey videoReplyPanelKey = GlobalKey(); + late final GlobalKey ugcPanelKey = GlobalKey(); + late final GlobalKey pgcPanelKey = GlobalKey(); @override void initState() { @@ -1797,6 +1799,7 @@ class _VideoDetailPageVState extends State slivers: [ if (videoDetailController.videoType == SearchType.video) ...[ VideoIntroPanel( + key: ugcPanelKey, heroTag: heroTag, showAiBottomSheet: showAiBottomSheet, showEpisodes: showEpisodes, @@ -1831,6 +1834,7 @@ class _VideoDetailPageVState extends State SearchType.media_bangumi) Obx( () => BangumiIntroPanel( + key: pgcPanelKey, heroTag: heroTag, cid: videoDetailController.cid.value, showEpisodes: showEpisodes,