接口优化
This commit is contained in:
@@ -5,27 +5,41 @@ 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.common.PageResult;
|
||||
import com.emotion.dto.request.achievement.AchievementCreateRequest;
|
||||
import com.emotion.dto.request.achievement.AchievementPageRequest;
|
||||
import com.emotion.dto.request.achievement.AchievementUpdateRequest;
|
||||
import com.emotion.dto.response.achievement.AchievementResponse;
|
||||
import com.emotion.entity.Achievement;
|
||||
import com.emotion.mapper.AchievementMapper;
|
||||
import com.emotion.service.AchievementService;
|
||||
import com.emotion.util.SnowflakeIdGenerator;
|
||||
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
|
||||
* @date 2025-09-08
|
||||
*/
|
||||
@Service
|
||||
public class AchievementServiceImpl extends ServiceImpl<AchievementMapper, Achievement> implements AchievementService {
|
||||
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<Achievement> getPage(BasePageRequest request) {
|
||||
public IPage<Achievement> getPage(AchievementPageRequest request) {
|
||||
Page<Achievement> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
@@ -35,6 +49,30 @@ public class AchievementServiceImpl extends ServiceImpl<AchievementMapper, Achie
|
||||
.or().like(Achievement::getDescription, request.getKeyword()));
|
||||
}
|
||||
|
||||
// 分类筛选
|
||||
if (StringUtils.hasText(request.getCategory())) {
|
||||
wrapper.eq(Achievement::getCategory, request.getCategory());
|
||||
}
|
||||
|
||||
// 稀有度筛选
|
||||
if (StringUtils.hasText(request.getRarity())) {
|
||||
wrapper.eq(Achievement::getRarity, request.getRarity());
|
||||
}
|
||||
|
||||
// 解锁状态筛选
|
||||
if (request.getUnlocked() != null) {
|
||||
if (request.getUnlocked()) {
|
||||
wrapper.isNotNull(Achievement::getUnlockedTime);
|
||||
} else {
|
||||
wrapper.isNull(Achievement::getUnlockedTime);
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏状态筛选
|
||||
if (request.getHidden() != null) {
|
||||
wrapper.eq(Achievement::getIsHidden, request.getHidden() ? 1 : 0);
|
||||
}
|
||||
|
||||
wrapper.eq(Achievement::getIsDeleted, 0);
|
||||
|
||||
// 排序
|
||||
@@ -256,4 +294,147 @@ public class AchievementServiceImpl extends ServiceImpl<AchievementMapper, Achie
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增的Response相关方法实现
|
||||
|
||||
@Override
|
||||
public PageResult<AchievementResponse> getPageWithResponse(AchievementPageRequest request) {
|
||||
IPage<Achievement> page = getPage(request);
|
||||
List<AchievementResponse> responses = page.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
PageResult<AchievementResponse> pageResult = new PageResult<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setRecords(responses);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AchievementResponse getAchievementResponseById(String id) {
|
||||
Achievement achievement = this.getById(id);
|
||||
if (achievement == null) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(achievement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AchievementResponse createAchievementWithResponse(AchievementCreateRequest request) {
|
||||
Achievement achievement = new Achievement();
|
||||
org.springframework.beans.BeanUtils.copyProperties(request, achievement);
|
||||
achievement.setId(snowflakeIdGenerator.nextIdAsString());
|
||||
|
||||
boolean saved = this.save(achievement);
|
||||
if (!saved) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(achievement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AchievementResponse updateAchievementWithResponse(AchievementUpdateRequest request) {
|
||||
Achievement achievement = this.getById(request.getId());
|
||||
if (achievement == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 更新非空字段
|
||||
if (request.getTitle() != null) {
|
||||
achievement.setTitle(request.getTitle());
|
||||
}
|
||||
if (request.getDescription() != null) {
|
||||
achievement.setDescription(request.getDescription());
|
||||
}
|
||||
if (request.getCategory() != null) {
|
||||
achievement.setCategory(request.getCategory());
|
||||
}
|
||||
if (request.getIcon() != null) {
|
||||
achievement.setIcon(request.getIcon());
|
||||
}
|
||||
if (request.getRarity() != null) {
|
||||
achievement.setRarity(request.getRarity());
|
||||
}
|
||||
if (request.getConditionType() != null) {
|
||||
achievement.setConditionType(request.getConditionType());
|
||||
}
|
||||
if (request.getConditionValue() != null) {
|
||||
achievement.setConditionValue(request.getConditionValue());
|
||||
}
|
||||
if (request.getRewards() != null) {
|
||||
achievement.setRewards(request.getRewards());
|
||||
}
|
||||
if (request.getIsHidden() != null) {
|
||||
achievement.setIsHidden(request.getIsHidden());
|
||||
}
|
||||
|
||||
achievement.setUpdateTime(LocalDateTime.now());
|
||||
|
||||
boolean updated = this.updateById(achievement);
|
||||
if (!updated) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(achievement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AchievementResponse> getByCategoryWithResponse(String category) {
|
||||
List<Achievement> achievements = getByCategory(category);
|
||||
return achievements.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AchievementResponse> getByRarityWithResponse(String rarity) {
|
||||
List<Achievement> achievements = getByRarity(rarity);
|
||||
return achievements.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AchievementResponse> getUnlockedAchievementsWithResponse() {
|
||||
List<Achievement> achievements = getUnlockedAchievements();
|
||||
return achievements.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AchievementResponse> getLockedAchievementsWithResponse() {
|
||||
List<Achievement> achievements = getLockedAchievements();
|
||||
return achievements.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AchievementResponse> getRecentlyUnlockedWithResponse(Integer limit) {
|
||||
List<Achievement> achievements = getRecentlyUnlocked(limit);
|
||||
return achievements.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为响应对象
|
||||
*/
|
||||
private AchievementResponse convertToResponse(Achievement achievement) {
|
||||
AchievementResponse response = new AchievementResponse();
|
||||
org.springframework.beans.BeanUtils.copyProperties(achievement, response);
|
||||
response.setId(achievement.getId());
|
||||
if (achievement.getCreateTime() != null) {
|
||||
response.setCreateTime(achievement.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (achievement.getUpdateTime() != null) {
|
||||
response.setUpdateTime(achievement.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (achievement.getUnlockedTime() != null) {
|
||||
response.setUnlockedTime(achievement.getUnlockedTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ import com.emotion.exception.TokenException;
|
||||
import com.emotion.service.AuthService;
|
||||
import com.emotion.service.UserService;
|
||||
import com.emotion.util.JwtUtil;
|
||||
import com.emotion.util.TokenUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -22,6 +23,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -55,6 +57,9 @@ public class AuthServiceImpl implements AuthService {
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
@Autowired
|
||||
private TokenUtil tokenUtil;
|
||||
|
||||
private static final String CAPTCHA_PREFIX = "captcha:";
|
||||
private static final String TOKEN_PREFIX = "token:";
|
||||
private static final String REFRESH_TOKEN_PREFIX = "refresh_token:";
|
||||
@@ -239,7 +244,8 @@ public class AuthServiceImpl implements AuthService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logoutByToken(String token) {
|
||||
public boolean logoutByToken(HttpServletRequest request) {
|
||||
String token = tokenUtil.extractToken(request);
|
||||
String userId = validateTokenAndGetUserId(token);
|
||||
return logout(userId, token);
|
||||
}
|
||||
@@ -248,7 +254,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
* 验证令牌并获取用户ID
|
||||
*/
|
||||
private String validateTokenAndGetUserId(String token) {
|
||||
if (!StringUtils.hasText(token)) {
|
||||
if (!tokenUtil.isValidToken(token)) {
|
||||
throw new TokenException("未提供访问令牌");
|
||||
}
|
||||
|
||||
@@ -293,9 +299,15 @@ public class AuthServiceImpl implements AuthService {
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateToken(HttpServletRequest request) {
|
||||
String token = tokenUtil.extractToken(request);
|
||||
return validateToken(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateToken(String token) {
|
||||
if (!StringUtils.hasText(token)) {
|
||||
if (!tokenUtil.isValidToken(token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -314,7 +326,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
|
||||
@Override
|
||||
public String getUserIdFromToken(String token) {
|
||||
if (!StringUtils.hasText(token)) {
|
||||
if (!tokenUtil.isValidToken(token)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -336,7 +348,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
|
||||
@Override
|
||||
public String getUsernameFromToken(String token) {
|
||||
if (!StringUtils.hasText(token)) {
|
||||
if (!tokenUtil.isValidToken(token)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -498,4 +510,4 @@ public class AuthServiceImpl implements AuthService {
|
||||
User user = userService.getByPhone(phone);
|
||||
return user != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,27 @@
|
||||
package com.emotion.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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.common.PageResult;
|
||||
import com.emotion.dto.request.comment.CommentCreateRequest;
|
||||
import com.emotion.dto.request.comment.CommentUpdateRequest;
|
||||
import com.emotion.dto.request.comment.CommentPageRequest;
|
||||
import com.emotion.dto.response.comment.CommentResponse;
|
||||
import com.emotion.entity.Comment;
|
||||
import com.emotion.mapper.CommentMapper;
|
||||
import com.emotion.service.CommentService;
|
||||
import com.emotion.util.SnowflakeIdGenerator;
|
||||
import com.emotion.util.UserContextUtils;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 评论服务实现类
|
||||
@@ -23,219 +32,125 @@ import java.util.List;
|
||||
@Service
|
||||
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
|
||||
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<Comment> getPage(BasePageRequest request) {
|
||||
public PageResult<CommentResponse> getPage(CommentPageRequest request) {
|
||||
Page<Comment> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 根据请求参数构建查询条件
|
||||
if (StringUtils.hasText(request.getPostId())) {
|
||||
wrapper.eq(Comment::getPostId, request.getPostId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getUserId())) {
|
||||
wrapper.eq(Comment::getUserId, request.getUserId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getKeyword())) {
|
||||
wrapper.like(Comment::getContent, request.getKeyword());
|
||||
}
|
||||
|
||||
|
||||
wrapper.eq(Comment::getIsDeleted, 0).orderByDesc(Comment::getCreateTime);
|
||||
return this.page(page, wrapper);
|
||||
page = this.page(page, wrapper);
|
||||
|
||||
return convertPageToPageResult(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<Comment> getPageByPostId(BasePageRequest request, String postId) {
|
||||
Page<Comment> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime);
|
||||
return this.page(page, wrapper);
|
||||
public CommentResponse getById(String id) {
|
||||
Comment comment = this.getBaseMapper().selectById(id);
|
||||
if (comment == null) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<Comment> getPageByUserId(BasePageRequest request, String userId) {
|
||||
Page<Comment> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getUserId, userId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime);
|
||||
return this.page(page, wrapper);
|
||||
public CommentResponse create(CommentCreateRequest request) {
|
||||
Comment comment = new Comment();
|
||||
comment.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID
|
||||
comment.setPostId(request.getPostId());
|
||||
|
||||
// 从上下文中获取当前用户ID
|
||||
String currentUserId = UserContextUtils.getCurrentUserId();
|
||||
if (currentUserId != null) {
|
||||
comment.setUserId(currentUserId);
|
||||
} else if (request.getUserId() != null) {
|
||||
// 如果上下文中没有用户ID,则使用请求中的用户ID(向后兼容)
|
||||
comment.setUserId(request.getUserId());
|
||||
} else {
|
||||
throw new IllegalArgumentException("用户ID不能为空");
|
||||
}
|
||||
|
||||
comment.setContent(request.getContent());
|
||||
comment.setReplyToId(request.getReplyToId());
|
||||
comment.setLikes(0);
|
||||
|
||||
this.save(comment);
|
||||
return convertToResponse(comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getByPostId(String postId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByAsc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
public CommentResponse update(CommentUpdateRequest request) {
|
||||
Comment comment = this.getBaseMapper().selectById(request.getId());
|
||||
if (comment == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 只更新非空字段
|
||||
if (StringUtils.hasText(request.getContent())) {
|
||||
comment.setContent(request.getContent());
|
||||
}
|
||||
|
||||
this.updateById(comment);
|
||||
return convertToResponse(comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getByUserId(String userId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getUserId, userId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getRepliesByCommentId(String replyToId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getReplyToId, replyToId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByAsc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getTopLevelCommentsByPostId(String postId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.isNull(Comment::getReplyToId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByAsc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getByLikesRange(Integer minLikes, Integer maxLikes) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(Comment::getLikes, minLikes, maxLikes)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getLikes);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(Comment::getCreateTime, startTime, endTime)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByPostId(String postId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.eq(Comment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByUserId(String userId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getUserId, userId)
|
||||
.eq(Comment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countRepliesByCommentId(String commentId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getReplyToId, commentId)
|
||||
.eq(Comment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countTopLevelCommentsByPostId(String postId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.isNull(Comment::getReplyToId)
|
||||
.eq(Comment::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getMostLikedCommentsByPostId(String postId, Integer limit) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getLikes)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getLatestCommentsByPostId(String postId, Integer limit) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getRecentByUserId(String userId, Integer limit) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getUserId, userId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getPopularCommentsByPostId(String postId, Integer limit) {
|
||||
// 这里需要自定义SQL查询,暂时返回最新评论
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> searchByKeyword(String keyword) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(Comment::getContent, keyword)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> searchByPostIdAndKeyword(String postId, String keyword) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.like(Comment::getContent, keyword)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Comment> getByPostIdAndUserId(String postId, String userId) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Comment::getPostId, postId)
|
||||
.eq(Comment::getUserId, userId)
|
||||
.eq(Comment::getIsDeleted, 0)
|
||||
.orderByDesc(Comment::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateLikes(String id, Integer increment) {
|
||||
Comment comment = this.getById(id);
|
||||
public boolean delete(String id) {
|
||||
Comment comment = this.getBaseMapper().selectById(id);
|
||||
if (comment == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Integer newLikes = comment.getLikes() + increment;
|
||||
comment.setLikes(newLikes);
|
||||
// 逻辑删除
|
||||
comment.setIsDeleted(1);
|
||||
return this.updateById(comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comment createComment(String postId, String userId, String content, String replyToId) {
|
||||
Comment comment = new Comment();
|
||||
comment.setPostId(postId);
|
||||
comment.setUserId(userId);
|
||||
comment.setContent(content);
|
||||
comment.setReplyToId(replyToId);
|
||||
comment.setLikes(0);
|
||||
/**
|
||||
* 转换为响应对象
|
||||
*/
|
||||
private CommentResponse convertToResponse(Comment comment) {
|
||||
CommentResponse response = new CommentResponse();
|
||||
BeanUtils.copyProperties(comment, response);
|
||||
response.setId(comment.getId());
|
||||
if (comment.getCreateTime() != null) {
|
||||
response.setCreateTime(comment.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (comment.getUpdateTime() != null) {
|
||||
response.setUpdateTime(comment.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
this.save(comment);
|
||||
return comment;
|
||||
/**
|
||||
* 转换分页对象为PageResult对象
|
||||
*/
|
||||
private PageResult<CommentResponse> convertPageToPageResult(Page<Comment> page) {
|
||||
PageResult<CommentResponse> pageResult = new PageResult<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setRecords(page.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList()));
|
||||
return pageResult;
|
||||
}
|
||||
}
|
||||
+130
-269
@@ -1,18 +1,26 @@
|
||||
package com.emotion.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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.common.PageResult;
|
||||
import com.emotion.dto.request.community.CommunityPostCreateRequest;
|
||||
import com.emotion.dto.request.community.CommunityPostUpdateRequest;
|
||||
import com.emotion.dto.request.community.CommunityPostPageRequest;
|
||||
import com.emotion.dto.response.community.CommunityPostResponse;
|
||||
import com.emotion.entity.CommunityPost;
|
||||
import com.emotion.mapper.CommunityPostMapper;
|
||||
import com.emotion.service.CommunityPostService;
|
||||
import com.emotion.util.SnowflakeIdGenerator;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 社区帖子服务实现类
|
||||
@@ -23,296 +31,149 @@ import java.util.List;
|
||||
@Service
|
||||
public class CommunityPostServiceImpl extends ServiceImpl<CommunityPostMapper, CommunityPost> implements CommunityPostService {
|
||||
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<CommunityPost> getPage(BasePageRequest request) {
|
||||
public PageResult<CommunityPostResponse> getPage(CommunityPostPageRequest request) {
|
||||
Page<CommunityPost> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 根据请求参数构建查询条件
|
||||
if (StringUtils.hasText(request.getUserId())) {
|
||||
wrapper.eq(CommunityPost::getUserId, request.getUserId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getType())) {
|
||||
wrapper.eq(CommunityPost::getType, request.getType());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getLocationId())) {
|
||||
wrapper.eq(CommunityPost::getLocationId, request.getLocationId());
|
||||
}
|
||||
|
||||
if (request.getPublicOnly() != null && request.getPublicOnly()) {
|
||||
wrapper.eq(CommunityPost::getIsPrivate, 0);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getKeyword())) {
|
||||
wrapper.and(w -> w.like(CommunityPost::getTitle, request.getKeyword())
|
||||
.or().like(CommunityPost::getContent, request.getKeyword()));
|
||||
}
|
||||
|
||||
|
||||
wrapper.eq(CommunityPost::getIsDeleted, 0).orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.page(page, wrapper);
|
||||
page = this.page(page, wrapper);
|
||||
|
||||
return convertPageToResponse(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<CommunityPost> getPublicPostsPage(BasePageRequest request) {
|
||||
Page<CommunityPost> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
if (StringUtils.hasText(request.getKeyword())) {
|
||||
wrapper.and(w -> w.like(CommunityPost::getTitle, request.getKeyword())
|
||||
.or().like(CommunityPost::getContent, request.getKeyword()));
|
||||
}
|
||||
|
||||
wrapper.eq(CommunityPost::getIsPrivate, 0)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<CommunityPost> getPageByUserId(BasePageRequest request, String userId) {
|
||||
Page<CommunityPost> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getUserId, userId)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getByLocationId(String locationId) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getLocationId, locationId)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getByType(String type) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getType, type)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getPrivatePostsByUserId(String userId) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getUserId, userId)
|
||||
.eq(CommunityPost::getIsPrivate, 1)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getByLikesRange(Integer minLikes, Integer maxLikes) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(CommunityPost::getLikes, minLikes, maxLikes)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getLikes);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getByViewRange(Integer minViews, Integer maxViews) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(CommunityPost::getViewCount, minViews, maxViews)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getViewCount);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getByCommentRange(Integer minComments, Integer maxComments) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(CommunityPost::getCommentCount, minComments, maxComments)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCommentCount);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(CommunityPost::getCreateTime, startTime, endTime)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByUserId(String userId) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getUserId, userId)
|
||||
.eq(CommunityPost::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countPublicPostsByUserId(String userId) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getUserId, userId)
|
||||
.eq(CommunityPost::getIsPrivate, 0)
|
||||
.eq(CommunityPost::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countPrivatePostsByUserId(String userId) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getUserId, userId)
|
||||
.eq(CommunityPost::getIsPrivate, 1)
|
||||
.eq(CommunityPost::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByType(String type) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getType, type)
|
||||
.eq(CommunityPost::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByLocationId(String locationId) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getLocationId, locationId)
|
||||
.eq(CommunityPost::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getMostLikedPosts(Integer limit) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getLikes)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getMostViewedPosts(Integer limit) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getViewCount)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getLatestPosts(Integer limit) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getPopularPosts(Integer limit) {
|
||||
// 这里需要自定义SQL查询,暂时返回最新帖子
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getByTag(String tag) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(CommunityPost::getTags, tag)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> searchByKeyword(String keyword) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.and(w -> w.like(CommunityPost::getTitle, keyword)
|
||||
.or().like(CommunityPost::getContent, keyword))
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getRecentByUserId(String userId, Integer limit) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getUserId, userId)
|
||||
.eq(CommunityPost::getIsDeleted, 0)
|
||||
.orderByDesc(CommunityPost::getCreateTime)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateLikes(String id, Integer increment) {
|
||||
CommunityPost post = this.getById(id);
|
||||
public CommunityPostResponse getById(String id) {
|
||||
CommunityPost post = this.getBaseMapper().selectById(id);
|
||||
if (post == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
// 增加浏览数
|
||||
Integer viewCount = post.getViewCount() == null ? 1 : post.getViewCount() + 1;
|
||||
post.setViewCount(viewCount);
|
||||
this.updateById(post);
|
||||
|
||||
Integer newLikes = post.getLikes() + increment;
|
||||
post.setLikes(newLikes);
|
||||
return this.updateById(post);
|
||||
return convertToResponse(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incrementViewCount(String id) {
|
||||
CommunityPost post = this.getById(id);
|
||||
if (post == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Integer newViewCount = post.getViewCount() + 1;
|
||||
post.setViewCount(newViewCount);
|
||||
return this.updateById(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateCommentCount(String id, Integer increment) {
|
||||
CommunityPost post = this.getById(id);
|
||||
if (post == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Integer newCommentCount = post.getCommentCount() + increment;
|
||||
post.setCommentCount(newCommentCount);
|
||||
return this.updateById(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updatePrivacyStatus(String id, Integer isPrivate) {
|
||||
public CommunityPostResponse create(CommunityPostCreateRequest request) {
|
||||
CommunityPost post = new CommunityPost();
|
||||
post.setId(id);
|
||||
post.setIsPrivate(isPrivate);
|
||||
return this.updateById(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommunityPost> getRecommendedPosts(String type, String locationId, Integer limit) {
|
||||
LambdaQueryWrapper<CommunityPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CommunityPost::getIsDeleted, 0);
|
||||
|
||||
if (StringUtils.hasText(type)) {
|
||||
wrapper.eq(CommunityPost::getType, type);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(locationId)) {
|
||||
wrapper.eq(CommunityPost::getLocationId, locationId);
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(CommunityPost::getCreateTime)
|
||||
.last("LIMIT " + limit);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommunityPost createPost(String userId, String title, String content, String type,
|
||||
String locationId, String tags, Integer isPrivate) {
|
||||
CommunityPost post = new CommunityPost();
|
||||
post.setUserId(userId);
|
||||
post.setTitle(title);
|
||||
post.setContent(content);
|
||||
post.setType(type);
|
||||
post.setLocationId(locationId);
|
||||
post.setTags(tags);
|
||||
post.setIsPrivate(isPrivate);
|
||||
post.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID
|
||||
post.setUserId(request.getUserId());
|
||||
post.setTitle(request.getTitle());
|
||||
post.setContent(request.getContent());
|
||||
post.setType(request.getType());
|
||||
post.setLocationId(request.getLocationId());
|
||||
post.setTags(request.getTags());
|
||||
post.setIsPrivate(request.getIsPrivate() != null ? request.getIsPrivate() : 0); // 默认公开
|
||||
post.setLikes(0);
|
||||
post.setViewCount(0);
|
||||
post.setCommentCount(0);
|
||||
|
||||
this.save(post);
|
||||
return post;
|
||||
return convertToResponse(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommunityPostResponse update(CommunityPostUpdateRequest request) {
|
||||
CommunityPost post = this.getBaseMapper().selectById(request.getId());
|
||||
if (post == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 只更新非空字段
|
||||
if (request.getTitle() != null) {
|
||||
post.setTitle(request.getTitle());
|
||||
}
|
||||
if (request.getContent() != null) {
|
||||
post.setContent(request.getContent());
|
||||
}
|
||||
if (request.getType() != null) {
|
||||
post.setType(request.getType());
|
||||
}
|
||||
if (request.getLocationId() != null) {
|
||||
post.setLocationId(request.getLocationId());
|
||||
}
|
||||
if (request.getTags() != null) {
|
||||
post.setTags(request.getTags());
|
||||
}
|
||||
if (request.getIsPrivate() != null) {
|
||||
post.setIsPrivate(request.getIsPrivate());
|
||||
}
|
||||
|
||||
this.updateById(post);
|
||||
return convertToResponse(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(String id) {
|
||||
CommunityPost post = this.getBaseMapper().selectById(id);
|
||||
if (post == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 逻辑删除
|
||||
post.setIsDeleted(1);
|
||||
return this.updateById(post);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为响应对象
|
||||
*/
|
||||
private CommunityPostResponse convertToResponse(CommunityPost post) {
|
||||
CommunityPostResponse response = new CommunityPostResponse();
|
||||
BeanUtils.copyProperties(post, response);
|
||||
response.setId(post.getId());
|
||||
if (post.getCreateTime() != null) {
|
||||
response.setCreateTime(post.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (post.getUpdateTime() != null) {
|
||||
response.setUpdateTime(post.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换分页对象为响应对象
|
||||
*/
|
||||
private PageResult<CommunityPostResponse> convertPageToResponse(Page<CommunityPost> page) {
|
||||
PageResult<CommunityPostResponse> 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;
|
||||
}
|
||||
}
|
||||
+192
-4
@@ -4,15 +4,25 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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.common.PageResult;
|
||||
import com.emotion.dto.request.ConversationCreateRequest;
|
||||
import com.emotion.dto.request.ConversationPageRequest;
|
||||
import com.emotion.dto.response.ConversationResponse;
|
||||
import com.emotion.entity.Conversation;
|
||||
import com.emotion.mapper.ConversationMapper;
|
||||
import com.emotion.service.ConversationService;
|
||||
import com.emotion.util.SnowflakeIdGenerator;
|
||||
import com.emotion.util.UserContextUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 会话服务实现类
|
||||
@@ -23,11 +33,29 @@ import java.util.List;
|
||||
@Service
|
||||
public class ConversationServiceImpl extends ServiceImpl<ConversationMapper, Conversation> implements ConversationService {
|
||||
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<Conversation> getPage(BasePageRequest request) {
|
||||
public IPage<Conversation> getPage(ConversationPageRequest request) {
|
||||
Page<Conversation> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<Conversation> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 根据请求参数构建查询条件
|
||||
if (StringUtils.hasText(request.getUserId())) {
|
||||
wrapper.eq(Conversation::getUserId, request.getUserId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getStatus())) {
|
||||
wrapper.eq(Conversation::getConversationStatus, request.getStatus());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getType())) {
|
||||
wrapper.eq(Conversation::getType, request.getType());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getKeyword())) {
|
||||
wrapper.and(w -> w.like(Conversation::getTitle, request.getKeyword())
|
||||
.or().like(Conversation::getSummary, request.getKeyword()));
|
||||
@@ -38,10 +66,16 @@ public class ConversationServiceImpl extends ServiceImpl<ConversationMapper, Con
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<Conversation> getPageByUserId(BasePageRequest request, String userId) {
|
||||
public IPage<Conversation> getPageByUserId(ConversationPageRequest request) {
|
||||
Page<Conversation> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<Conversation> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Conversation::getUserId, userId)
|
||||
|
||||
// 必须提供userId参数
|
||||
if (!StringUtils.hasText(request.getUserId())) {
|
||||
throw new IllegalArgumentException("userId不能为空");
|
||||
}
|
||||
|
||||
wrapper.eq(Conversation::getUserId, request.getUserId())
|
||||
.eq(Conversation::getIsDeleted, 0)
|
||||
.orderByDesc(Conversation::getCreateTime);
|
||||
return this.page(page, wrapper);
|
||||
@@ -148,6 +182,7 @@ public class ConversationServiceImpl extends ServiceImpl<ConversationMapper, Con
|
||||
@Override
|
||||
public Conversation createConversation(String userId, String title, String cozeConversationId) {
|
||||
Conversation conversation = new Conversation();
|
||||
conversation.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID
|
||||
conversation.setUserId(userId);
|
||||
conversation.setTitle(title);
|
||||
conversation.setCozeConversationId(cozeConversationId);
|
||||
@@ -172,4 +207,157 @@ public class ConversationServiceImpl extends ServiceImpl<ConversationMapper, Con
|
||||
conversation.setEndTime(LocalDateTime.now());
|
||||
return this.updateById(conversation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ConversationResponse> getPageWithResponse(ConversationPageRequest request) {
|
||||
IPage<Conversation> page = this.getPage(request);
|
||||
return convertPageToResponse(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ConversationResponse> getPageByUserIdWithResponse(ConversationPageRequest request) {
|
||||
IPage<Conversation> page = this.getPageByUserId(request);
|
||||
return convertPageToResponse(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationResponse getConversationResponseById(String id) {
|
||||
Conversation conversation = this.getById(id);
|
||||
if (conversation == null) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(conversation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConversationResponse> getByUserIdWithResponse(String userId) {
|
||||
List<Conversation> conversations = this.getByUserId(userId);
|
||||
return conversations.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConversationResponse> getActiveConversationsWithResponse() {
|
||||
// 实现获取活跃对话的逻辑
|
||||
LambdaQueryWrapper<Conversation> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Conversation::getConversationStatus, "active")
|
||||
.eq(Conversation::getIsDeleted, 0)
|
||||
.orderByDesc(Conversation::getLastActiveTime);
|
||||
List<Conversation> conversations = this.list(wrapper);
|
||||
return conversations.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConversationResponse> getArchivedConversationsWithResponse() {
|
||||
// 实现获取归档对话的逻辑
|
||||
LambdaQueryWrapper<Conversation> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Conversation::getConversationStatus, "archived")
|
||||
.eq(Conversation::getIsDeleted, 0)
|
||||
.orderByDesc(Conversation::getCreateTime);
|
||||
List<Conversation> conversations = this.list(wrapper);
|
||||
return conversations.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean archiveConversation(String id) {
|
||||
Conversation conversation = new Conversation();
|
||||
conversation.setId(id);
|
||||
conversation.setConversationStatus("archived");
|
||||
return this.updateById(conversation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activateConversation(String id) {
|
||||
Conversation conversation = new Conversation();
|
||||
conversation.setId(id);
|
||||
conversation.setConversationStatus("active");
|
||||
return this.updateById(conversation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationResponse createConversationWithResponse(ConversationCreateRequest request,
|
||||
HttpServletRequest httpRequest) {
|
||||
// 获取客户端IP地址
|
||||
String clientIp = UserContextUtils.getClientIpAddress(httpRequest);
|
||||
|
||||
Conversation conversation = this.createConversation(
|
||||
request.getUserId(),
|
||||
request.getTitle(),
|
||||
null // cozeConversationId
|
||||
);
|
||||
|
||||
// 设置客户端IP
|
||||
conversation.setClientIp(clientIp);
|
||||
this.updateById(conversation);
|
||||
|
||||
return convertToResponse(conversation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationResponse updateConversationWithResponse(ConversationCreateRequest request) {
|
||||
Conversation conversation = this.getById(request.getId()); // 修复:使用ID而不是userId
|
||||
if (conversation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 更新字段
|
||||
if (request.getTitle() != null) {
|
||||
conversation.setTitle(request.getTitle());
|
||||
}
|
||||
if (request.getType() != null) {
|
||||
conversation.setType(request.getType());
|
||||
}
|
||||
|
||||
this.updateById(conversation);
|
||||
return convertToResponse(conversation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateConversationStatus(String id, String status) {
|
||||
Conversation conversation = new Conversation();
|
||||
conversation.setId(id);
|
||||
conversation.setConversationStatus(status);
|
||||
return this.updateById(conversation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为响应对象
|
||||
*/
|
||||
private ConversationResponse convertToResponse(Conversation conversation) {
|
||||
ConversationResponse response = new ConversationResponse();
|
||||
BeanUtils.copyProperties(conversation, response);
|
||||
response.setId(conversation.getId());
|
||||
response.setStatus(conversation.getConversationStatus());
|
||||
if (conversation.getCreateTime() != null) {
|
||||
response.setCreateTime(conversation.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (conversation.getUpdateTime() != null) {
|
||||
response.setUpdateTime(conversation.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (conversation.getLastActiveTime() != null) {
|
||||
response.setLastMessageTime(conversation.getLastActiveTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换分页对象为响应对象
|
||||
*/
|
||||
private PageResult<ConversationResponse> convertPageToResponse(IPage<Conversation> page) {
|
||||
PageResult<ConversationResponse> 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;
|
||||
}
|
||||
}
|
||||
+259
-146
@@ -1,20 +1,27 @@
|
||||
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.common.PageResult;
|
||||
import com.emotion.dto.request.coze.CozeApiCallPageRequest;
|
||||
import com.emotion.dto.request.coze.CozeApiCallCreateRequest;
|
||||
import com.emotion.dto.request.coze.CozeApiCallUpdateRequest;
|
||||
import com.emotion.dto.response.coze.CozeApiCallResponse;
|
||||
import com.emotion.entity.CozeApiCall;
|
||||
import com.emotion.mapper.CozeApiCallMapper;
|
||||
import com.emotion.service.CozeApiCallService;
|
||||
import com.emotion.util.SnowflakeIdGenerator;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
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.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Coze API调用记录服务实现类
|
||||
@@ -25,15 +32,46 @@ import java.util.List;
|
||||
@Service
|
||||
public class CozeApiCallServiceImpl extends ServiceImpl<CozeApiCallMapper, CozeApiCall> implements CozeApiCallService {
|
||||
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<CozeApiCall> getPage(BasePageRequest request) {
|
||||
public PageResult<CozeApiCallResponse> getPage(CozeApiCallPageRequest request) {
|
||||
Page<CozeApiCall> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 根据请求参数构建查询条件
|
||||
if (StringUtils.hasText(request.getConversationId())) {
|
||||
wrapper.eq(CozeApiCall::getConversationId, request.getConversationId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getUserId())) {
|
||||
wrapper.eq(CozeApiCall::getUserId, request.getUserId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getBotId())) {
|
||||
wrapper.eq(CozeApiCall::getBotId, request.getBotId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getStatus())) {
|
||||
wrapper.eq(CozeApiCall::getStatus, request.getStatus());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getRequestType())) {
|
||||
wrapper.eq(CozeApiCall::getRequestType, request.getRequestType());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(request.getTraceId())) {
|
||||
wrapper.eq(CozeApiCall::getTraceId, request.getTraceId());
|
||||
}
|
||||
|
||||
// 关键词搜索
|
||||
if (StringUtils.hasText(request.getKeyword())) {
|
||||
wrapper.like(CozeApiCall::getRequestUrl, request.getKeyword())
|
||||
.or().like(CozeApiCall::getAiReply, request.getKeyword());
|
||||
wrapper.and(w -> w.like(CozeApiCall::getRequestUrl, request.getKeyword())
|
||||
.or().like(CozeApiCall::getAiReply, request.getKeyword())
|
||||
.or().like(CozeApiCall::getUserMessage, request.getKeyword()));
|
||||
}
|
||||
|
||||
wrapper.eq(CozeApiCall::getIsDeleted, 0);
|
||||
@@ -49,77 +87,193 @@ public class CozeApiCallServiceImpl extends ServiceImpl<CozeApiCallMapper, CozeA
|
||||
wrapper.orderByDesc(CozeApiCall::getStartTime);
|
||||
}
|
||||
|
||||
return this.page(page, wrapper);
|
||||
page = this.page(page, wrapper);
|
||||
return convertPageToPageResult(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<CozeApiCall> getPageByConversationId(BasePageRequest request, String conversationId) {
|
||||
Page<CozeApiCall> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getConversationId, conversationId)
|
||||
.eq(CozeApiCall::getIsDeleted, 0);
|
||||
public CozeApiCallResponse getById(String id) {
|
||||
CozeApiCall apiCall = this.getBaseMapper().selectById(id);
|
||||
if (apiCall == null || apiCall.getIsDeleted() == 1) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(apiCall);
|
||||
}
|
||||
|
||||
// 关键词搜索
|
||||
if (StringUtils.hasText(request.getKeyword())) {
|
||||
wrapper.like(CozeApiCall::getRequestUrl, request.getKeyword())
|
||||
.or().like(CozeApiCall::getAiReply, request.getKeyword());
|
||||
@Override
|
||||
public CozeApiCallResponse create(CozeApiCallCreateRequest request) {
|
||||
CozeApiCall apiCall = new CozeApiCall();
|
||||
apiCall.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID
|
||||
|
||||
// 复制属性
|
||||
apiCall.setConversationId(request.getConversationId());
|
||||
apiCall.setMessageId(request.getMessageId());
|
||||
apiCall.setCozeChatId(request.getCozeChatId());
|
||||
apiCall.setCozeConversationId(request.getCozeConversationId());
|
||||
apiCall.setBotId(request.getBotId());
|
||||
apiCall.setWorkflowId(request.getWorkflowId());
|
||||
apiCall.setUserId(request.getUserId());
|
||||
apiCall.setRequestType(request.getRequestType());
|
||||
apiCall.setRequestUrl(request.getRequestUrl());
|
||||
apiCall.setRequestBody(request.getRequestBody());
|
||||
apiCall.setRequestHeaders(request.getRequestHeaders());
|
||||
apiCall.setUserMessage(request.getUserMessage());
|
||||
apiCall.setUserMessageType(request.getUserMessageType());
|
||||
apiCall.setAiReply(request.getAiReply());
|
||||
apiCall.setAiReplyType(request.getAiReplyType());
|
||||
apiCall.setResponseStatus(request.getResponseStatus());
|
||||
apiCall.setResponseBody(request.getResponseBody());
|
||||
apiCall.setResponseHeaders(request.getResponseHeaders());
|
||||
apiCall.setPollCount(request.getPollCount());
|
||||
apiCall.setFinalStatus(request.getFinalStatus());
|
||||
apiCall.setStatus(request.getStatus());
|
||||
apiCall.setDurationMs(request.getDurationMs());
|
||||
apiCall.setPromptTokens(request.getPromptTokens());
|
||||
apiCall.setCompletionTokens(request.getCompletionTokens());
|
||||
apiCall.setTotalTokens(request.getTotalTokens());
|
||||
apiCall.setCost(request.getCost());
|
||||
apiCall.setFunctionCalls(request.getFunctionCalls());
|
||||
apiCall.setFunctionResults(request.getFunctionResults());
|
||||
apiCall.setErrorCode(request.getErrorCode());
|
||||
apiCall.setErrorMessage(request.getErrorMessage());
|
||||
apiCall.setClientIp(request.getClientIp());
|
||||
apiCall.setUserAgent(request.getUserAgent());
|
||||
apiCall.setSessionId(request.getSessionId());
|
||||
apiCall.setTraceId(request.getTraceId());
|
||||
apiCall.setMetadata(request.getMetadata());
|
||||
|
||||
this.save(apiCall);
|
||||
return convertToResponse(apiCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CozeApiCallResponse update(CozeApiCallUpdateRequest request) {
|
||||
CozeApiCall apiCall = this.getBaseMapper().selectById(request.getId());
|
||||
if (apiCall == null || apiCall.getIsDeleted() == 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<CozeApiCall> getPageByUserId(BasePageRequest request, String userId) {
|
||||
Page<CozeApiCall> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getUserId, userId)
|
||||
.eq(CozeApiCall::getIsDeleted, 0);
|
||||
|
||||
// 关键词搜索
|
||||
if (StringUtils.hasText(request.getKeyword())) {
|
||||
wrapper.like(CozeApiCall::getRequestUrl, request.getKeyword())
|
||||
.or().like(CozeApiCall::getAiReply, request.getKeyword());
|
||||
// 只更新非空字段
|
||||
if (request.getConversationId() != null) {
|
||||
apiCall.setConversationId(request.getConversationId());
|
||||
}
|
||||
if (request.getMessageId() != null) {
|
||||
apiCall.setMessageId(request.getMessageId());
|
||||
}
|
||||
if (request.getCozeChatId() != null) {
|
||||
apiCall.setCozeChatId(request.getCozeChatId());
|
||||
}
|
||||
if (request.getCozeConversationId() != null) {
|
||||
apiCall.setCozeConversationId(request.getCozeConversationId());
|
||||
}
|
||||
if (request.getBotId() != null) {
|
||||
apiCall.setBotId(request.getBotId());
|
||||
}
|
||||
if (request.getWorkflowId() != null) {
|
||||
apiCall.setWorkflowId(request.getWorkflowId());
|
||||
}
|
||||
if (request.getUserId() != null) {
|
||||
apiCall.setUserId(request.getUserId());
|
||||
}
|
||||
if (request.getRequestType() != null) {
|
||||
apiCall.setRequestType(request.getRequestType());
|
||||
}
|
||||
if (request.getRequestUrl() != null) {
|
||||
apiCall.setRequestUrl(request.getRequestUrl());
|
||||
}
|
||||
if (request.getRequestBody() != null) {
|
||||
apiCall.setRequestBody(request.getRequestBody());
|
||||
}
|
||||
if (request.getRequestHeaders() != null) {
|
||||
apiCall.setRequestHeaders(request.getRequestHeaders());
|
||||
}
|
||||
if (request.getUserMessage() != null) {
|
||||
apiCall.setUserMessage(request.getUserMessage());
|
||||
}
|
||||
if (request.getUserMessageType() != null) {
|
||||
apiCall.setUserMessageType(request.getUserMessageType());
|
||||
}
|
||||
if (request.getAiReply() != null) {
|
||||
apiCall.setAiReply(request.getAiReply());
|
||||
}
|
||||
if (request.getAiReplyType() != null) {
|
||||
apiCall.setAiReplyType(request.getAiReplyType());
|
||||
}
|
||||
if (request.getResponseStatus() != null) {
|
||||
apiCall.setResponseStatus(request.getResponseStatus());
|
||||
}
|
||||
if (request.getResponseBody() != null) {
|
||||
apiCall.setResponseBody(request.getResponseBody());
|
||||
}
|
||||
if (request.getResponseHeaders() != null) {
|
||||
apiCall.setResponseHeaders(request.getResponseHeaders());
|
||||
}
|
||||
if (request.getPollCount() != null) {
|
||||
apiCall.setPollCount(request.getPollCount());
|
||||
}
|
||||
if (request.getFinalStatus() != null) {
|
||||
apiCall.setFinalStatus(request.getFinalStatus());
|
||||
}
|
||||
if (request.getStatus() != null) {
|
||||
apiCall.setStatus(request.getStatus());
|
||||
}
|
||||
if (request.getDurationMs() != null) {
|
||||
apiCall.setDurationMs(request.getDurationMs());
|
||||
}
|
||||
if (request.getPromptTokens() != null) {
|
||||
apiCall.setPromptTokens(request.getPromptTokens());
|
||||
}
|
||||
if (request.getCompletionTokens() != null) {
|
||||
apiCall.setCompletionTokens(request.getCompletionTokens());
|
||||
}
|
||||
if (request.getTotalTokens() != null) {
|
||||
apiCall.setTotalTokens(request.getTotalTokens());
|
||||
}
|
||||
if (request.getCost() != null) {
|
||||
apiCall.setCost(request.getCost());
|
||||
}
|
||||
if (request.getFunctionCalls() != null) {
|
||||
apiCall.setFunctionCalls(request.getFunctionCalls());
|
||||
}
|
||||
if (request.getFunctionResults() != null) {
|
||||
apiCall.setFunctionResults(request.getFunctionResults());
|
||||
}
|
||||
if (request.getErrorCode() != null) {
|
||||
apiCall.setErrorCode(request.getErrorCode());
|
||||
}
|
||||
if (request.getErrorMessage() != null) {
|
||||
apiCall.setErrorMessage(request.getErrorMessage());
|
||||
}
|
||||
if (request.getClientIp() != null) {
|
||||
apiCall.setClientIp(request.getClientIp());
|
||||
}
|
||||
if (request.getUserAgent() != null) {
|
||||
apiCall.setUserAgent(request.getUserAgent());
|
||||
}
|
||||
if (request.getSessionId() != null) {
|
||||
apiCall.setSessionId(request.getSessionId());
|
||||
}
|
||||
if (request.getTraceId() != null) {
|
||||
apiCall.setTraceId(request.getTraceId());
|
||||
}
|
||||
if (request.getMetadata() != null) {
|
||||
apiCall.setMetadata(request.getMetadata());
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.page(page, wrapper);
|
||||
this.updateById(apiCall);
|
||||
return convertToResponse(apiCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CozeApiCall> getByBotId(String botId) {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getBotId, botId)
|
||||
.eq(CozeApiCall::getIsDeleted, 0)
|
||||
.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
public boolean delete(String id) {
|
||||
CozeApiCall apiCall = this.getBaseMapper().selectById(id);
|
||||
if (apiCall == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CozeApiCall> getByStatus(String status) {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getStatus, status)
|
||||
.eq(CozeApiCall::getIsDeleted, 0)
|
||||
.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CozeApiCall> getByRequestType(String requestType) {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getRequestType, requestType)
|
||||
.eq(CozeApiCall::getIsDeleted, 0)
|
||||
.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CozeApiCall> getByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(CozeApiCall::getStartTime, startTime, endTime)
|
||||
.eq(CozeApiCall::getIsDeleted, 0)
|
||||
.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.list(wrapper);
|
||||
// 逻辑删除
|
||||
apiCall.setIsDeleted(1);
|
||||
return this.updateById(apiCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,87 +321,46 @@ public class CozeApiCallServiceImpl extends ServiceImpl<CozeApiCallMapper, CozeA
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CozeApiCall> getFailedCalls() {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.and(w -> w.eq(CozeApiCall::getStatus, "failed").or().eq(CozeApiCall::getFinalStatus, "failed"))
|
||||
.eq(CozeApiCall::getIsDeleted, 0)
|
||||
.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.list(wrapper);
|
||||
/**
|
||||
* 转换为响应对象
|
||||
*/
|
||||
private CozeApiCallResponse convertToResponse(CozeApiCall apiCall) {
|
||||
CozeApiCallResponse response = new CozeApiCallResponse();
|
||||
BeanUtils.copyProperties(apiCall, response);
|
||||
response.setId(apiCall.getId());
|
||||
if (apiCall.getCreateTime() != null) {
|
||||
response.setCreateTime(apiCall.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (apiCall.getUpdateTime() != null) {
|
||||
response.setUpdateTime(apiCall.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (apiCall.getStartTime() != null) {
|
||||
response.setStartTime(apiCall.getStartTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (apiCall.getEndTime() != null) {
|
||||
response.setEndTime(apiCall.getEndTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (apiCall.getPollStartTime() != null) {
|
||||
response.setPollStartTime(apiCall.getPollStartTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (apiCall.getPollEndTime() != null) {
|
||||
response.setPollEndTime(apiCall.getPollEndTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CozeApiCall> getTimeoutCalls() {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.and(w -> w.eq(CozeApiCall::getStatus, "timeout").or().eq(CozeApiCall::getFinalStatus, "timeout"))
|
||||
.eq(CozeApiCall::getIsDeleted, 0)
|
||||
.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.list(wrapper);
|
||||
/**
|
||||
* 转换分页对象为PageResult对象
|
||||
*/
|
||||
private PageResult<CozeApiCallResponse> convertPageToPageResult(Page<CozeApiCall> page) {
|
||||
PageResult<CozeApiCallResponse> pageResult = new PageResult<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setRecords(page.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList()));
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CozeApiCall getByTraceId(String traceId) {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getTraceId, traceId)
|
||||
.eq(CozeApiCall::getIsDeleted, 0);
|
||||
return this.getOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CozeApiCall> getByConversationIdAndRequestType(String conversationId, String requestType) {
|
||||
LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getConversationId, conversationId)
|
||||
.eq(CozeApiCall::getRequestType, requestType)
|
||||
.eq(CozeApiCall::getIsDeleted, 0)
|
||||
.orderByDesc(CozeApiCall::getStartTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateStatus(String id, String status, String finalStatus, LocalDateTime endTime) {
|
||||
LambdaUpdateWrapper<CozeApiCall> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getId, id)
|
||||
.set(CozeApiCall::getStatus, status)
|
||||
.set(CozeApiCall::getFinalStatus, finalStatus)
|
||||
.set(CozeApiCall::getEndTime, endTime)
|
||||
.set(CozeApiCall::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateResult(String id, Integer responseStatus, String responseBody, String aiReply,
|
||||
Integer totalTokens, BigDecimal cost, String status, String finalStatus,
|
||||
LocalDateTime endTime) {
|
||||
LambdaUpdateWrapper<CozeApiCall> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(CozeApiCall::getId, id)
|
||||
.set(CozeApiCall::getResponseStatus, responseStatus)
|
||||
.set(CozeApiCall::getResponseBody, responseBody)
|
||||
.set(CozeApiCall::getAiReply, aiReply)
|
||||
.set(CozeApiCall::getTotalTokens, totalTokens)
|
||||
.set(CozeApiCall::getCost, cost)
|
||||
.set(CozeApiCall::getStatus, status)
|
||||
.set(CozeApiCall::getFinalStatus, finalStatus)
|
||||
.set(CozeApiCall::getEndTime, endTime)
|
||||
.set(CozeApiCall::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CozeApiCall createApiCall(String conversationId, String messageId, String userId,
|
||||
String requestType, String requestUrl, String requestBody) {
|
||||
CozeApiCall apiCall = CozeApiCall.builder()
|
||||
.conversationId(conversationId)
|
||||
.messageId(messageId)
|
||||
.userId(userId)
|
||||
.requestType(requestType)
|
||||
.requestUrl(requestUrl)
|
||||
.requestBody(requestBody)
|
||||
.status("pending")
|
||||
.startTime(LocalDateTime.now())
|
||||
.createBy(userId) // 设置创建人为当前用户
|
||||
.updateBy(userId) // 设置更新人为当前用户
|
||||
.build();
|
||||
this.save(apiCall);
|
||||
return apiCall;
|
||||
}
|
||||
}
|
||||
}
|
||||
+214
-182
@@ -5,18 +5,24 @@ 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.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.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -29,207 +35,105 @@ import java.util.stream.Collectors;
|
||||
@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 IPage<DiaryComment> getPage(BasePageRequest request) {
|
||||
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)
|
||||
.orderByDesc(DiaryComment::getIsTop)
|
||||
|
||||
// 基础查询条件
|
||||
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);
|
||||
return this.page(page, wrapper);
|
||||
|
||||
IPage<DiaryComment> resultPage = this.page(page, wrapper);
|
||||
return convertPageToResponse(resultPage);
|
||||
}
|
||||
|
||||
@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);
|
||||
public DiaryCommentResponse getCommentResponseById(String id) {
|
||||
DiaryComment comment = this.getById(id);
|
||||
if (comment == null) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(comment);
|
||||
}
|
||||
|
||||
@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);
|
||||
public List<DiaryCommentResponse> getCommentTreeWithResponse(String diaryId) {
|
||||
List<DiaryComment> comments = this.getCommentTree(diaryId);
|
||||
return comments.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@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) {
|
||||
public DiaryCommentResponse createCommentWithResponse(DiaryCommentCreateRequest request) {
|
||||
DiaryComment comment = DiaryComment.builder()
|
||||
.diaryId(diaryId)
|
||||
.userId(userId)
|
||||
.content(content)
|
||||
.images(convertListToJson(images))
|
||||
.parentCommentId(parentCommentId)
|
||||
.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(isAnonymous)
|
||||
.isAnonymous(request.getIsAnonymous())
|
||||
.isTop(0)
|
||||
.status("published")
|
||||
.publishTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
|
||||
this.save(comment);
|
||||
|
||||
|
||||
// 如果有父评论,更新父评论的回复数
|
||||
if (StringUtils.hasText(parentCommentId)) {
|
||||
this.incrementReplyCount(parentCommentId);
|
||||
this.updateLastReplyTime(parentCommentId);
|
||||
if (StringUtils.hasText(request.getParentCommentId())) {
|
||||
this.incrementReplyCount(request.getParentCommentId());
|
||||
this.updateLastReplyTime(request.getParentCommentId());
|
||||
}
|
||||
|
||||
return comment;
|
||||
|
||||
return convertToResponse(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) {
|
||||
public DiaryCommentResponse updateCommentWithResponse(DiaryCommentCreateRequest request) {
|
||||
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);
|
||||
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
|
||||
@@ -241,7 +145,8 @@ public class DiaryCommentServiceImpl extends ServiceImpl<DiaryCommentMapper, Dia
|
||||
public boolean softDeleteComment(String commentId) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.set(DiaryComment::getIsDeleted, 1);
|
||||
.set(DiaryComment::getIsDeleted, 1)
|
||||
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -249,22 +154,52 @@ public class DiaryCommentServiceImpl extends ServiceImpl<DiaryCommentMapper, Dia
|
||||
public boolean restoreComment(String commentId) {
|
||||
LambdaUpdateWrapper<DiaryComment> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryComment::getId, commentId)
|
||||
.set(DiaryComment::getIsDeleted, 0);
|
||||
.set(DiaryComment::getIsDeleted, 0)
|
||||
.set(DiaryComment::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryComment> getCommentTree(String diaryId) {
|
||||
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);
|
||||
|
||||
.isNull(DiaryComment::getParentCommentId)
|
||||
.eq(DiaryComment::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryComment::getIsTop)
|
||||
.orderByDesc(DiaryComment::getPublishTime);
|
||||
|
||||
List<DiaryComment> topComments = this.list(wrapper);
|
||||
|
||||
|
||||
// 为每个顶级评论加载回复
|
||||
return topComments.stream()
|
||||
.peek(comment -> {
|
||||
@@ -274,6 +209,103 @@ public class DiaryCommentServiceImpl extends ServiceImpl<DiaryCommentMapper, Dia
|
||||
.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字符串
|
||||
*/
|
||||
@@ -287,4 +319,4 @@ public class DiaryCommentServiceImpl extends ServiceImpl<DiaryCommentMapper, Dia
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,24 +5,30 @@ 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.common.PageResult;
|
||||
import com.emotion.dto.request.DiaryPostCreateRequest;
|
||||
import com.emotion.dto.request.DiaryPostPageRequest;
|
||||
import com.emotion.dto.request.DiaryPostUpdateRequest;
|
||||
import com.emotion.dto.response.DiaryPostResponse;
|
||||
import com.emotion.entity.DiaryPost;
|
||||
import com.emotion.mapper.DiaryPostMapper;
|
||||
import com.emotion.service.DiaryPostService;
|
||||
import com.emotion.service.DiaryCommentService;
|
||||
import com.emotion.service.AiChatService;
|
||||
import com.emotion.dto.request.DiaryPostCreateRequest;
|
||||
import com.emotion.dto.response.DiaryPostResponse;
|
||||
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.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户日记服务实现类
|
||||
@@ -39,112 +45,153 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
private DiaryCommentService diaryCommentService;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<DiaryPost> getPage(BasePageRequest request) {
|
||||
public PageResult<DiaryPostResponse> getPageWithResponse(DiaryPostPageRequest request) {
|
||||
Page<DiaryPost> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPriority)
|
||||
|
||||
// 基础查询条件
|
||||
wrapper.eq(DiaryPost::getIsDeleted, 0);
|
||||
|
||||
// 根据请求参数添加查询条件
|
||||
if (StringUtils.hasText(request.getUserId())) {
|
||||
wrapper.eq(DiaryPost::getUserId, request.getUserId());
|
||||
}
|
||||
if (Boolean.TRUE.equals(request.getPublicOnly())) {
|
||||
wrapper.eq(DiaryPost::getIsPublic, 1)
|
||||
.eq(DiaryPost::getStatus, "published");
|
||||
}
|
||||
if (Boolean.TRUE.equals(request.getFeaturedOnly())) {
|
||||
wrapper.eq(DiaryPost::getFeatured, 1)
|
||||
.eq(DiaryPost::getIsPublic, 1)
|
||||
.eq(DiaryPost::getStatus, "published");
|
||||
}
|
||||
if (StringUtils.hasText(request.getMood())) {
|
||||
wrapper.eq(DiaryPost::getMood, request.getMood());
|
||||
}
|
||||
if (StringUtils.hasText(request.getTag())) {
|
||||
// 标签查询可能需要特殊处理,因为tags字段是JSON格式
|
||||
wrapper.like(DiaryPost::getTags, request.getTag());
|
||||
}
|
||||
|
||||
// 排序
|
||||
wrapper.orderByDesc(DiaryPost::getPriority)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.page(page, wrapper);
|
||||
|
||||
IPage<DiaryPost> resultPage = this.page(page, wrapper);
|
||||
List<DiaryPostResponse> responses = resultPage.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
return createPageResult(resultPage, responses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<DiaryPost> getPageByUserId(String userId, BasePageRequest request) {
|
||||
Page<DiaryPost> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getUserId, userId)
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPriority)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.page(page, wrapper);
|
||||
public DiaryPostResponse getDiaryPostResponseById(String id) {
|
||||
DiaryPost diaryPost = this.getById(id);
|
||||
if (diaryPost == null) {
|
||||
return null;
|
||||
}
|
||||
// 增加浏览数
|
||||
incrementViewCount(id);
|
||||
return convertToResponse(diaryPost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<DiaryPost> getPublicPageByUserId(String userId, BasePageRequest request) {
|
||||
Page<DiaryPost> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getUserId, userId)
|
||||
.eq(DiaryPost::getIsPublic, 1)
|
||||
.eq(DiaryPost::getStatus, "published")
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPriority)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.page(page, wrapper);
|
||||
public DiaryPostResponse createDiaryPostWithResponse(DiaryPostCreateRequest request) {
|
||||
// 处理标题:如果为空,则设置为null或生成默认标题
|
||||
String title = request.getTitle();
|
||||
if (title == null || title.trim().isEmpty()) {
|
||||
// 可以选择设置为null,或者生成一个默认标题
|
||||
// 这里我们设置为null,让数据库使用默认值
|
||||
title = null;
|
||||
}
|
||||
|
||||
DiaryPost diaryPost = DiaryPost.builder()
|
||||
.id(snowflakeIdGenerator.nextIdAsString()) // 使用雪花算法生成ID
|
||||
.userId(request.getUserId())
|
||||
.title(title)
|
||||
.content(request.getContent())
|
||||
.images(convertListToJson(request.getImages()))
|
||||
.videos(convertListToJson(request.getVideos()))
|
||||
.location(request.getLocation())
|
||||
.weather(request.getWeather())
|
||||
.mood(request.getMood())
|
||||
.tags(convertListToJson(request.getTags()))
|
||||
.isPublic(request.getIsPublic())
|
||||
.isAnonymous(request.getIsAnonymous())
|
||||
.viewCount(0)
|
||||
.likeCount(0)
|
||||
.commentCount(0)
|
||||
.shareCount(0)
|
||||
.publishTime(LocalDateTime.now())
|
||||
.status("published")
|
||||
.priority(0)
|
||||
.featured(0)
|
||||
.build();
|
||||
|
||||
this.save(diaryPost);
|
||||
return convertToResponse(diaryPost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<DiaryPost> getFeaturedPage(BasePageRequest request) {
|
||||
Page<DiaryPost> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getFeatured, 1)
|
||||
.eq(DiaryPost::getIsPublic, 1)
|
||||
.eq(DiaryPost::getStatus, "published")
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPriority)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.page(page, wrapper);
|
||||
public DiaryPostResponse updateDiaryPostWithResponse(DiaryPostUpdateRequest request) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, request.getId())
|
||||
.set(StringUtils.hasText(request.getTitle()), DiaryPost::getTitle, request.getTitle())
|
||||
.set(StringUtils.hasText(request.getContent()), DiaryPost::getContent, request.getContent())
|
||||
.set(request.getImages() != null, DiaryPost::getImages, convertListToJson(request.getImages()))
|
||||
.set(request.getVideos() != null, DiaryPost::getVideos, convertListToJson(request.getVideos()))
|
||||
.set(StringUtils.hasText(request.getLocation()), DiaryPost::getLocation, request.getLocation())
|
||||
.set(StringUtils.hasText(request.getWeather()), DiaryPost::getWeather, request.getWeather())
|
||||
.set(StringUtils.hasText(request.getMood()), DiaryPost::getMood, request.getMood())
|
||||
.set(request.getTags() != null, DiaryPost::getTags, convertListToJson(request.getTags()))
|
||||
.set(request.getIsPublic() != null, DiaryPost::getIsPublic, request.getIsPublic())
|
||||
.set(request.getIsAnonymous() != null, DiaryPost::getIsAnonymous, request.getIsAnonymous())
|
||||
.set(StringUtils.hasText(request.getStatus()), DiaryPost::getStatus, request.getStatus())
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
|
||||
boolean updated = this.update(wrapper);
|
||||
if (!updated) {
|
||||
return null;
|
||||
}
|
||||
DiaryPost updatedDiaryPost = this.getById(request.getId());
|
||||
return convertToResponse(updatedDiaryPost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryPost> getByStatus(String status) {
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getStatus, status)
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.list(wrapper);
|
||||
public boolean deleteDiaryPost(String diaryId) {
|
||||
return this.removeById(diaryId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryPost> getByUserIdAndStatus(String userId, String status) {
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getUserId, userId)
|
||||
.eq(DiaryPost::getStatus, status)
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.list(wrapper);
|
||||
public boolean softDeleteDiaryPost(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getIsDeleted, 1)
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryPost> getByMood(String mood) {
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getMood, mood)
|
||||
.eq(DiaryPost::getIsPublic, 1)
|
||||
.eq(DiaryPost::getStatus, "published")
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryPost> getByTags(List<String> tags) {
|
||||
// 这里需要根据实际需求实现标签查询逻辑
|
||||
// 由于tags字段是JSON格式,可能需要使用数据库的JSON查询功能
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getIsPublic, 1)
|
||||
.eq(DiaryPost::getStatus, "published")
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiaryPost> getByLocation(String location) {
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(DiaryPost::getLocation, location)
|
||||
.eq(DiaryPost::getIsPublic, 1)
|
||||
.eq(DiaryPost::getStatus, "published")
|
||||
.eq(DiaryPost::getIsDeleted, 0)
|
||||
.orderByDesc(DiaryPost::getPublishTime);
|
||||
return this.list(wrapper);
|
||||
public boolean restoreDiaryPost(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getIsDeleted, 0)
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incrementViewCount(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.setSql("view_count = view_count + 1");
|
||||
.setSql("view_count = view_count + 1")
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -152,7 +199,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean incrementLikeCount(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.setSql("like_count = like_count + 1");
|
||||
.setSql("like_count = like_count + 1")
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -160,7 +208,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean decrementLikeCount(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.setSql("like_count = GREATEST(like_count - 1, 0)");
|
||||
.setSql("like_count = GREATEST(like_count - 1, 0)")
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -168,7 +217,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean incrementCommentCount(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.setSql("comment_count = comment_count + 1");
|
||||
.setSql("comment_count = comment_count + 1")
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -176,7 +226,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean decrementCommentCount(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.setSql("comment_count = GREATEST(comment_count - 1, 0)");
|
||||
.setSql("comment_count = GREATEST(comment_count - 1, 0)")
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -184,7 +235,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean incrementShareCount(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.setSql("share_count = share_count + 1");
|
||||
.setSql("share_count = share_count + 1")
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -192,7 +244,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean updateLastCommentTime(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getLastCommentTime, LocalDateTime.now());
|
||||
.set(DiaryPost::getLastCommentTime, LocalDateTime.now())
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -200,7 +253,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean setFeatured(String diaryId, Integer featured) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getFeatured, featured);
|
||||
.set(DiaryPost::getFeatured, featured)
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -208,7 +262,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
public boolean setPriority(String diaryId, Integer priority) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getPriority, priority);
|
||||
.set(DiaryPost::getPriority, priority)
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@@ -239,26 +294,12 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByStatus(String status) {
|
||||
LambdaQueryWrapper<DiaryPost> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DiaryPost::getStatus, status)
|
||||
.eq(DiaryPost::getIsDeleted, 0);
|
||||
return this.count(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiaryPost createDiaryPost(com.emotion.dto.request.DiaryPostCreateRequest request) {
|
||||
// 处理标题:如果为空,则设置为null或生成默认标题
|
||||
String title = request.getTitle();
|
||||
if (title == null || title.trim().isEmpty()) {
|
||||
// 可以选择设置为null,或者生成一个默认标题
|
||||
// 这里我们设置为null,让数据库使用默认值
|
||||
title = null;
|
||||
}
|
||||
|
||||
public DiaryPostResponse publishDiaryWithAiComment(DiaryPostCreateRequest request) {
|
||||
// 1. 保存日记
|
||||
DiaryPost diaryPost = DiaryPost.builder()
|
||||
.id(snowflakeIdGenerator.nextIdAsString()) // 使用雪花算法生成ID
|
||||
.userId(request.getUserId())
|
||||
.title(title)
|
||||
.title(request.getTitle())
|
||||
.content(request.getContent())
|
||||
.images(convertListToJson(request.getImages()))
|
||||
.videos(convertListToJson(request.getVideos()))
|
||||
@@ -277,69 +318,8 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
.priority(0)
|
||||
.featured(0)
|
||||
.build();
|
||||
|
||||
this.save(diaryPost);
|
||||
return diaryPost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateDiaryPost(String diaryId, com.emotion.dto.request.DiaryPostUpdateRequest request) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(StringUtils.hasText(request.getTitle()), DiaryPost::getTitle, request.getTitle())
|
||||
.set(StringUtils.hasText(request.getContent()), DiaryPost::getContent, request.getContent())
|
||||
.set(request.getImages() != null, DiaryPost::getImages, convertListToJson(request.getImages()))
|
||||
.set(request.getVideos() != null, DiaryPost::getVideos, convertListToJson(request.getVideos()))
|
||||
.set(StringUtils.hasText(request.getLocation()), DiaryPost::getLocation, request.getLocation())
|
||||
.set(StringUtils.hasText(request.getWeather()), DiaryPost::getWeather, request.getWeather())
|
||||
.set(StringUtils.hasText(request.getMood()), DiaryPost::getMood, request.getMood())
|
||||
.set(request.getTags() != null, DiaryPost::getTags, convertListToJson(request.getTags()))
|
||||
.set(request.getIsPublic() != null, DiaryPost::getIsPublic, request.getIsPublic())
|
||||
.set(request.getIsAnonymous() != null, DiaryPost::getIsAnonymous, request.getIsAnonymous())
|
||||
.set(StringUtils.hasText(request.getStatus()), DiaryPost::getStatus, request.getStatus());
|
||||
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteDiaryPost(String diaryId) {
|
||||
return this.removeById(diaryId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean softDeleteDiaryPost(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getIsDeleted, 1);
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreDiaryPost(String diaryId) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getIsDeleted, 0);
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAiComment(String diaryId, String aiComment, Object aiEmotionAnalysis,
|
||||
BigDecimal aiSentimentScore, List<String> aiKeywords, String aiSuggestions) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getAiComment, aiComment)
|
||||
.set(DiaryPost::getAiCommentTime, LocalDateTime.now())
|
||||
.set(DiaryPost::getAiEmotionAnalysis, convertObjectToJson(aiEmotionAnalysis))
|
||||
.set(DiaryPost::getAiSentimentScore, aiSentimentScore)
|
||||
.set(DiaryPost::getAiKeywords, convertListToJson(aiKeywords))
|
||||
.set(DiaryPost::getAiSuggestions, aiSuggestions);
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.emotion.dto.response.DiaryPostResponse publishDiaryWithAiComment(com.emotion.dto.request.DiaryPostCreateRequest request) {
|
||||
// 1. 保存日记
|
||||
DiaryPost diaryPost = createDiaryPost(request);
|
||||
// 2. 生成AI评论
|
||||
String aiComment = null;
|
||||
try {
|
||||
@@ -350,13 +330,14 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
}
|
||||
// 3. 写入AI评论到diary_comment表
|
||||
if (aiComment != null) {
|
||||
diaryCommentService.createAiComment(
|
||||
diaryPost.getId(),
|
||||
aiComment,
|
||||
"diary_ai_summary",
|
||||
null,
|
||||
null
|
||||
);
|
||||
// 使用createCommentWithResponse方法创建AI评论
|
||||
com.emotion.dto.request.DiaryCommentCreateRequest commentRequest = new com.emotion.dto.request.DiaryCommentCreateRequest();
|
||||
commentRequest.setDiaryId(diaryPost.getId());
|
||||
commentRequest.setUserId("system"); // AI评论使用system用户ID
|
||||
commentRequest.setContent(aiComment);
|
||||
commentRequest.setIsAnonymous(0);
|
||||
diaryCommentService.createCommentWithResponse(commentRequest);
|
||||
|
||||
addAiComment(
|
||||
diaryPost.getId(),
|
||||
aiComment,
|
||||
@@ -367,53 +348,37 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
);
|
||||
}
|
||||
// 4. 返回日记详情(含AI评论)
|
||||
com.emotion.dto.response.DiaryPostResponse response = new com.emotion.dto.response.DiaryPostResponse();
|
||||
org.springframework.beans.BeanUtils.copyProperties(diaryPost, response);
|
||||
// 查询AI评论
|
||||
List<com.emotion.entity.DiaryComment> aiComments = diaryCommentService.getByDiaryIdAndCommentType(diaryPost.getId(), "ai");
|
||||
if (!aiComments.isEmpty()) {
|
||||
response.setAiComment(aiComments.get(0).getContent());
|
||||
}
|
||||
// 转换时间格式
|
||||
if (diaryPost.getPublishTime() != null) {
|
||||
response.setPublishTime(diaryPost.getPublishTime().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
}
|
||||
if (diaryPost.getLastCommentTime() != null) {
|
||||
response.setLastCommentTime(diaryPost.getLastCommentTime().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
}
|
||||
if (diaryPost.getAiCommentTime() != null) {
|
||||
response.setAiCommentTime(diaryPost.getAiCommentTime().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
}
|
||||
if (diaryPost.getCreateTime() != null) {
|
||||
response.setCreateTime(diaryPost.getCreateTime().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
}
|
||||
if (diaryPost.getUpdateTime() != null) {
|
||||
response.setUpdateTime(diaryPost.getUpdateTime().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
}
|
||||
// 转换JSON字段
|
||||
try {
|
||||
if (diaryPost.getImages() != null) {
|
||||
response.setImages(objectMapper.readValue(diaryPost.getImages(), new com.fasterxml.jackson.core.type.TypeReference<List<String>>() {}));
|
||||
}
|
||||
if (diaryPost.getVideos() != null) {
|
||||
response.setVideos(objectMapper.readValue(diaryPost.getVideos(), new com.fasterxml.jackson.core.type.TypeReference<List<String>>() {}));
|
||||
}
|
||||
if (diaryPost.getTags() != null) {
|
||||
response.setTags(objectMapper.readValue(diaryPost.getTags(), new com.fasterxml.jackson.core.type.TypeReference<List<String>>() {}));
|
||||
}
|
||||
if (diaryPost.getAiKeywords() != null) {
|
||||
response.setAiKeywords(objectMapper.readValue(diaryPost.getAiKeywords(), new com.fasterxml.jackson.core.type.TypeReference<List<String>>() {}));
|
||||
}
|
||||
if (diaryPost.getAiEmotionAnalysis() != null) {
|
||||
response.setAiEmotionAnalysis(objectMapper.readValue(diaryPost.getAiEmotionAnalysis(), Object.class));
|
||||
}
|
||||
if (diaryPost.getMetadata() != null) {
|
||||
response.setMetadata(objectMapper.readValue(diaryPost.getMetadata(), Object.class));
|
||||
}
|
||||
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
|
||||
// 忽略JSON解析错误
|
||||
}
|
||||
return response;
|
||||
return convertToResponse(diaryPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加AI评论
|
||||
*/
|
||||
private boolean addAiComment(String diaryId, String aiComment, Object aiEmotionAnalysis,
|
||||
BigDecimal aiSentimentScore, List<String> aiKeywords, String aiSuggestions) {
|
||||
LambdaUpdateWrapper<DiaryPost> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.eq(DiaryPost::getId, diaryId)
|
||||
.set(DiaryPost::getAiComment, aiComment)
|
||||
.set(DiaryPost::getAiCommentTime, LocalDateTime.now())
|
||||
.set(DiaryPost::getAiEmotionAnalysis, convertObjectToJson(aiEmotionAnalysis))
|
||||
.set(DiaryPost::getAiSentimentScore, aiSentimentScore)
|
||||
.set(DiaryPost::getAiKeywords, convertListToJson(aiKeywords))
|
||||
.set(DiaryPost::getAiSuggestions, aiSuggestions)
|
||||
.set(DiaryPost::getUpdateTime, LocalDateTime.now());
|
||||
return this.update(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建PageResult对象
|
||||
*/
|
||||
private <T> PageResult<T> createPageResult(IPage<?> page, List<T> records) {
|
||||
PageResult<T> pageResult = new PageResult<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setRecords(records);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,4 +408,60 @@ public class DiaryPostServiceImpl extends ServiceImpl<DiaryPostMapper, DiaryPost
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换实体为响应DTO
|
||||
*/
|
||||
private DiaryPostResponse convertToResponse(DiaryPost diaryPost) {
|
||||
DiaryPostResponse response = new DiaryPostResponse();
|
||||
BeanUtils.copyProperties(diaryPost, response);
|
||||
|
||||
// 转换时间格式
|
||||
if (diaryPost.getPublishTime() != null) {
|
||||
response.setPublishTime(diaryPost.getPublishTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (diaryPost.getLastCommentTime() != null) {
|
||||
response.setLastCommentTime(diaryPost.getLastCommentTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (diaryPost.getAiCommentTime() != null) {
|
||||
response.setAiCommentTime(diaryPost.getAiCommentTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (diaryPost.getCreateTime() != null) {
|
||||
response.setCreateTime(diaryPost.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (diaryPost.getUpdateTime() != null) {
|
||||
response.setUpdateTime(diaryPost.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
|
||||
// 转换JSON字段
|
||||
try {
|
||||
if (diaryPost.getImages() != null) {
|
||||
response.setImages(objectMapper.readValue(diaryPost.getImages(), new TypeReference<List<String>>() {
|
||||
}));
|
||||
}
|
||||
if (diaryPost.getVideos() != null) {
|
||||
response.setVideos(objectMapper.readValue(diaryPost.getVideos(), new TypeReference<List<String>>() {
|
||||
}));
|
||||
}
|
||||
if (diaryPost.getTags() != null) {
|
||||
response.setTags(objectMapper.readValue(diaryPost.getTags(), new TypeReference<List<String>>() {
|
||||
}));
|
||||
}
|
||||
if (diaryPost.getAiKeywords() != null) {
|
||||
response.setAiKeywords(
|
||||
objectMapper.readValue(diaryPost.getAiKeywords(), new TypeReference<List<String>>() {
|
||||
}));
|
||||
}
|
||||
if (diaryPost.getAiEmotionAnalysis() != null) {
|
||||
response.setAiEmotionAnalysis(objectMapper.readValue(diaryPost.getAiEmotionAnalysis(), Object.class));
|
||||
}
|
||||
if (diaryPost.getMetadata() != null) {
|
||||
response.setMetadata(objectMapper.readValue(diaryPost.getMetadata(), Object.class));
|
||||
}
|
||||
} catch (JsonProcessingException e) {
|
||||
// 忽略JSON解析错误
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
+174
@@ -5,15 +5,25 @@ 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.common.PageResult;
|
||||
import com.emotion.dto.request.EmotionAnalysisCreateRequest;
|
||||
import com.emotion.dto.request.EmotionAnalysisPageRequest;
|
||||
import com.emotion.dto.request.EmotionAnalysisUpdateRequest;
|
||||
import com.emotion.dto.response.EmotionAnalysisResponse;
|
||||
import com.emotion.entity.EmotionAnalysis;
|
||||
import com.emotion.mapper.EmotionAnalysisMapper;
|
||||
import com.emotion.service.EmotionAnalysisService;
|
||||
import com.emotion.util.SnowflakeIdGenerator;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
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.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 情绪分析服务实现类
|
||||
@@ -24,6 +34,11 @@ import java.util.List;
|
||||
@Service
|
||||
public class EmotionAnalysisServiceImpl extends ServiceImpl<EmotionAnalysisMapper, EmotionAnalysis> implements EmotionAnalysisService {
|
||||
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<EmotionAnalysis> getPage(BasePageRequest request) {
|
||||
Page<EmotionAnalysis> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
@@ -173,6 +188,7 @@ public class EmotionAnalysisServiceImpl extends ServiceImpl<EmotionAnalysisMappe
|
||||
public EmotionAnalysis createEmotionAnalysis(String messageId, String userId, String primaryEmotion,
|
||||
String polarity, Double intensity, Double confidence) {
|
||||
EmotionAnalysis analysis = new EmotionAnalysis();
|
||||
analysis.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID
|
||||
analysis.setMessageId(messageId);
|
||||
analysis.setCreateBy(userId);
|
||||
analysis.setPrimaryEmotion(primaryEmotion);
|
||||
@@ -183,4 +199,162 @@ public class EmotionAnalysisServiceImpl extends ServiceImpl<EmotionAnalysisMappe
|
||||
this.save(analysis);
|
||||
return analysis;
|
||||
}
|
||||
|
||||
// 新增的方法实现
|
||||
|
||||
@Override
|
||||
public PageResult<EmotionAnalysisResponse> getPageWithResponse(EmotionAnalysisPageRequest request) {
|
||||
IPage<EmotionAnalysis> page = getPage(request);
|
||||
List<EmotionAnalysisResponse> responses = page.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
return createPageResult(page, responses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<EmotionAnalysisResponse> getPageByUserIdWithResponse(String userId,
|
||||
EmotionAnalysisPageRequest request) {
|
||||
IPage<EmotionAnalysis> page = getPageByUserId(request, userId);
|
||||
List<EmotionAnalysisResponse> responses = page.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
return createPageResult(page, responses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmotionAnalysisResponse getEmotionAnalysisResponseById(String id) {
|
||||
EmotionAnalysis analysis = this.getById(id);
|
||||
if (analysis == null) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(analysis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmotionAnalysisResponse getEmotionAnalysisResponseByMessageId(String messageId) {
|
||||
EmotionAnalysis analysis = getByMessageId(messageId);
|
||||
if (analysis == null) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(analysis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmotionAnalysisResponse createEmotionAnalysisWithResponse(EmotionAnalysisCreateRequest request) {
|
||||
EmotionAnalysis analysis = createEmotionAnalysis(
|
||||
request.getMessageId(),
|
||||
request.getUserId(),
|
||||
request.getPrimaryEmotion(),
|
||||
request.getPolarity(),
|
||||
request.getIntensity(),
|
||||
request.getConfidence());
|
||||
return convertToResponse(analysis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmotionAnalysisResponse updateEmotionAnalysisWithResponse(EmotionAnalysisUpdateRequest request) {
|
||||
EmotionAnalysis analysis = this.getById(request.getId());
|
||||
if (analysis == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 更新字段
|
||||
if (request.getMessageId() != null) {
|
||||
analysis.setMessageId(request.getMessageId());
|
||||
}
|
||||
if (request.getUserId() != null) {
|
||||
analysis.setCreateBy(request.getUserId());
|
||||
}
|
||||
if (request.getPrimaryEmotion() != null) {
|
||||
analysis.setPrimaryEmotion(request.getPrimaryEmotion());
|
||||
}
|
||||
if (request.getPolarity() != null) {
|
||||
analysis.setPolarity(request.getPolarity());
|
||||
}
|
||||
if (request.getIntensity() != null) {
|
||||
analysis.setIntensity(BigDecimal.valueOf(request.getIntensity()));
|
||||
}
|
||||
if (request.getConfidence() != null) {
|
||||
analysis.setConfidence(BigDecimal.valueOf(request.getConfidence()));
|
||||
}
|
||||
|
||||
this.updateById(analysis);
|
||||
return convertToResponse(analysis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteEmotionAnalysis(String id) {
|
||||
return this.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmotionAnalysisResponse> getEmotionAnalysisResponsesByPrimaryEmotion(String primaryEmotion) {
|
||||
List<EmotionAnalysis> analyses = getByPrimaryEmotion(primaryEmotion);
|
||||
return analyses.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmotionAnalysisResponse> getEmotionAnalysisResponsesByPolarity(String polarity) {
|
||||
List<EmotionAnalysis> analyses = getByPolarity(polarity);
|
||||
return analyses.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmotionAnalysisResponse> getEmotionAnalysisResponsesByUserIdAndEmotion(String userId,
|
||||
String primaryEmotion) {
|
||||
List<EmotionAnalysis> analyses = getByUserIdAndEmotion(userId, primaryEmotion);
|
||||
return analyses.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmotionAnalysisResponse> getEmotionAnalysisResponsesByUserIdAndTimeRange(String userId,
|
||||
LocalDateTime startTime, LocalDateTime endTime) {
|
||||
List<EmotionAnalysis> analyses = getByUserIdAndTimeRange(userId, startTime, endTime);
|
||||
return analyses.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmotionAnalysisResponse> getEmotionAnalysisResponsesRecentByUserId(String userId, Integer limit) {
|
||||
List<EmotionAnalysis> analyses = getRecentByUserId(userId, limit);
|
||||
return analyses.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建PageResult对象
|
||||
*/
|
||||
private <T> PageResult<T> createPageResult(IPage<?> page, List<T> records) {
|
||||
PageResult<T> pageResult = new PageResult<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setRecords(records);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为响应对象
|
||||
*/
|
||||
private EmotionAnalysisResponse convertToResponse(EmotionAnalysis analysis) {
|
||||
EmotionAnalysisResponse response = new EmotionAnalysisResponse();
|
||||
BeanUtils.copyProperties(analysis, response);
|
||||
response.setId(analysis.getId());
|
||||
if (analysis.getCreateTime() != null) {
|
||||
response.setCreateTime(analysis.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (analysis.getUpdateTime() != null) {
|
||||
response.setUpdateTime(analysis.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
+282
-6
@@ -5,17 +5,29 @@ 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.common.PageResult;
|
||||
import com.emotion.dto.request.EmotionRecordCreateRequest;
|
||||
import com.emotion.dto.request.EmotionRecordPageRequest;
|
||||
import com.emotion.dto.request.EmotionRecordUpdateRequest;
|
||||
import com.emotion.dto.response.EmotionRecordResponse;
|
||||
import com.emotion.entity.EmotionRecord;
|
||||
import com.emotion.mapper.EmotionRecordMapper;
|
||||
import com.emotion.service.EmotionRecordService;
|
||||
import com.emotion.util.SnowflakeIdGenerator;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 情绪记录服务实现类
|
||||
@@ -26,6 +38,11 @@ import java.util.Collections;
|
||||
@Service
|
||||
public class EmotionRecordServiceImpl extends ServiceImpl<EmotionRecordMapper, EmotionRecord> implements EmotionRecordService {
|
||||
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public IPage<EmotionRecord> getPage(BasePageRequest request) {
|
||||
Page<EmotionRecord> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
@@ -134,20 +151,59 @@ public class EmotionRecordServiceImpl extends ServiceImpl<EmotionRecordMapper, E
|
||||
|
||||
@Override
|
||||
public Double getAvgIntensityByUserId(String userId) {
|
||||
// 这里需要自定义SQL查询平均值,暂时返回0
|
||||
return 0.0;
|
||||
LambdaQueryWrapper<EmotionRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(EmotionRecord::getUserId, userId)
|
||||
.eq(EmotionRecord::getIsDeleted, 0);
|
||||
|
||||
List<EmotionRecord> records = this.list(wrapper);
|
||||
if (records.isEmpty()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double sum = records.stream()
|
||||
.mapToDouble(record -> record.getIntensity().doubleValue())
|
||||
.sum();
|
||||
|
||||
return sum / records.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAvgIntensityByUserIdAndTimeRange(String userId, LocalDateTime startTime, LocalDateTime endTime) {
|
||||
// 这里需要自定义SQL查询平均值,暂时返回0
|
||||
return 0.0;
|
||||
LambdaQueryWrapper<EmotionRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(EmotionRecord::getUserId, userId)
|
||||
.between(EmotionRecord::getCreateTime, startTime, endTime)
|
||||
.eq(EmotionRecord::getIsDeleted, 0);
|
||||
|
||||
List<EmotionRecord> records = this.list(wrapper);
|
||||
if (records.isEmpty()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double sum = records.stream()
|
||||
.mapToDouble(record -> record.getIntensity().doubleValue())
|
||||
.sum();
|
||||
|
||||
return sum / records.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMostFrequentEmotionByUserId(String userId) {
|
||||
// 这里需要自定义SQL查询最常见的情绪类型,暂时返回null
|
||||
return null;
|
||||
LambdaQueryWrapper<EmotionRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(EmotionRecord::getUserId, userId)
|
||||
.eq(EmotionRecord::getIsDeleted, 0);
|
||||
|
||||
List<EmotionRecord> records = this.list(wrapper);
|
||||
if (records.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return records.stream()
|
||||
.collect(Collectors.groupingBy(EmotionRecord::getEmotionType, Collectors.counting()))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.max(Map.Entry.comparingByValue())
|
||||
.map(Map.Entry::getKey)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -181,6 +237,7 @@ public class EmotionRecordServiceImpl extends ServiceImpl<EmotionRecordMapper, E
|
||||
public EmotionRecord createEmotionRecord(String userId, String emotionType, Double intensity,
|
||||
String trigger, String location, String notes) {
|
||||
EmotionRecord record = new EmotionRecord();
|
||||
record.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID
|
||||
record.setUserId(userId);
|
||||
record.setEmotionType(emotionType);
|
||||
record.setIntensity(BigDecimal.valueOf(intensity));
|
||||
@@ -204,4 +261,223 @@ public class EmotionRecordServiceImpl extends ServiceImpl<EmotionRecordMapper, E
|
||||
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
// 新增的方法实现
|
||||
|
||||
@Override
|
||||
public PageResult<EmotionRecordResponse> getPageWithResponse(EmotionRecordPageRequest request) {
|
||||
IPage<EmotionRecord> page = getPage(request);
|
||||
List<EmotionRecordResponse> responses = page.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
PageResult<EmotionRecordResponse> pageResult = new PageResult<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setRecords(responses);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<EmotionRecordResponse> getPageByUserIdWithResponse(String userId, EmotionRecordPageRequest request) {
|
||||
IPage<EmotionRecord> page = getPageByUserId(request, userId);
|
||||
List<EmotionRecordResponse> responses = page.getRecords().stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
PageResult<EmotionRecordResponse> pageResult = new PageResult<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setRecords(responses);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmotionRecordResponse getEmotionRecordResponseById(String id) {
|
||||
EmotionRecord record = this.getById(id);
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
return convertToResponse(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmotionRecordResponse createEmotionRecordWithResponse(EmotionRecordCreateRequest request) {
|
||||
EmotionRecord record = new EmotionRecord();
|
||||
record.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID
|
||||
record.setUserId(request.getUserId());
|
||||
record.setRecordDate(request.getRecordDate());
|
||||
record.setEmotionType(request.getEmotionType());
|
||||
record.setIntensity(request.getIntensity());
|
||||
record.setTriggers(request.getTriggers());
|
||||
record.setDescription(request.getDescription());
|
||||
// 注意:tags字段在实体类中是String类型,需要转换
|
||||
record.setTags(request.getTags() != null ? request.getTags().toString() : null);
|
||||
record.setWeather(request.getWeather());
|
||||
record.setLocation(request.getLocation());
|
||||
record.setActivity(request.getActivity());
|
||||
record.setPeople(request.getPeople());
|
||||
record.setNotes(request.getNotes());
|
||||
|
||||
this.save(record);
|
||||
return convertToResponse(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmotionRecordResponse updateEmotionRecordWithResponse(EmotionRecordUpdateRequest request) {
|
||||
EmotionRecord record = this.getById(request.getId());
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 更新字段
|
||||
if (request.getRecordDate() != null) {
|
||||
record.setRecordDate(request.getRecordDate());
|
||||
}
|
||||
if (request.getEmotionType() != null) {
|
||||
record.setEmotionType(request.getEmotionType());
|
||||
}
|
||||
if (request.getIntensity() != null) {
|
||||
record.setIntensity(request.getIntensity());
|
||||
}
|
||||
if (request.getTriggers() != null) {
|
||||
record.setTriggers(request.getTriggers());
|
||||
}
|
||||
if (request.getDescription() != null) {
|
||||
record.setDescription(request.getDescription());
|
||||
}
|
||||
// 注意:tags字段在实体类中是String类型,需要转换
|
||||
if (request.getTags() != null) {
|
||||
record.setTags(request.getTags().toString());
|
||||
}
|
||||
if (request.getWeather() != null) {
|
||||
record.setWeather(request.getWeather());
|
||||
}
|
||||
if (request.getLocation() != null) {
|
||||
record.setLocation(request.getLocation());
|
||||
}
|
||||
if (request.getActivity() != null) {
|
||||
record.setActivity(request.getActivity());
|
||||
}
|
||||
if (request.getPeople() != null) {
|
||||
record.setPeople(request.getPeople());
|
||||
}
|
||||
if (request.getNotes() != null) {
|
||||
record.setNotes(request.getNotes());
|
||||
}
|
||||
|
||||
this.updateById(record);
|
||||
return convertToResponse(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteEmotionRecord(String id) {
|
||||
return this.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getEmotionStats(String userId, String startDate, String endDate) {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
// 构建查询条件
|
||||
LambdaQueryWrapper<EmotionRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(EmotionRecord::getUserId, userId)
|
||||
.eq(EmotionRecord::getIsDeleted, 0);
|
||||
|
||||
// 如果提供了日期范围,则添加时间条件
|
||||
if (StringUtils.hasText(startDate) && StringUtils.hasText(endDate)) {
|
||||
try {
|
||||
LocalDateTime start = LocalDate.parse(startDate).atStartOfDay();
|
||||
LocalDateTime end = LocalDate.parse(endDate).atTime(23, 59, 59);
|
||||
wrapper.between(EmotionRecord::getCreateTime, start, end);
|
||||
} catch (Exception e) {
|
||||
// 如果日期解析失败,忽略日期条件
|
||||
}
|
||||
}
|
||||
|
||||
// 查询用户的所有情绪记录
|
||||
List<EmotionRecord> records = this.list(wrapper);
|
||||
|
||||
if (records.isEmpty()) {
|
||||
stats.put("emotionDistribution", new HashMap<>());
|
||||
stats.put("totalRecords", 0);
|
||||
stats.put("averageIntensity", 0.0);
|
||||
stats.put("mostFrequentEmotion", null);
|
||||
stats.put("emotionTrend", "no_data");
|
||||
return stats;
|
||||
}
|
||||
|
||||
// 情绪类型分布
|
||||
Map<String, Long> emotionDistribution = records.stream()
|
||||
.collect(Collectors.groupingBy(EmotionRecord::getEmotionType, Collectors.counting()));
|
||||
|
||||
stats.put("emotionDistribution", emotionDistribution);
|
||||
stats.put("totalRecords", records.size());
|
||||
|
||||
// 平均情绪强度
|
||||
double avgIntensity = records.stream()
|
||||
.mapToDouble(record -> record.getIntensity().doubleValue())
|
||||
.average()
|
||||
.orElse(0.0);
|
||||
stats.put("averageIntensity", avgIntensity);
|
||||
|
||||
// 最常见的情绪类型
|
||||
String mostFrequentEmotion = emotionDistribution.entrySet().stream()
|
||||
.max(Map.Entry.comparingByValue())
|
||||
.map(Map.Entry::getKey)
|
||||
.orElse(null);
|
||||
stats.put("mostFrequentEmotion", mostFrequentEmotion);
|
||||
|
||||
// 情绪趋势(简单实现:比较前半段和后半段的平均强度)
|
||||
if (records.size() > 1) {
|
||||
int mid = records.size() / 2;
|
||||
double firstHalfAvg = records.subList(0, mid).stream()
|
||||
.mapToDouble(record -> record.getIntensity().doubleValue())
|
||||
.average()
|
||||
.orElse(0.0);
|
||||
|
||||
double secondHalfAvg = records.subList(mid, records.size()).stream()
|
||||
.mapToDouble(record -> record.getIntensity().doubleValue())
|
||||
.average()
|
||||
.orElse(0.0);
|
||||
|
||||
if (secondHalfAvg > firstHalfAvg) {
|
||||
stats.put("emotionTrend", "improving");
|
||||
} else if (secondHalfAvg < firstHalfAvg) {
|
||||
stats.put("emotionTrend", "declining");
|
||||
} else {
|
||||
stats.put("emotionTrend", "stable");
|
||||
}
|
||||
} else {
|
||||
stats.put("emotionTrend", "insufficient_data");
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmotionRecordResponse> getRecentByUserIdWithResponse(String userId, Integer limit) {
|
||||
List<EmotionRecord> records = getRecentByUserId(userId, limit);
|
||||
return records.stream()
|
||||
.map(this::convertToResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为响应对象
|
||||
*/
|
||||
private EmotionRecordResponse convertToResponse(EmotionRecord record) {
|
||||
EmotionRecordResponse response = new EmotionRecordResponse();
|
||||
BeanUtils.copyProperties(record, response);
|
||||
response.setId(record.getId());
|
||||
if (record.getCreateTime() != null) {
|
||||
response.setCreateTime(record.getCreateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
if (record.getUpdateTime() != null) {
|
||||
response.setUpdateTime(record.getUpdateTime().format(DATE_TIME_FORMATTER));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,13 @@ import com.emotion.dto.response.UserInfoResponse;
|
||||
import com.emotion.exception.TokenException;
|
||||
import com.emotion.service.AuthService;
|
||||
import com.emotion.service.TokenService;
|
||||
import com.emotion.util.TokenUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 令牌服务实现类
|
||||
*
|
||||
@@ -20,15 +23,19 @@ public class TokenServiceImpl implements TokenService {
|
||||
@Autowired
|
||||
private AuthService authService;
|
||||
|
||||
@Autowired
|
||||
private TokenUtil tokenUtil;
|
||||
|
||||
@Override
|
||||
public UserInfoResponse getUserInfoByToken(String token) {
|
||||
String userId = validateTokenAndGetUserId(token);
|
||||
public UserInfoResponse getUserInfoByToken(HttpServletRequest request) {
|
||||
String userId = validateTokenAndGetUserId(request);
|
||||
return authService.getCurrentUserInfo(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsernameByToken(String token) {
|
||||
if (!StringUtils.hasText(token)) {
|
||||
public String getUsernameByToken(HttpServletRequest request) {
|
||||
String token = tokenUtil.extractToken(request);
|
||||
if (!tokenUtil.isValidToken(token)) {
|
||||
throw new TokenException("未提供访问令牌");
|
||||
}
|
||||
|
||||
@@ -45,8 +52,9 @@ public class TokenServiceImpl implements TokenService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validateTokenAndGetUserId(String token) {
|
||||
if (!StringUtils.hasText(token)) {
|
||||
public String validateTokenAndGetUserId(HttpServletRequest request) {
|
||||
String token = tokenUtil.extractToken(request);
|
||||
if (!tokenUtil.isValidToken(token)) {
|
||||
throw new TokenException("未提供访问令牌");
|
||||
}
|
||||
|
||||
@@ -61,4 +69,4 @@ public class TokenServiceImpl implements TokenService {
|
||||
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.emotion.service.impl;
|
||||
|
||||
import com.emotion.dto.request.WebSocketRequest;
|
||||
import com.emotion.dto.websocket.ChatRequest;
|
||||
import com.emotion.dto.websocket.ConnectRequest;
|
||||
import com.emotion.dto.websocket.WebSocketMessage;
|
||||
@@ -13,6 +14,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -48,64 +50,54 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
* 处理聊天消息
|
||||
*/
|
||||
@Override
|
||||
public void handleChatMessage(ChatRequest request, String sessionId, Principal principal) {
|
||||
public void handleChatMessage(WebSocketRequest webSocketRequest, String sessionId, Principal principal) {
|
||||
try {
|
||||
log.info("处理聊天消息: request={}, sessionId={}, principal={}", request, sessionId, principal);
|
||||
log.info("处理聊天消息: request={}, sessionId={}, principal={}", webSocketRequest, sessionId, principal);
|
||||
|
||||
// 验证请求参数
|
||||
if (request.getContent() == null || request.getContent().trim().isEmpty()) {
|
||||
sendErrorMessage(request.getSenderId(), "消息内容不能为空");
|
||||
if (webSocketRequest.getContent() == null || webSocketRequest.getContent().trim().isEmpty()) {
|
||||
sendErrorMessage(getUserId(principal, sessionId), "消息内容不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 确定用户身份和类型
|
||||
String userId = request.getSenderId();
|
||||
WebSocketMessage.SenderType senderType = WebSocketMessage.SenderType.GUEST;
|
||||
// 设置默认值
|
||||
setWebSocketRequestDefaults(webSocketRequest, principal, sessionId);
|
||||
|
||||
if (principal != null) {
|
||||
userId = principal.getName();
|
||||
// 如果用户ID不是以guest_开头,说明是认证用户
|
||||
if (!userId.startsWith("guest_")) {
|
||||
senderType = WebSocketMessage.SenderType.USER;
|
||||
}
|
||||
}
|
||||
log.info("确定用户身份: userId={}, senderType={}", webSocketRequest.getSenderId(),
|
||||
webSocketRequest.getSenderType());
|
||||
|
||||
// 更新请求中的用户信息
|
||||
request.setSenderId(userId);
|
||||
request.setSenderType(senderType == WebSocketMessage.SenderType.USER ? ChatRequest.SenderType.USER
|
||||
: ChatRequest.SenderType.GUEST);
|
||||
|
||||
log.info("确定用户身份: userId={}, senderType={}", userId, senderType);
|
||||
// 转换请求对象
|
||||
ChatRequest chatRequest = convertToChatRequest(webSocketRequest);
|
||||
|
||||
// 构建用户消息
|
||||
WebSocketMessage userMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.conversationId(request.getConversationId())
|
||||
.type(WebSocketMessage.MessageType.TEXT)
|
||||
.content(request.getContent())
|
||||
.senderId(userId)
|
||||
.senderType(senderType)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.conversationId(chatRequest.getConversationId())
|
||||
.type("TEXT")
|
||||
.content(chatRequest.getContent())
|
||||
.senderId(chatRequest.getSenderId())
|
||||
.senderType(getSenderType(chatRequest.getSenderType()))
|
||||
.status("SENT")
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
// 发送用户消息到会话
|
||||
if (request.getConversationId() != null) {
|
||||
messagingTemplate.convertAndSend("/topic/conversation/" + request.getConversationId(), userMessage);
|
||||
if (chatRequest.getConversationId() != null) {
|
||||
messagingTemplate.convertAndSend("/topic/conversation/" + chatRequest.getConversationId(), userMessage);
|
||||
}
|
||||
|
||||
// 发送给用户私有队列
|
||||
messagingTemplate.convertAndSendToUser(request.getSenderId(), "/queue/messages", userMessage);
|
||||
messagingTemplate.convertAndSendToUser(chatRequest.getSenderId(), "/queue/messages", userMessage);
|
||||
|
||||
// 发送AI思考状态
|
||||
sendAiThinkingMessage(request.getSenderId(), request.getConversationId());
|
||||
sendAiThinkingMessage(chatRequest.getSenderId(), chatRequest.getConversationId());
|
||||
|
||||
// 异步调用AI服务
|
||||
processAiResponse(request);
|
||||
processAiResponse(chatRequest);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理聊天消息失败", e);
|
||||
sendErrorMessage(request.getSenderId(), "消息处理失败,请稍后重试");
|
||||
sendErrorMessage(getUserId(principal, sessionId), "消息处理失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,39 +107,27 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
@Override
|
||||
public void handleUserConnect(ConnectRequest request, String sessionId, Principal principal) {
|
||||
try {
|
||||
String userId = request.getUserId();
|
||||
boolean isAuthenticated = false;
|
||||
|
||||
// 优先从Principal获取认证用户信息
|
||||
if (principal != null) {
|
||||
userId = principal.getName();
|
||||
// 检查是否是认证用户(不是访客)
|
||||
isAuthenticated = !userId.startsWith("guest_");
|
||||
}
|
||||
|
||||
// 如果还没有userId,生成访客ID
|
||||
if (userId == null) {
|
||||
userId = "guest_" + sessionId;
|
||||
}
|
||||
// 设置默认值
|
||||
setConnectRequestDefaults(request, principal, sessionId);
|
||||
|
||||
log.info("用户连接WebSocket: userId={}, sessionId={}, authenticated={}",
|
||||
userId, sessionId, isAuthenticated);
|
||||
request.getUserId(), sessionId, isUserAuthenticated(request.getUserId()));
|
||||
|
||||
// 记录在线用户
|
||||
onlineUsers.put(sessionId, userId);
|
||||
onlineUsers.put(sessionId, request.getUserId());
|
||||
|
||||
// 发送连接成功消息
|
||||
WebSocketMessage connectMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.type(WebSocketMessage.MessageType.CONNECTION)
|
||||
.type("CONNECTION")
|
||||
.content("连接成功")
|
||||
.senderId("system")
|
||||
.senderType(WebSocketMessage.SenderType.SYSTEM)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.senderType("SYSTEM")
|
||||
.status("SENT")
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
messagingTemplate.convertAndSendToUser(userId, "/queue/messages", connectMessage);
|
||||
messagingTemplate.convertAndSendToUser(request.getUserId(), "/queue/messages", connectMessage);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理用户连接失败", e);
|
||||
@@ -182,11 +162,11 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
// 发送心跳响应
|
||||
WebSocketMessage heartbeatMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.type(WebSocketMessage.MessageType.HEARTBEAT)
|
||||
.type("HEARTBEAT")
|
||||
.content("pong")
|
||||
.senderId("system")
|
||||
.senderType(WebSocketMessage.SenderType.SYSTEM)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.senderType("SYSTEM")
|
||||
.status("SENT")
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
@@ -206,11 +186,11 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
WebSocketMessage thinkingMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.conversationId(conversationId)
|
||||
.type(WebSocketMessage.MessageType.AI_THINKING)
|
||||
.type("AI_THINKING")
|
||||
.content("AI正在思考中...")
|
||||
.senderId("ai")
|
||||
.senderType(WebSocketMessage.SenderType.AI)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.senderType("AI")
|
||||
.status("SENT")
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
@@ -246,7 +226,7 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
userMessage.setUserId(userId);
|
||||
userMessage.setCreateBy(userId); // 设置创建人为当前用户
|
||||
userMessage
|
||||
.setUserType(request.getSenderType() == ChatRequest.SenderType.USER ? "registered" : "guest");
|
||||
.setUserType("USER".equals(request.getSenderType()) ? "registered" : "guest");
|
||||
userMessage.setContent(request.getContent());
|
||||
userMessage.setType("text");
|
||||
userMessage.setSender("user");
|
||||
@@ -281,11 +261,11 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
private void sendErrorMessage(String userId, String errorContent) {
|
||||
WebSocketMessage errorMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.type(WebSocketMessage.MessageType.ERROR)
|
||||
.type("ERROR")
|
||||
.content(errorContent)
|
||||
.senderId("system")
|
||||
.senderType(WebSocketMessage.SenderType.SYSTEM)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.senderType("SYSTEM")
|
||||
.status("SENT")
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
@@ -309,7 +289,7 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
|
||||
Conversation conversation = Conversation.builder()
|
||||
.userId(userId)
|
||||
.userType(request.getSenderType() == ChatRequest.SenderType.USER ? "registered" : "guest")
|
||||
.userType("USER".equals(request.getSenderType()) ? "registered" : "guest")
|
||||
.title("新对话")
|
||||
.type("chat")
|
||||
.conversationStatus("active")
|
||||
@@ -341,7 +321,7 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
// 如果会话不存在,创建一个
|
||||
conversation = Conversation.builder()
|
||||
.userId(userId)
|
||||
.userType(request.getSenderType() == ChatRequest.SenderType.USER ? "registered" : "guest")
|
||||
.userType("USER".equals(request.getSenderType()) ? "registered" : "guest")
|
||||
.title("对话")
|
||||
.type("chat")
|
||||
.conversationStatus("active")
|
||||
@@ -453,11 +433,11 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
WebSocketMessage fallbackMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.conversationId(conversationId)
|
||||
.type(WebSocketMessage.MessageType.TEXT)
|
||||
.type("TEXT")
|
||||
.content(aiReply)
|
||||
.senderId("ai")
|
||||
.senderType(WebSocketMessage.SenderType.AI)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.senderType("AI")
|
||||
.status("SENT")
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
@@ -488,11 +468,11 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
WebSocketMessage aiMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.conversationId(conversationId)
|
||||
.type(WebSocketMessage.MessageType.TEXT)
|
||||
.type("TEXT")
|
||||
.content(content)
|
||||
.senderId("ai")
|
||||
.senderType(WebSocketMessage.SenderType.AI)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.senderType("AI")
|
||||
.status("SENT")
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
@@ -534,4 +514,95 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
log.debug("没有换行符,返回原始内容");
|
||||
return new String[]{aiReply};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置WebSocket请求的默认值
|
||||
*/
|
||||
private void setWebSocketRequestDefaults(WebSocketRequest request, Principal principal, String sessionId) {
|
||||
// 如果请求中没有发送者ID,尝试从Principal获取
|
||||
if (request.getSenderId() == null && principal != null) {
|
||||
request.setSenderId(principal.getName());
|
||||
}
|
||||
|
||||
// 如果还是没有发送者ID,使用会话ID作为访客ID
|
||||
if (request.getSenderId() == null) {
|
||||
request.setSenderId("guest_" + sessionId);
|
||||
request.setSenderType("GUEST");
|
||||
}
|
||||
|
||||
// 设置时间戳
|
||||
if (request.getTimestamp() == null) {
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置连接请求的默认值
|
||||
*/
|
||||
private void setConnectRequestDefaults(ConnectRequest request, Principal principal, String sessionId) {
|
||||
// 优先从Principal获取认证用户信息
|
||||
if (principal != null) {
|
||||
request.setUserId(principal.getName());
|
||||
}
|
||||
|
||||
// 如果还没有userId,生成访客ID
|
||||
if (request.getUserId() == null) {
|
||||
request.setUserId("guest_" + sessionId);
|
||||
}
|
||||
|
||||
// 设置连接时间戳
|
||||
if (request.getTimestamp() == null) {
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户ID
|
||||
*/
|
||||
private String getUserId(Principal principal, String sessionId) {
|
||||
if (principal != null) {
|
||||
return principal.getName();
|
||||
}
|
||||
return "guest_" + sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否已认证
|
||||
*/
|
||||
private boolean isUserAuthenticated(String userId) {
|
||||
return userId != null && !userId.startsWith("guest_");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取发送者类型
|
||||
*/
|
||||
private String getSenderType(String senderType) {
|
||||
if ("USER".equals(senderType)) {
|
||||
return "USER";
|
||||
} else if ("GUEST".equals(senderType)) {
|
||||
return "GUEST";
|
||||
} else if ("AI".equals(senderType)) {
|
||||
return "AI";
|
||||
} else if ("SYSTEM".equals(senderType)) {
|
||||
return "SYSTEM";
|
||||
}
|
||||
return "USER";
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换WebSocketRequest到ChatRequest
|
||||
*
|
||||
* @param webSocketRequest WebSocket请求对象
|
||||
* @return ChatRequest对象
|
||||
*/
|
||||
private ChatRequest convertToChatRequest(WebSocketRequest webSocketRequest) {
|
||||
return ChatRequest.builder()
|
||||
.content(webSocketRequest.getContent())
|
||||
.senderId(webSocketRequest.getSenderId())
|
||||
.senderType(webSocketRequest.getSenderType())
|
||||
.messageType(webSocketRequest.getMessageType())
|
||||
.conversationId(webSocketRequest.getConversationId())
|
||||
.timestamp(webSocketRequest.getTimestamp())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user