feat: 完成情绪博物馆项目重构和功能增强 - 新增日记评论和帖子功能 - 重构前端架构,优化用户体验 - 完善WebSocket通信机制 - 更新项目文档和部署配置

This commit is contained in:
2025-07-27 10:05:59 +08:00
parent 6903ac1c0d
commit cc886cd4d5
126 changed files with 21179 additions and 15734 deletions
@@ -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;
}
}
}