213 lines
6.4 KiB
Dart
213 lines
6.4 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:get/get.dart';
|
||
import 'package:hgdj/hj_model/comment/comment_model.dart';
|
||
import 'package:hgdj/hj_model/comment/reply_model.dart';
|
||
import 'package:hgdj/hj_page/comment/comment_input_view.dart';
|
||
import 'package:hgdj/hj_utils/api_service/comment_service.dart';
|
||
import 'package:hgdj/hj_utils/api_service/common_service.dart';
|
||
import 'package:hgdj/hj_utils/date_time_util.dart';
|
||
import 'package:hgdj/tools_base/debug_log.dart';
|
||
import 'package:hgdj/tools_base/toast.dart';
|
||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||
|
||
import '../../hj_model/banner/comment_top_banner_model.dart';
|
||
import '../../hj_model/comment/comment_list_res.dart';
|
||
import '../../tools_base/file_upload/file_upload_tool.dart';
|
||
import '../../tools_base/file_upload/upload_result_model.dart';
|
||
|
||
mixin CommentMixin on GetxController {
|
||
final comments = <CommentModel>[];
|
||
final commentController = TextEditingController();
|
||
Function(int)? totalCallback;
|
||
CommentModel? replyComment;
|
||
ReplyModel? replyCommentModel;
|
||
int page = 1;
|
||
String? hintText;
|
||
Rx<String?> selectedImagePath = Rx<String?>(null);
|
||
RefreshController? refreshCtr;
|
||
final quickSearchList = <CommentLink>[];
|
||
final commentTopBanners = <CommentTopBannerModel>[];
|
||
String? id;
|
||
String? objType;
|
||
RxBool isSendingMsg = false.obs;
|
||
|
||
@override
|
||
void onClose() {
|
||
commentController.dispose();
|
||
super.onClose();
|
||
}
|
||
|
||
Future sendComment() async {
|
||
String content = commentController.text;
|
||
if (content.isEmpty) {
|
||
showToast('请输入评论内容哦~');
|
||
return;
|
||
}
|
||
isSendingMsg.value = true;
|
||
String? sendImagePath;
|
||
if (selectedImagePath.value?.isNotEmpty == true) {
|
||
try {
|
||
ImageUploadResultModel? imgResult =
|
||
await FileUploadTool().uploadImage(selectedImagePath.value!);
|
||
sendImagePath = imgResult?.coverImg ?? "";
|
||
if (sendImagePath.isEmpty) {
|
||
isSendingMsg.value = false;
|
||
showToast("图片上传失败!");
|
||
return;
|
||
}
|
||
} catch (e) {
|
||
debugLog(e);
|
||
isSendingMsg.value = false;
|
||
showToast("图片上传失败!");
|
||
return;
|
||
}
|
||
}
|
||
|
||
try {
|
||
if (replyComment != null) {
|
||
// 回复评论
|
||
final res = await CommentService.sendReply(
|
||
id,
|
||
2,
|
||
content,
|
||
rid: replyCommentModel?.id,
|
||
cid: replyComment?.id,
|
||
toUserID: replyCommentModel?.toUserID,
|
||
objType: objType,
|
||
image: sendImagePath,
|
||
);
|
||
if (res != null) {
|
||
replyComment?.replies ??= [];
|
||
replyComment?.replies?.insert(0, res);
|
||
replyComment?.commCount = replyComment?.replies?.length ?? 0;
|
||
replyComment = null;
|
||
replyCommentModel = null;
|
||
hintText = null;
|
||
showToast('已提交,审核通过后将展示');
|
||
}
|
||
update();
|
||
} else {
|
||
// 评论
|
||
final res = await CommentService.sendComment(
|
||
id,
|
||
1,
|
||
content,
|
||
objType ?? '',
|
||
image: sendImagePath,
|
||
);
|
||
if (res == null) {
|
||
hintText = null;
|
||
} else {
|
||
showToast('已提交,审核通过后将展示');
|
||
hintText = null;
|
||
//插在第一条普通评论前面,置顶那几条不动
|
||
final insertIndex =
|
||
comments.indexWhere((e) => !e.isHideLikeOrComment);
|
||
comments.insert(
|
||
insertIndex == -1 ? comments.length : insertIndex, res);
|
||
}
|
||
update();
|
||
}
|
||
} catch (e) {
|
||
debugLog(e);
|
||
}
|
||
selectedImagePath.value = null;
|
||
commentController.text = "";
|
||
isSendingMsg.value = false;
|
||
}
|
||
|
||
// isSend: true 点击了发送按钮, 如果没有发送内容弹键盘, 有内容直接发送
|
||
readyReplyComment(CommentModel? comment,
|
||
{ReplyModel? replyModel, bool? isSend}) async {
|
||
replyComment = comment;
|
||
replyCommentModel = replyModel;
|
||
if (replyModel != null) {
|
||
hintText = '回复:${replyModel.userName ?? ''}';
|
||
}
|
||
if (comment != null && hintText == null) {
|
||
hintText = '回复:${comment.userName ?? ''}';
|
||
}
|
||
if (isSend == true && commentController.text.isNotEmpty) {
|
||
update();
|
||
sendComment();
|
||
} else {
|
||
final result = await Get.bottomSheet(
|
||
CommentInputView(
|
||
hint: hintText,
|
||
textCtr: commentController,
|
||
imgPath: selectedImagePath.value,
|
||
onImgChange: (value) => selectedImagePath.value = value,
|
||
),
|
||
backgroundColor: Colors.transparent,
|
||
barrierColor: Colors.transparent,
|
||
enableDrag: false,
|
||
settings: RouteSettings(name: CommentInputView.routeName),
|
||
useRootNavigator: true,
|
||
);
|
||
if (result == true) {
|
||
update();
|
||
sendComment();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取评论
|
||
Future fetchComments(String id, {bool isRefresh = false}) async {
|
||
try {
|
||
if (isRefresh) {
|
||
page = 1;
|
||
}
|
||
final currentT = DateTimeUtil.format2utc(DateTime.now()) ?? "";
|
||
final result =
|
||
await CommentService.getCommentList(id, currentT, page, 20);
|
||
totalCallback?.call(result?.total ?? 0);
|
||
refreshCtr?.refreshCompleted();
|
||
refreshCtr?.loadComplete();
|
||
if (!(result?.hasNext ?? false)) {
|
||
refreshCtr?.loadNoData();
|
||
}
|
||
if (page == 1) {
|
||
comments.clear();
|
||
quickSearchList.clear();
|
||
// 首屏并行拉置顶 Banner;失败不影响评论列表
|
||
_fetchCommentTopBanners();
|
||
}
|
||
comments.addAll(result?.list ?? []);
|
||
if (page == 1) {
|
||
quickSearchList.addAll(result?.quickSearchList ?? []);
|
||
}
|
||
page += 1;
|
||
for (final e in comments) {
|
||
e.hasMoreReply = (e.commCount ?? 0) > (e.replies?.length ?? 0);
|
||
}
|
||
} catch (e) {
|
||
refreshCtr?.refreshCompleted();
|
||
refreshCtr?.loadComplete();
|
||
debugLog(e);
|
||
}
|
||
update();
|
||
}
|
||
|
||
/// 评论区置顶 Banner(scene=COMMENT_TOP)
|
||
Future<void> _fetchCommentTopBanners() async {
|
||
try {
|
||
final list = await CommonService.fetchBannerList(scene: 'COMMENT_TOP');
|
||
commentTopBanners
|
||
..clear()
|
||
..addAll(list);
|
||
update();
|
||
} catch (e) {
|
||
debugLog(e);
|
||
}
|
||
}
|
||
|
||
/// 首条置顶评论下标:官方评论或带内外链的置顶样式评论
|
||
int get topPinnedCommentIndex {
|
||
for (int i = 0; i < comments.length; i++) {
|
||
final c = comments[i];
|
||
if (c.isOfficial || c.isHideLikeOrComment) return i;
|
||
}
|
||
return -1;
|
||
}
|
||
}
|