322 lines
12 KiB
Java
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;
|
|
}
|
|
}
|
|
} |