feat: 完成情绪博物馆项目重构和功能增强 - 新增日记评论和帖子功能 - 重构前端架构,优化用户体验 - 完善WebSocket通信机制 - 更新项目文档和部署配置
This commit is contained in:
@@ -0,0 +1,290 @@
|
||||
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.BasePageRequest;
|
||||
import com.emotion.entity.DiaryComment;
|
||||
import com.emotion.mapper.DiaryCommentMapper;
|
||||
import com.emotion.service.DiaryCommentService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
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 ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public IPage<DiaryComment> getPage(BasePageRequest request) {
|
||||
Page<DiaryComment> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryComment::getIsTop)
|
||||
.orderByDesc(DiaryComment::getPublishTime);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<DiaryComment> getPageByDiaryId(String diaryId, BasePageRequest request) {
|
||||
Page<DiaryComment> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getDiaryId, diaryId)
|
||||
.eq(DiaryComment::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryComment::getIsTop)
|
||||
.orderByDesc(DiaryComment::getPublishTime);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<DiaryComment> getPageByUserId(String userId, BasePageRequest request) {
|
||||
Page<DiaryComment> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getUserId, userId)
|
||||
.eq(DiaryComment::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryComment::getPublishTime);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryComment> getByCommentType(String commentType) {
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getCommentType, commentType)
|
||||
.eq(DiaryComment::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryComment::getPublishTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryComment> getByDiaryIdAndCommentType(String diaryId, String commentType) {
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getDiaryId, diaryId)
|
||||
.eq(DiaryComment::getCommentType, commentType)
|
||||
.eq(DiaryComment::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryComment::getPublishTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incrementLikeCount(String commentId) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.setSql("like_count = like_count + 1");
|
||||
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)");
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incrementReplyCount(String commentId) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.setSql("reply_count = reply_count + 1");
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decrementReplyCount(String commentId) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.setSql("reply_count = GREATEST(reply_count - 1, 0)");
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateLastReplyTime(String commentId) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.set(DiaryComment::getLastReplyTime, 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);
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByDiaryId(String diaryId) {
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getDiaryId, diaryId)
|
||||
.eq(DiaryComment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByUserId(String userId) {
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getUserId, userId)
|
||||
.eq(DiaryComment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByCommentType(String commentType) {
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getCommentType, commentType)
|
||||
.eq(DiaryComment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countReplies(String parentCommentId) {
|
||||
LambdaQueryWrapper<DiaryComment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryComment::getParentCommentId, parentCommentId)
|
||||
.eq(DiaryComment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiaryComment createComment(String diaryId, String userId, String content, List<String> images,
|
||||
String parentCommentId, Integer isAnonymous) {
|
||||
DiaryComment comment = DiaryComment.builder()
|
||||
.diaryId(diaryId)
|
||||
.userId(userId)
|
||||
.content(content)
|
||||
.images(convertListToJson(images))
|
||||
.parentCommentId(parentCommentId)
|
||||
.commentType("user")
|
||||
.likeCount(0)
|
||||
.replyCount(0)
|
||||
.isAnonymous(isAnonymous)
|
||||
.isTop(0)
|
||||
.status("published")
|
||||
.publishTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
this.save(comment);
|
||||
|
||||
// 如果有父评论,更新父评论的回复数
|
||||
if (StringUtils.hasText(parentCommentId)) {
|
||||
this.incrementReplyCount(parentCommentId);
|
||||
this.updateLastReplyTime(parentCommentId);
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiaryComment createAiComment(String diaryId, String content, String aiCommentSource,
|
||||
BigDecimal emotionScore, BigDecimal sentimentScore) {
|
||||
DiaryComment comment = DiaryComment.builder()
|
||||
.diaryId(diaryId)
|
||||
.userId("system") // AI评论使用system用户ID
|
||||
.content(content)
|
||||
.commentType("ai")
|
||||
.aiCommentSource(aiCommentSource)
|
||||
.likeCount(0)
|
||||
.replyCount(0)
|
||||
.isAnonymous(0)
|
||||
.isTop(0)
|
||||
.status("published")
|
||||
.publishTime(LocalDateTime.now())
|
||||
.emotionScore(emotionScore)
|
||||
.sentimentScore(sentimentScore)
|
||||
.build();
|
||||
|
||||
this.save(comment);
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateComment(String commentId, String content, List<String> images) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.set(StringUtils.hasText(content), DiaryComment::getContent, content)
|
||||
.set(images != null, DiaryComment::getImages, convertListToJson(images));
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@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);
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreComment(String commentId) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.set(DiaryComment::getIsDeleted, 0);
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将List转换为JSON字符串
|
||||
*/
|
||||
private String convertListToJson(List<?> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.writeValueAsString(list);
|
||||
} catch (JsonProcessingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user