opt pgc review

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-05-24 20:11:28 +08:00
parent 2d22501d08
commit a130b5db98
8 changed files with 224 additions and 64 deletions

View File

@@ -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';
}

View File

@@ -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']};
}
}
}

View File

@@ -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<void> 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']);
}
}
}

View File

@@ -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<PgcReviewChildPage>
: 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(

View File

@@ -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<PgcReviewPostPanel> createState() => _PgcReviewPostPanelState();
@@ -23,10 +30,11 @@ class PgcReviewPostPanel extends CommonCollapseSlidePage {
class _PgcReviewPostPanelState
extends CommonCollapseSlidePageState<PgcReviewPostPanel> {
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<void> _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']);
}
}
}

View File

@@ -87,8 +87,11 @@ class _PgcReviewPageState extends State<PgcReviewPage>
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(),
),
),

View File

@@ -39,7 +39,7 @@ class BangumiIntroController extends GetxController {
? '追番'
: '追剧';
BangumiInfoModel bangumiItem = Get.arguments['bangumiItem'];
final BangumiInfoModel bangumiItem = Get.arguments['bangumiItem'];
// 是否点赞
RxBool hasLike = false.obs;

View File

@@ -108,6 +108,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
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<VideoDetailPageV>
slivers: [
if (videoDetailController.videoType == SearchType.video) ...[
VideoIntroPanel(
key: ugcPanelKey,
heroTag: heroTag,
showAiBottomSheet: showAiBottomSheet,
showEpisodes: showEpisodes,
@@ -1831,6 +1834,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
SearchType.media_bangumi)
Obx(
() => BangumiIntroPanel(
key: pgcPanelKey,
heroTag: heroTag,
cid: videoDetailController.cid.value,
showEpisodes: showEpisodes,