Files
2026-09-15 15:44:13 +07:00

213 lines
6.4 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
/// 评论区置顶 Bannerscene=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;
}
}