|
|
@@ -21,6 +21,7 @@ import shop.alien.entity.result.R;
|
|
|
import shop.alien.entity.store.*;
|
|
|
import shop.alien.entity.store.vo.CommonCommentVo;
|
|
|
import shop.alien.entity.store.vo.CommonRatingVo;
|
|
|
+import shop.alien.entity.store.vo.RatingPercentVo;
|
|
|
import shop.alien.entity.store.vo.StoreInfoScoreVo;
|
|
|
import shop.alien.entity.store.vo.WebSocketVo;
|
|
|
import shop.alien.mapper.*;
|
|
|
@@ -155,22 +156,6 @@ public class CommonRatingServiceImpl extends ServiceImpl<CommonRatingMapper, Com
|
|
|
}
|
|
|
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * 分页查询评价列表
|
|
|
- *
|
|
|
- * @param pageNum 页数
|
|
|
- * @param pageSize 页容
|
|
|
- * @param businessType 业务类型:1-店铺评价
|
|
|
- * @param businessId 业务关联ID
|
|
|
- * @param userId 用户ID
|
|
|
- * @param auditStatus 审核状态:0-待审核 1-通过 2-驳回
|
|
|
- * @param searchScore 搜索评分:0-全部,1-好评 2-中评 3-差评,4-有图
|
|
|
- * @param days 查询时间, 多少天前
|
|
|
- * @param replyStatus 回复状态(0:全部, 1:已回复, 2:未回复)
|
|
|
- * @param tagId 标签id
|
|
|
- * @return R
|
|
|
- */
|
|
|
@Override
|
|
|
public R getRatingList(Integer pageNum, Integer pageSize, Integer businessType, Long businessId, Long userId, Integer auditStatus, Integer searchScore, Integer days, Integer replyStatus, Integer tagId) {
|
|
|
Page<CommonRating> page = new Page<>(pageNum, pageSize);
|
|
|
@@ -307,14 +292,10 @@ public class CommonRatingServiceImpl extends ServiceImpl<CommonRatingMapper, Com
|
|
|
ratingCount = commonRatingMapper.getRatingCount(new QueryWrapper<CommonRating>().in("id", collect));
|
|
|
|
|
|
// 计算好评、中评、差评占比
|
|
|
- // 注意:数据库返回的 count 可能是 Long 类型,需要安全转换
|
|
|
- Long goodCountLong = (Long) ratingCount.getOrDefault("goodCount", 0L);
|
|
|
- Long midCountLong = (Long) ratingCount.getOrDefault("midCount", 0L);
|
|
|
- Long badCountLong = (Long) ratingCount.getOrDefault("badCount", 0L);
|
|
|
-
|
|
|
- int goodCount = goodCountLong != null ? goodCountLong.intValue() : 0;
|
|
|
- int midCount = midCountLong != null ? midCountLong.intValue() : 0;
|
|
|
- int badCount = badCountLong != null ? badCountLong.intValue() : 0;
|
|
|
+ // 注意:数据库返回的 count 可能是 BigDecimal、Long 或 Integer 类型,需要安全转换
|
|
|
+ int goodCount = getIntValue(ratingCount.get("goodCount"));
|
|
|
+ int midCount = getIntValue(ratingCount.get("midCount"));
|
|
|
+ int badCount = getIntValue(ratingCount.get("badCount"));
|
|
|
int totalCount = goodCount + midCount + badCount;
|
|
|
|
|
|
if (totalCount > 0) {
|
|
|
@@ -585,6 +566,38 @@ public class CommonRatingServiceImpl extends ServiceImpl<CommonRatingMapper, Com
|
|
|
Map<Long, Long> ratingCommentCountMap = allComments.stream()
|
|
|
.collect(Collectors.groupingBy(CommonComment::getSourceId, Collectors.counting()));
|
|
|
|
|
|
+ // 查询每个评价的最新一条商户回复(comment_type=2, parent_id=0)
|
|
|
+ Map<Long, CommonCommentVo> latestMerchantReplyMap = new HashMap<>();
|
|
|
+ if (!ratingIdSet.isEmpty()) {
|
|
|
+ QueryWrapper<CommonCommentVo> merchantReplyWrapper = new QueryWrapper<>();
|
|
|
+ merchantReplyWrapper.eq("cc.source_type", CommentSourceTypeEnum.STORE_COMMENT.getType())
|
|
|
+ .in("cc.source_id", ratingIdSet)
|
|
|
+ .eq("cc.comment_type", 2) // 商户评论
|
|
|
+ .eq("cc.parent_id", 0) // 直接回复评价的根评论
|
|
|
+ .eq("cc.is_show", 1)
|
|
|
+ .eq("cc.audit_status", 1)
|
|
|
+ .eq("cc.delete_flag", 0)
|
|
|
+ .orderByDesc("cc.created_time");
|
|
|
+
|
|
|
+ // 查询所有商户回复(包含用户信息)
|
|
|
+ List<CommonCommentVo> merchantReplies = commonCommentMapper.selectALlComment(
|
|
|
+ merchantReplyWrapper,
|
|
|
+ CommonConstant.COMMENT_LIKE,
|
|
|
+ userId != null ? userId : 0L
|
|
|
+ );
|
|
|
+
|
|
|
+ // 按评价ID分组,每组只取最新的一条(已按时间倒序排序)
|
|
|
+ if (CollectionUtils.isNotEmpty(merchantReplies)) {
|
|
|
+ for (CommonCommentVo reply : merchantReplies) {
|
|
|
+ Long ratingId = reply.getSourceId();
|
|
|
+ // 如果该评价还没有设置回复,则设置(因为已经按时间倒序,第一条就是最新的)
|
|
|
+ if (ratingId != null && !latestMerchantReplyMap.containsKey(ratingId)) {
|
|
|
+ latestMerchantReplyMap.put(ratingId, reply);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 4. 组装评价列表数据
|
|
|
for (CommonRating record : page1.getRecords()) {
|
|
|
CommonRatingVo commonRatingVo = new CommonRatingVo();
|
|
|
@@ -606,6 +619,16 @@ public class CommonRatingServiceImpl extends ServiceImpl<CommonRatingMapper, Com
|
|
|
// 设置评论数
|
|
|
commonRatingVo.setCommentCount(ratingCommentCountMap.getOrDefault(record.getId(), 0L));
|
|
|
|
|
|
+ // 设置商户最新回复(同一评价下,商家只显示最新的一条回复)
|
|
|
+ CommonCommentVo latestMerchantReply = latestMerchantReplyMap.get(record.getId());
|
|
|
+ if (latestMerchantReply != null) {
|
|
|
+ // 只设置一条最新的商户回复
|
|
|
+ commonRatingVo.setChildCommonComments(Collections.singletonList(latestMerchantReply));
|
|
|
+ } else {
|
|
|
+ // 没有商户回复,设置为空列表
|
|
|
+ commonRatingVo.setChildCommonComments(new ArrayList<>());
|
|
|
+ }
|
|
|
+
|
|
|
resultList.add(commonRatingVo);
|
|
|
}
|
|
|
|
|
|
@@ -643,5 +666,134 @@ public class CommonRatingServiceImpl extends ServiceImpl<CommonRatingMapper, Com
|
|
|
|
|
|
return (long) this.count(wrapper);
|
|
|
}*/
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 安全地将数据库返回的数值类型转换为 int
|
|
|
+ * 支持 BigDecimal、Long、Integer、Number 等类型
|
|
|
+ *
|
|
|
+ * @param value 数据库返回的数值对象
|
|
|
+ * @return int 值,如果为 null 或无法转换则返回 0
|
|
|
+ */
|
|
|
+ private int getIntValue(Object value) {
|
|
|
+ if (value == null) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (value instanceof Number) {
|
|
|
+ return ((Number) value).intValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 尝试字符串转换
|
|
|
+ try {
|
|
|
+ if (value instanceof String) {
|
|
|
+ return Integer.parseInt((String) value);
|
|
|
+ }
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ log.warn("无法将值转换为 int: {}", value, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取回复率和评价比例
|
|
|
+ *
|
|
|
+ * @param businessId 业务ID(店铺ID)
|
|
|
+ * @param businessType 业务类型:1-店铺评价
|
|
|
+ * @return 回复率和评价比例信息
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public RatingPercentVo getRatingPercent(Integer businessId, Integer businessType) {
|
|
|
+ log.info("CommonRatingServiceImpl.getRatingPercent?businessId={}&businessType={}", businessId, businessType);
|
|
|
+
|
|
|
+ RatingPercentVo vo = new RatingPercentVo();
|
|
|
+
|
|
|
+ // 1. 查询全部评价记录(仅展示的、审核通过的)
|
|
|
+ LambdaQueryWrapper<CommonRating> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(CommonRating::getBusinessId, businessId);
|
|
|
+ wrapper.eq(CommonRating::getBusinessType, businessType);
|
|
|
+ wrapper.eq(CommonRating::getIsShow, 1);
|
|
|
+ wrapper.eq(CommonRating::getAuditStatus, 1); // 仅统计审核通过的
|
|
|
+ List<CommonRating> commonRatings = commonRatingMapper.selectList(wrapper);
|
|
|
+
|
|
|
+ // 如果为空,返回默认值
|
|
|
+ if (CollectionUtils.isEmpty(commonRatings)) {
|
|
|
+ vo.setTotalRatingCount(0);
|
|
|
+ vo.setGoodCount(0);
|
|
|
+ vo.setMidCount(0);
|
|
|
+ vo.setBadCount(0);
|
|
|
+ vo.setGoodPercent(0.0);
|
|
|
+ vo.setMidPercent(0.0);
|
|
|
+ vo.setBadPercent(0.0);
|
|
|
+ vo.setRepliedCount(0);
|
|
|
+ vo.setReplyRate(0.0);
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> ratingIdList = commonRatings.stream()
|
|
|
+ .map(CommonRating::getId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 2. 获取评价统计信息(好评、中评、差评数量)
|
|
|
+ Map<String, Object> ratingCount = commonRatingMapper.getRatingCount(
|
|
|
+ new QueryWrapper<CommonRating>().in("id", ratingIdList));
|
|
|
+
|
|
|
+ // 3. 计算好评、中评、差评数量和占比
|
|
|
+ int goodCount = getIntValue(ratingCount.get("goodCount"));
|
|
|
+ int midCount = getIntValue(ratingCount.get("midCount"));
|
|
|
+ int badCount = getIntValue(ratingCount.get("badCount"));
|
|
|
+ int totalCount = goodCount + midCount + badCount;
|
|
|
+
|
|
|
+ vo.setTotalRatingCount(totalCount);
|
|
|
+ vo.setGoodCount(goodCount);
|
|
|
+ vo.setMidCount(midCount);
|
|
|
+ vo.setBadCount(badCount);
|
|
|
+
|
|
|
+ // 计算占比(保留2位小数)
|
|
|
+ if (totalCount > 0) {
|
|
|
+ Double goodPercent = Math.round((goodCount * 100.0 / totalCount) * 100.0) / 100.0;
|
|
|
+ Double midPercent = Math.round((midCount * 100.0 / totalCount) * 100.0) / 100.0;
|
|
|
+ Double badPercent = Math.round((badCount * 100.0 / totalCount) * 100.0) / 100.0;
|
|
|
+
|
|
|
+ vo.setGoodPercent(goodPercent);
|
|
|
+ vo.setMidPercent(midPercent);
|
|
|
+ vo.setBadPercent(badPercent);
|
|
|
+ } else {
|
|
|
+ vo.setGoodPercent(0.0);
|
|
|
+ vo.setMidPercent(0.0);
|
|
|
+ vo.setBadPercent(0.0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 计算回复率
|
|
|
+ // 查询已回复的评价数(存在商户评论 comment_type=2, parent_id=0)
|
|
|
+ LambdaQueryWrapper<CommonComment> repliedWrapper = new LambdaQueryWrapper<>();
|
|
|
+ repliedWrapper.eq(CommonComment::getSourceType, CommentSourceTypeEnum.STORE_COMMENT.getType())
|
|
|
+ .in(CommonComment::getSourceId, ratingIdList)
|
|
|
+ .eq(CommonComment::getCommentType, 2) // 商户评论
|
|
|
+ .eq(CommonComment::getParentId, 0) // 根评论(直接回复评价)
|
|
|
+ .eq(CommonComment::getIsShow, 1)
|
|
|
+ .eq(CommonComment::getAuditStatus, 1);
|
|
|
+
|
|
|
+ // 获取已回复的评价ID列表(去重)
|
|
|
+ Set<Long> repliedRatingIds = commonCommentMapper.selectList(repliedWrapper).stream()
|
|
|
+ .map(CommonComment::getSourceId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ int repliedCount = repliedRatingIds.size();
|
|
|
+ vo.setRepliedCount(repliedCount);
|
|
|
+
|
|
|
+ // 计算回复率(保留2位小数)
|
|
|
+ Double replyRate = 0.0;
|
|
|
+ if (totalCount > 0) {
|
|
|
+ replyRate = Math.round((repliedCount * 100.0 / totalCount) * 100.0) / 100.0;
|
|
|
+ }
|
|
|
+ vo.setReplyRate(replyRate);
|
|
|
+
|
|
|
+ log.info("CommonRatingServiceImpl.getRatingPercent result: totalCount={}, goodCount={}, midCount={}, badCount={}, repliedCount={}, replyRate={}%",
|
|
|
+ totalCount, goodCount, midCount, badCount, repliedCount, replyRate);
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
}
|
|
|
|