Compare commits

..

2 Commits

8 changed files with 99 additions and 19 deletions

View File

@@ -8,6 +8,7 @@ import com.yolo.keyborad.common.ErrorCode;
import com.yolo.keyborad.common.ResultUtils;
import com.yolo.keyborad.exception.BusinessException;
import com.yolo.keyborad.model.dto.comment.CommentAddReq;
import com.yolo.keyborad.model.dto.comment.CommentDeleteReq;
import com.yolo.keyborad.model.dto.comment.CommentLikeReq;
import com.yolo.keyborad.model.dto.comment.CommentPageReq;
import com.yolo.keyborad.model.dto.comment.CommentReportReq;
@@ -56,6 +57,18 @@ public class AiCompanionCommentController {
return ResultUtils.success(commentId);
}
@PostMapping("/delete")
@Operation(summary = "删除评论", description = "删除当前用户自己发布的评论;若删除根评论,其下回复将不会继续展示")
public BaseResponse<Boolean> deleteComment(@RequestBody CommentDeleteReq req) {
if (req == null || req.getCommentId() == null) {
throw new BusinessException(ErrorCode.COMMENT_ID_EMPTY);
}
Long userId = StpUtil.getLoginIdAsLong();
commentService.deleteComment(userId, req.getCommentId());
return ResultUtils.success(true);
}
@PostMapping("/page")
@Operation(summary = "分页查询评论", description = "分页查询AI陪聊角色的评论列表包含当前用户是否已点赞状态")
public BaseResponse<IPage<CommentVO>> pageComments(@RequestBody CommentPageReq req) {

View File

@@ -0,0 +1,16 @@
package com.yolo.keyborad.model.dto.comment;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/*
* @author: ziin
* @date: 2026/3/20
*/
@Data
@Schema(description = "删除评论请求")
public class CommentDeleteReq {
@Schema(description = "评论ID", requiredMode = Schema.RequiredMode.REQUIRED)
private Long commentId;
}

View File

@@ -22,9 +22,6 @@ public class CommentReportReq {
@Schema(description = "详细描述")
private String reportDesc;
@Schema(description = "评论上下文快照JSON")
private String chatContext;
@Schema(description = "图片证据URL")
private String evidenceImageUrl;
@Schema(description = "评论内容")
private String commentContext;
}

View File

@@ -42,13 +42,9 @@ public class KeyboardAiCommentReport {
@Schema(description = "用户填写的详细举报描述")
private String reportDesc;
@TableField(value = "chat_context")
@TableField(value = "comment_context")
@Schema(description = "评论上下文快照JSON")
private String chatContext;
@TableField(value = "evidence_image_url")
@Schema(description = "图片证据URL")
private String evidenceImageUrl;
private String commentContext;
@TableField(value = "\"status\"")
@Schema(description = "处理状态0=待处理, 1=违规确立, 2=无效举报, 3=已忽略")

View File

@@ -23,6 +23,9 @@ public class CommentVO {
@Schema(description = "发表评论的用户ID")
private Long userId;
@Schema(description = "发表评论的用户UID")
private Long userUid;
@Schema(description = "用户昵称")
private String userName;

View File

@@ -23,6 +23,14 @@ public interface KeyboardAiCompanionCommentService extends IService<KeyboardAiCo
*/
Long addComment(Long userId, Long companionId, String content, Long parentId, Long rootId);
/**
* 删除评论
*
* @param userId 当前用户ID
* @param commentId 评论ID
*/
void deleteComment(Long userId, Long commentId);
/**
* 分页查询评论
*

View File

@@ -69,8 +69,7 @@ public class KeyboardAiCommentReportServiceImpl extends ServiceImpl<KeyboardAiCo
report.setCommentId(req.getCommentId());
report.setReportType(req.getReportTypes().stream().map(String::valueOf).collect(Collectors.joining(",")));
report.setReportDesc(req.getReportDesc());
report.setChatContext(req.getChatContext());
report.setEvidenceImageUrl(req.getEvidenceImageUrl());
report.setCommentContext(req.getCommentContext());
report.setStatus(PENDING_STATUS);
report.setCreatedAt(new Date());
return report;

View File

@@ -1,9 +1,12 @@
package com.yolo.keyborad.service.impl;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.yolo.keyborad.common.ErrorCode;
import com.yolo.keyborad.exception.BusinessException;
import com.yolo.keyborad.mapper.KeyboardAiCompanionCommentMapper;
import com.yolo.keyborad.model.entity.KeyboardAiCompanionComment;
import com.yolo.keyborad.model.entity.KeyboardUser;
@@ -13,10 +16,11 @@ import com.yolo.keyborad.service.KeyboardAiCompanionCommentLikeService;
import com.yolo.keyborad.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -29,6 +33,12 @@ import java.util.stream.Collectors;
@Service
public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardAiCompanionCommentMapper, KeyboardAiCompanionComment> implements KeyboardAiCompanionCommentService {
private static final short ACTIVE_STATUS = 1;
private static final short DELETED_STATUS = -1;
private static final long MAX_REPLY_PREVIEW_COUNT = 999L;
@Resource
private UserService userService;
@@ -43,19 +53,27 @@ public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardA
comment.setContent(content);
comment.setParentId(parentId);
comment.setRootId(rootId);
comment.setStatus((short) 1);
comment.setStatus(ACTIVE_STATUS);
comment.setLikeCount(0);
comment.setCreatedAt(new Date());
this.save(comment);
return comment.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteComment(Long userId, Long commentId) {
KeyboardAiCompanionComment comment = getActiveComment(commentId);
validateDeletePermission(userId, comment.getUserId());
softDeleteComment(commentId);
}
@Override
public IPage<CommentVO> pageComments(Long companionId, Integer pageNum, Integer pageSize) {
Page<KeyboardAiCompanionComment> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<KeyboardAiCompanionComment> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(KeyboardAiCompanionComment::getCompanionId, companionId)
.eq(KeyboardAiCompanionComment::getStatus, 1)
.eq(KeyboardAiCompanionComment::getStatus, ACTIVE_STATUS)
.isNull(KeyboardAiCompanionComment::getParentId)
.orderByDesc(KeyboardAiCompanionComment::getCreatedAt);
IPage<KeyboardAiCompanionComment> entityPage = this.page(page, queryWrapper);
@@ -87,7 +105,7 @@ public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardA
Page<KeyboardAiCompanionComment> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<KeyboardAiCompanionComment> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(KeyboardAiCompanionComment::getCompanionId, companionId)
.eq(KeyboardAiCompanionComment::getStatus, 1)
.eq(KeyboardAiCompanionComment::getStatus, ACTIVE_STATUS)
.isNull(KeyboardAiCompanionComment::getParentId)
.orderByDesc(KeyboardAiCompanionComment::getCreatedAt);
IPage<KeyboardAiCompanionComment> entityPage = this.page(page, queryWrapper);
@@ -105,7 +123,7 @@ public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardA
// 查询所有回复
LambdaQueryWrapper<KeyboardAiCompanionComment> replyWrapper = new LambdaQueryWrapper<>();
replyWrapper.in(KeyboardAiCompanionComment::getRootId, topCommentIds)
.eq(KeyboardAiCompanionComment::getStatus, 1)
.eq(KeyboardAiCompanionComment::getStatus, ACTIVE_STATUS)
.orderByAsc(KeyboardAiCompanionComment::getCreatedAt);
allReplies = this.list(replyWrapper);
@@ -121,7 +139,7 @@ public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardA
repliesMap = repliesMap.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().stream().limit(999).collect(Collectors.toList())
e -> e.getValue().stream().limit(MAX_REPLY_PREVIEW_COUNT).collect(Collectors.toList())
));
}
@@ -178,6 +196,35 @@ public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardA
});
}
private KeyboardAiCompanionComment getActiveComment(Long commentId) {
KeyboardAiCompanionComment comment = this.getById(commentId);
if (comment == null || comment.getStatus() == null || comment.getStatus() != ACTIVE_STATUS) {
throw new BusinessException(ErrorCode.COMMENT_NOT_FOUND);
}
return comment;
}
private void validateDeletePermission(Long userId, Long ownerId) {
if (!userId.equals(ownerId)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
}
private void softDeleteComment(Long commentId) {
KeyboardAiCompanionComment updateEntity = new KeyboardAiCompanionComment();
updateEntity.setStatus(DELETED_STATUS);
updateEntity.setUpdatedAt(new Date());
LambdaUpdateWrapper<KeyboardAiCompanionComment> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(KeyboardAiCompanionComment::getId, commentId)
.eq(KeyboardAiCompanionComment::getStatus, ACTIVE_STATUS);
boolean updated = this.update(updateEntity, updateWrapper);
if (!updated) {
throw new BusinessException(ErrorCode.OPERATION_ERROR, "删除评论失败");
}
}
/**
* 将评论实体转换为VO
*/
@@ -201,6 +248,7 @@ public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardA
// 填充用户信息
KeyboardUser user = userMap.get(entity.getUserId());
if (user != null) {
vo.setUserUid(user.getUid());
vo.setUserName(user.getNickName());
vo.setUserAvatar(user.getAvatarUrl());
}