|
@@ -0,0 +1,257 @@
|
|
|
|
|
+package shop.alien.lawyer.service.impl;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson2.JSON;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
+import shop.alien.entity.result.R;
|
|
|
|
|
+import shop.alien.entity.store.LawyerConsultationOrder;
|
|
|
|
|
+import shop.alien.entity.store.OrderReview;
|
|
|
|
|
+import shop.alien.entity.store.ReviewComment;
|
|
|
|
|
+import shop.alien.entity.store.dto.OrderReviewDto;
|
|
|
|
|
+import shop.alien.entity.store.vo.OrderReviewDetailVo;
|
|
|
|
|
+import shop.alien.entity.store.vo.OrderReviewVo;
|
|
|
|
|
+import shop.alien.lawyer.service.OrderReviewService;
|
|
|
|
|
+import shop.alien.lawyer.service.ReviewCommentService;
|
|
|
|
|
+import shop.alien.mapper.*;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.Date;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 订单评价 服务实现类
|
|
|
|
|
+ *
|
|
|
|
|
+ * @author system
|
|
|
|
|
+ * @since 2025-01-XX
|
|
|
|
|
+ */
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@Transactional
|
|
|
|
|
+@Service
|
|
|
|
|
+@RequiredArgsConstructor
|
|
|
|
|
+public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, OrderReview> implements OrderReviewService {
|
|
|
|
|
+
|
|
|
|
|
+ private final OrderReviewMapper orderReviewMapper;
|
|
|
|
|
+ private final LawyerConsultationOrderMapper lawyerConsultationOrderMapper;
|
|
|
|
|
+ private final ReviewCommentService reviewCommentService;
|
|
|
|
|
+ private final ReviewCommentMapper reviewCommentMapper;
|
|
|
|
|
+ private final CommentReplyMapper commentReplyMapper;
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public R<OrderReview> createReview(OrderReviewDto reviewDto, Integer userId) {
|
|
|
|
|
+ log.info("OrderReviewServiceImpl.createReview?reviewDto={}, userId={}", reviewDto, userId);
|
|
|
|
|
+
|
|
|
|
|
+ // 参数校验
|
|
|
|
|
+ if (reviewDto == null) {
|
|
|
|
|
+ return R.fail("评价信息不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (reviewDto.getOrderId() == null) {
|
|
|
|
|
+ return R.fail("订单ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return R.fail("用户ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证订单是否存在且属于该用户
|
|
|
|
|
+ LawyerConsultationOrder order = lawyerConsultationOrderMapper.selectById(reviewDto.getOrderId());
|
|
|
|
|
+ if (order == null) {
|
|
|
|
|
+ return R.fail("订单不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!order.getClientUserId().equals(userId)) {
|
|
|
|
|
+ return R.fail("只能评价自己的订单");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查订单是否已完成
|
|
|
|
|
+ if (order.getOrderStatus() == null || order.getOrderStatus() != 3) {
|
|
|
|
|
+ return R.fail("只能对已完成的订单进行评价");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否已经评价过
|
|
|
|
|
+ LambdaQueryWrapper<OrderReview> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ queryWrapper.eq(OrderReview::getOrderId, reviewDto.getOrderId())
|
|
|
|
|
+ .eq(OrderReview::getDeleteFlag, 0);
|
|
|
|
|
+ OrderReview existingReview = this.getOne(queryWrapper);
|
|
|
|
|
+ if (existingReview != null) {
|
|
|
|
|
+ return R.fail("该订单已经评价过了");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 创建评价
|
|
|
|
|
+ OrderReview review = new OrderReview();
|
|
|
|
|
+ review.setOrderId(reviewDto.getOrderId());
|
|
|
|
|
+ review.setOrderNumber(reviewDto.getOrderNumber());
|
|
|
|
|
+ review.setUserId(userId);
|
|
|
|
|
+ review.setLawyerUserId(order.getLawyerUserId());
|
|
|
|
|
+ review.setOverallRating(reviewDto.getOverallRating());
|
|
|
|
|
+ review.setServiceAttitudeRating(reviewDto.getServiceAttitudeRating());
|
|
|
|
|
+ review.setResponseTimeRating(reviewDto.getResponseTimeRating());
|
|
|
|
|
+ review.setProfessionalAbilityRating(reviewDto.getProfessionalAbilityRating());
|
|
|
|
|
+ review.setReviewContent(reviewDto.getReviewContent());
|
|
|
|
|
+
|
|
|
|
|
+ // 处理评价图片
|
|
|
|
|
+ if (reviewDto.getReviewImages() != null && !reviewDto.getReviewImages().isEmpty()) {
|
|
|
|
|
+ review.setReviewImages(JSON.toJSONString(reviewDto.getReviewImages()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ review.setIsAnonymous(reviewDto.getIsAnonymous() != null ? reviewDto.getIsAnonymous() : 0);
|
|
|
|
|
+ review.setLikeCount(0);
|
|
|
|
|
+ review.setCommentCount(0);
|
|
|
|
|
+ review.setCreatedUserId(userId);
|
|
|
|
|
+ review.setCreatedTime(new Date());
|
|
|
|
|
+
|
|
|
|
|
+ boolean success = this.save(review);
|
|
|
|
|
+ if (success) {
|
|
|
|
|
+ log.info("创建评价成功,评价ID={}", review.getId());
|
|
|
|
|
+ return R.data(review, "评价成功");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.error("创建评价失败");
|
|
|
|
|
+ return R.fail("创建评价失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public R<IPage<OrderReviewVo>> getReviewList(int pageNum, int pageSize, Integer orderId, Integer lawyerUserId, Integer userId) {
|
|
|
|
|
+ log.info("OrderReviewServiceImpl.getReviewList?pageNum={}, pageSize={}, orderId={}, lawyerUserId={}, userId={}",
|
|
|
|
|
+ pageNum, pageSize, orderId, lawyerUserId, userId);
|
|
|
|
|
+
|
|
|
|
|
+ Page<OrderReviewVo> page = new Page<>(pageNum, pageSize);
|
|
|
|
|
+ IPage<OrderReviewVo> result = orderReviewMapper.getReviewListWithUser(page, orderId, lawyerUserId, userId);
|
|
|
|
|
+
|
|
|
|
|
+ // 处理评价图片JSON字符串转换为列表
|
|
|
|
|
+ if (result.getRecords() != null) {
|
|
|
|
|
+ for (OrderReviewVo vo : result.getRecords()) {
|
|
|
|
|
+ if (vo.getReviewImages() != null && !vo.getReviewImages().isEmpty()) {
|
|
|
|
|
+ // 如果已经是列表,则不需要转换
|
|
|
|
|
+ // 这里假设VO中的reviewImages已经是List<String>类型
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return R.data(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public R<OrderReviewDetailVo> getReviewDetail(Integer reviewId) {
|
|
|
|
|
+ log.info("OrderReviewServiceImpl.getReviewDetail?reviewId={}", reviewId);
|
|
|
|
|
+
|
|
|
|
|
+ if (reviewId == null) {
|
|
|
|
|
+ return R.fail("评价ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询评价详情
|
|
|
|
|
+ OrderReviewVo reviewVo = orderReviewMapper.getReviewDetailById(reviewId);
|
|
|
|
|
+ if (reviewVo == null) {
|
|
|
|
|
+ return R.fail("评价不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理评价图片
|
|
|
|
|
+ OrderReview review = this.getById(reviewId);
|
|
|
|
|
+ if (review != null && review.getReviewImages() != null) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ List<String> images = JSON.parseArray(review.getReviewImages(), String.class);
|
|
|
|
|
+ reviewVo.setReviewImages(images);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("解析评价图片失败:{}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询评论列表
|
|
|
|
|
+ List<shop.alien.entity.store.vo.ReviewCommentVo> comments = reviewCommentMapper.getCommentListByReviewId(reviewId);
|
|
|
|
|
+
|
|
|
|
|
+ // 构建返回结果
|
|
|
|
|
+ OrderReviewDetailVo detailVo = new OrderReviewDetailVo();
|
|
|
|
|
+ detailVo.setReview(reviewVo);
|
|
|
|
|
+ detailVo.setComments(comments);
|
|
|
|
|
+ detailVo.setTotalCommentCount(comments != null ? comments.size() : 0);
|
|
|
|
|
+
|
|
|
|
|
+ return R.data(detailVo);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public R<Boolean> deleteReview(Integer reviewId, Integer userId) {
|
|
|
|
|
+ log.info("OrderReviewServiceImpl.deleteReview?reviewId={}, userId={}", reviewId, userId);
|
|
|
|
|
+
|
|
|
|
|
+ if (reviewId == null) {
|
|
|
|
|
+ return R.fail("评价ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return R.fail("用户ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询评价
|
|
|
|
|
+ OrderReview review = this.getById(reviewId);
|
|
|
|
|
+ if (review == null) {
|
|
|
|
|
+ return R.fail("评价不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证是否为评价用户
|
|
|
|
|
+ if (!review.getUserId().equals(userId)) {
|
|
|
|
|
+ return R.fail("只能删除自己的评价");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询该评价下的所有评论
|
|
|
|
|
+ LambdaQueryWrapper<ReviewComment> commentWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ commentWrapper.eq(ReviewComment::getReviewId, reviewId)
|
|
|
|
|
+ .eq(ReviewComment::getDeleteFlag, 0);
|
|
|
|
|
+ List<ReviewComment> comments = reviewCommentService.list(commentWrapper);
|
|
|
|
|
+
|
|
|
|
|
+ // 删除评价(逻辑删除)
|
|
|
|
|
+ review.setDeleteFlag(1);
|
|
|
|
|
+ review.setUpdatedUserId(userId);
|
|
|
|
|
+ review.setUpdatedTime(new Date());
|
|
|
|
|
+ boolean success = this.updateById(review);
|
|
|
|
|
+
|
|
|
|
|
+ if (success) {
|
|
|
|
|
+ // 级联删除该评价下的所有评论和回复
|
|
|
|
|
+ for (ReviewComment comment : comments) {
|
|
|
|
|
+ // 删除评论下的所有回复
|
|
|
|
|
+ commentReplyMapper.deleteRepliesByCommentId(comment.getId());
|
|
|
|
|
+
|
|
|
|
|
+ // 删除评论
|
|
|
|
|
+ comment.setDeleteFlag(1);
|
|
|
|
|
+ comment.setUpdatedUserId(userId);
|
|
|
|
|
+ comment.setUpdatedTime(new Date());
|
|
|
|
|
+ reviewCommentService.updateById(comment);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("删除评价成功,评价ID={}", reviewId);
|
|
|
|
|
+ return R.data(true, "删除成功");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.error("删除评价失败,评价ID={}", reviewId);
|
|
|
|
|
+ return R.fail("删除评价失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public R<OrderReviewVo> getReviewByOrderId(Integer orderId) {
|
|
|
|
|
+ log.info("OrderReviewServiceImpl.getReviewByOrderId?orderId={}", orderId);
|
|
|
|
|
+
|
|
|
|
|
+ if (orderId == null) {
|
|
|
|
|
+ return R.fail("订单ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ OrderReviewVo reviewVo = orderReviewMapper.getReviewByOrderId(orderId);
|
|
|
|
|
+ if (reviewVo == null) {
|
|
|
|
|
+ return R.fail("该订单暂无评价");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理评价图片
|
|
|
|
|
+ OrderReview review = this.getOne(new LambdaQueryWrapper<OrderReview>()
|
|
|
|
|
+ .eq(OrderReview::getOrderId, orderId)
|
|
|
|
|
+ .eq(OrderReview::getDeleteFlag, 0));
|
|
|
|
|
+ if (review != null && review.getReviewImages() != null) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ List<String> images = JSON.parseArray(review.getReviewImages(), String.class);
|
|
|
|
|
+ reviewVo.setReviewImages(images);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("解析评价图片失败:{}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return R.data(reviewVo);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|