Files
happy-life-star/backend-single/src/main/java/com/emotion/service/impl/DiaryCommentServiceImpl.java
T
2025-09-08 17:54:12 +08:00

322 lines
12 KiB
Java

package com.emotion.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.emotion.common.PageResult;
import com.emotion.dto.request.DiaryCommentCreateRequest;
import com.emotion.dto.request.DiaryCommentPageRequest;
import com.emotion.dto.response.DiaryCommentResponse;
import com.emotion.entity.DiaryComment;
import com.emotion.mapper.DiaryCommentMapper;
import com.emotion.service.DiaryCommentService;
import com.emotion.util.SnowflakeIdGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* 日记评论服务实现类
*
* @author emotion-museum
* @date 2025-07-23
*/
@Service
public class DiaryCommentServiceImpl extends ServiceImpl<DiaryCommentMapper, DiaryComment> implements DiaryCommentService {
@Autowired
private SnowflakeIdGenerator snowflakeIdGenerator;
@Autowired
private ObjectMapper objectMapper;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public PageResult<DiaryCommentResponse> getPageWithResponse(DiaryCommentPageRequest request) {
Page<DiaryComment> page = new Page<>(request.getCurrent(), request.getSize());
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
// 基础查询条件
wrapper.eq(DiaryComment::getIsDeleted, 0);
// 根据请求参数添加查询条件
if (StringUtils.hasText(request.getDiaryId())) {
wrapper.eq(DiaryComment::getDiaryId, request.getDiaryId());
}
if (StringUtils.hasText(request.getUserId())) {
wrapper.eq(DiaryComment::getUserId, request.getUserId());
}
if (StringUtils.hasText(request.getCommentType())) {
wrapper.eq(DiaryComment::getCommentType, request.getCommentType());
}
if (request.getTopLevelOnly() != null && request.getTopLevelOnly()) {
wrapper.isNull(DiaryComment::getParentCommentId);
}
// 排序
wrapper.orderByDesc(DiaryComment::getIsTop)
.orderByDesc(DiaryComment::getPublishTime);
IPage<DiaryComment> resultPage = this.page(page, wrapper);
return convertPageToResponse(resultPage);
}
@Override
public DiaryCommentResponse getCommentResponseById(String id) {
DiaryComment comment = this.getById(id);
if (comment == null) {
return null;
}
return convertToResponse(comment);
}
@Override
public List<DiaryCommentResponse> getCommentTreeWithResponse(String diaryId) {
List<DiaryComment> comments = this.getCommentTree(diaryId);
return comments.stream()
.map(this::convertToResponse)
.collect(Collectors.toList());
}
@Override
public DiaryCommentResponse createCommentWithResponse(DiaryCommentCreateRequest request) {
DiaryComment comment = DiaryComment.builder()
.id(snowflakeIdGenerator.nextIdAsString()) // 使用雪花算法生成ID
.diaryId(request.getDiaryId())
.userId(request.getUserId())
.content(request.getContent())
.images(convertListToJson(request.getImages()))
.parentCommentId(request.getParentCommentId())
.commentType("user")
.likeCount(0)
.replyCount(0)
.isAnonymous(request.getIsAnonymous())
.isTop(0)
.status("published")
.publishTime(LocalDateTime.now())
.build();
this.save(comment);
// 如果有父评论,更新父评论的回复数
if (StringUtils.hasText(request.getParentCommentId())) {
this.incrementReplyCount(request.getParentCommentId());
this.updateLastReplyTime(request.getParentCommentId());
}
return convertToResponse(comment);
}
@Override
public DiaryCommentResponse updateCommentWithResponse(DiaryCommentCreateRequest request) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, request.getId())
.set(StringUtils.hasText(request.getContent()), DiaryComment::getContent, request.getContent())
.set(request.getImages() != null, DiaryComment::getImages, convertListToJson(request.getImages()))
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
boolean updated = this.update(wrapper);
if (!updated) {
return null;
}
DiaryComment updatedComment = this.getById(request.getId());
return updatedComment != null ? convertToResponse(updatedComment) : null;
}
@Override
public boolean deleteComment(String commentId) {
return this.removeById(commentId);
}
@Override
public boolean softDeleteComment(String commentId) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.set(DiaryComment::getIsDeleted, 1)
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
@Override
public boolean restoreComment(String commentId) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.set(DiaryComment::getIsDeleted, 0)
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
@Override
public boolean incrementLikeCount(String commentId) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.setSql("like_count = like_count + 1")
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
@Override
public boolean decrementLikeCount(String commentId) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.setSql("like_count = GREATEST(like_count - 1, 0)")
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
@Override
public boolean setTop(String commentId, Integer isTop) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.set(DiaryComment::getIsTop, isTop)
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
/**
* 获取评论树结构
*/
private List<DiaryComment> getCommentTree(String diaryId) {
// 获取所有顶级评论(没有父评论的评论)
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(DiaryComment::getDiaryId, diaryId)
.isNull(DiaryComment::getParentCommentId)
.eq(DiaryComment::getIsDeleted, 0)
.orderByDesc(DiaryComment::getIsTop)
.orderByDesc(DiaryComment::getPublishTime);
List<DiaryComment> topComments = this.list(wrapper);
// 为每个顶级评论加载回复
return topComments.stream()
.peek(comment -> {
List<DiaryComment> replies = getRepliesByParentId(comment.getId());
// 这里可以递归加载更深层的回复,但为了性能考虑,通常只加载一层
})
.collect(Collectors.toList());
}
/**
* 根据父评论ID查询回复列表
*/
private List<DiaryComment> getRepliesByParentId(String parentCommentId) {
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(DiaryComment::getParentCommentId, parentCommentId)
.eq(DiaryComment::getIsDeleted, 0)
.orderByAsc(DiaryComment::getPublishTime);
return this.list(wrapper);
}
/**
* 增加回复数
*/
private boolean incrementReplyCount(String commentId) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.setSql("reply_count = reply_count + 1")
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
/**
* 减少回复数
*/
private boolean decrementReplyCount(String commentId) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.setSql("reply_count = GREATEST(reply_count - 1, 0)")
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
/**
* 更新最后回复时间
*/
private boolean updateLastReplyTime(String commentId) {
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(DiaryComment::getId, commentId)
.set(DiaryComment::getLastReplyTime, LocalDateTime.now())
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
return this.update(wrapper);
}
/**
* 转换为响应对象
*/
private DiaryCommentResponse convertToResponse(DiaryComment comment) {
DiaryCommentResponse response = new DiaryCommentResponse();
BeanUtils.copyProperties(comment, response);
// 转换时间格式
if (comment.getPublishTime() != null) {
response.setPublishTime(comment.getPublishTime().format(DATE_TIME_FORMATTER));
}
if (comment.getLastReplyTime() != null) {
response.setLastReplyTime(comment.getLastReplyTime().format(DATE_TIME_FORMATTER));
}
if (comment.getCreateTime() != null) {
response.setCreateTime(comment.getCreateTime().format(DATE_TIME_FORMATTER));
}
if (comment.getUpdateTime() != null) {
response.setUpdateTime(comment.getUpdateTime().format(DATE_TIME_FORMATTER));
}
// 转换JSON字段
try {
if (comment.getImages() != null) {
response.setImages(objectMapper.readValue(comment.getImages(), new TypeReference<List<String>>() {
}));
}
if (comment.getMetadata() != null) {
response.setMetadata(objectMapper.readValue(comment.getMetadata(), Object.class));
}
} catch (JsonProcessingException e) {
// 忽略JSON解析错误
}
return response;
}
/**
* 转换分页对象为响应对象
*/
private PageResult<DiaryCommentResponse> convertPageToResponse(IPage<DiaryComment> page) {
PageResult<DiaryCommentResponse> responsePage = new PageResult<>();
responsePage.setCurrent(page.getCurrent());
responsePage.setSize(page.getSize());
responsePage.setTotal(page.getTotal());
responsePage.setPages(page.getPages());
responsePage.setRecords(
page.getRecords().stream()
.map(this::convertToResponse)
.collect(Collectors.toList()));
return responsePage;
}
/**
* 将List转换为JSON字符串
*/
private String convertListToJson(List<?> list) {
if (list == null || list.isEmpty()) {
return null;
}
try {
return objectMapper.writeValueAsString(list);
} catch (JsonProcessingException e) {
return null;
}
}
}