feat(comment): 新增AI伴侣评论功能并补充相关错误码
This commit is contained in:
@@ -30,6 +30,8 @@ public enum ErrorCode {
|
||||
CHAT_SAVE_DATA_EMPTY(40010, "保存数据不能为空"),
|
||||
COMPANION_MESSAGE_EMPTY(40011, "消息内容不能为空"),
|
||||
COMPANION_ID_EMPTY(40012, "AI陪聊角色ID不能为空"),
|
||||
COMMENT_CONTENT_EMPTY(40013, "评论内容不能为空"),
|
||||
COMMENT_NOT_FOUND(40014, "评论不存在"),
|
||||
TOKEN_NOT_FOUND(40102, "未能读取到有效用户令牌"),
|
||||
TOKEN_INVALID(40103, "令牌无效"),
|
||||
TOKEN_TIMEOUT(40104, "令牌已过期"),
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.yolo.keyborad.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.yolo.keyborad.common.BaseResponse;
|
||||
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.CommentPageReq;
|
||||
import com.yolo.keyborad.model.vo.CommentVO;
|
||||
import com.yolo.keyborad.service.KeyboardAiCompanionCommentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping("/ai-companion/comment")
|
||||
@Tag(name = "AI陪聊角色评论", description = "AI陪聊角色评论管理接口")
|
||||
public class AiCompanionCommentController {
|
||||
|
||||
@Resource
|
||||
private KeyboardAiCompanionCommentService commentService;
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "发表评论", description = "用户对AI陪聊角色发表评论")
|
||||
public BaseResponse<Long> addComment(@RequestBody CommentAddReq req) {
|
||||
if (req.getCompanionId() == null) {
|
||||
throw new BusinessException(ErrorCode.COMPANION_ID_EMPTY);
|
||||
}
|
||||
if (StrUtil.isBlank(req.getContent())) {
|
||||
throw new BusinessException(ErrorCode.COMMENT_CONTENT_EMPTY);
|
||||
}
|
||||
|
||||
Long userId = StpUtil.getLoginIdAsLong();
|
||||
Long commentId = commentService.addComment(userId, req.getCompanionId(), req.getContent(),
|
||||
req.getParentId(), req.getRootId());
|
||||
return ResultUtils.success(commentId);
|
||||
}
|
||||
|
||||
@PostMapping("/page")
|
||||
@Operation(summary = "分页查询评论", description = "分页查询AI陪聊角色的评论列表")
|
||||
public BaseResponse<IPage<CommentVO>> pageComments(@RequestBody CommentPageReq req) {
|
||||
if (req.getCompanionId() == null) {
|
||||
throw new BusinessException(ErrorCode.COMPANION_ID_EMPTY);
|
||||
}
|
||||
|
||||
IPage<CommentVO> result = commentService.pageComments(req.getCompanionId(),
|
||||
req.getPageNum(), req.getPageSize());
|
||||
return ResultUtils.success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.yolo.keyborad.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yolo.keyborad.model.entity.KeyboardAiCompanionComment;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26 20:31
|
||||
*/
|
||||
|
||||
public interface KeyboardAiCompanionCommentMapper extends BaseMapper<KeyboardAiCompanionComment> {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.yolo.keyborad.model.dto.comment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "发表评论请求")
|
||||
public class CommentAddReq {
|
||||
|
||||
@Schema(description = "被评论的AI陪伴角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long companionId;
|
||||
|
||||
@Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String content;
|
||||
|
||||
@Schema(description = "父评论ID,NULL表示一级评论")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "根评论ID,用于标识同一评论线程")
|
||||
private Long rootId;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.yolo.keyborad.model.dto.comment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "评论分页查询请求")
|
||||
public class CommentPageReq {
|
||||
|
||||
@Schema(description = "AI陪伴角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long companionId;
|
||||
|
||||
@Schema(description = "页码", example = "1")
|
||||
private Integer pageNum = 1;
|
||||
|
||||
@Schema(description = "每页数量", example = "20")
|
||||
private Integer pageSize = 20;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.yolo.keyborad.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26 20:31
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用户对AI陪伴角色的评论表,支持多级评论结构(一级评论与回复)
|
||||
*/
|
||||
@Schema(description="用户对AI陪伴角色的评论表,支持多级评论结构(一级评论与回复)")
|
||||
@Data
|
||||
@TableName(value = "keyboard_ai_companion_comment")
|
||||
public class KeyboardAiCompanionComment {
|
||||
/**
|
||||
* 评论唯一ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@Schema(description="评论唯一ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 被评论的AI陪伴角色ID
|
||||
*/
|
||||
@TableField(value = "companion_id")
|
||||
@Schema(description="被评论的AI陪伴角色ID")
|
||||
private Long companionId;
|
||||
|
||||
/**
|
||||
* 发表评论的用户ID
|
||||
*/
|
||||
@TableField(value = "user_id")
|
||||
@Schema(description="发表评论的用户ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 父评论ID,NULL表示一级评论
|
||||
*/
|
||||
@TableField(value = "parent_id")
|
||||
@Schema(description="父评论ID,NULL表示一级评论")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 根评论ID,用于标识同一评论线程
|
||||
*/
|
||||
@TableField(value = "root_id")
|
||||
@Schema(description="根评论ID,用于标识同一评论线程")
|
||||
private Long rootId;
|
||||
|
||||
/**
|
||||
* 评论内容
|
||||
*/
|
||||
@TableField(value = "content")
|
||||
@Schema(description="评论内容")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 点赞数量
|
||||
*/
|
||||
@TableField(value = "\"like\"")
|
||||
@Schema(description="点赞数量")
|
||||
private Long like;
|
||||
|
||||
/**
|
||||
* 评论状态:1=正常,0=隐藏,-1=删除
|
||||
*/
|
||||
@TableField(value = "\"status\"")
|
||||
@Schema(description="评论状态:1=正常,0=隐藏,-1=删除")
|
||||
private Short status;
|
||||
|
||||
/**
|
||||
* 评论点赞数
|
||||
*/
|
||||
@TableField(value = "like_count")
|
||||
@Schema(description="评论点赞数")
|
||||
private Integer likeCount;
|
||||
|
||||
/**
|
||||
* 评论创建时间
|
||||
*/
|
||||
@TableField(value = "created_at")
|
||||
@Schema(description="评论创建时间")
|
||||
private Date createdAt;
|
||||
|
||||
/**
|
||||
* 评论更新时间
|
||||
*/
|
||||
@TableField(value = "updated_at")
|
||||
@Schema(description="评论更新时间")
|
||||
private Date updatedAt;
|
||||
}
|
||||
45
src/main/java/com/yolo/keyborad/model/vo/CommentVO.java
Normal file
45
src/main/java/com/yolo/keyborad/model/vo/CommentVO.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.yolo.keyborad.model.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "评论VO")
|
||||
public class CommentVO {
|
||||
|
||||
@Schema(description = "评论ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "被评论的AI陪伴角色ID")
|
||||
private Long companionId;
|
||||
|
||||
@Schema(description = "发表评论的用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户昵称")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "用户头像")
|
||||
private String userAvatar;
|
||||
|
||||
@Schema(description = "父评论ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "根评论ID")
|
||||
private Long rootId;
|
||||
|
||||
@Schema(description = "评论内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "点赞数")
|
||||
private Integer likeCount;
|
||||
|
||||
@Schema(description = "评论创建时间")
|
||||
private Date createdAt;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.yolo.keyborad.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.yolo.keyborad.model.entity.KeyboardAiCompanionComment;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yolo.keyborad.model.vo.CommentVO;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26 20:31
|
||||
*/
|
||||
public interface KeyboardAiCompanionCommentService extends IService<KeyboardAiCompanionComment> {
|
||||
|
||||
/**
|
||||
* 发表评论
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param companionId AI陪伴角色ID
|
||||
* @param content 评论内容
|
||||
* @param parentId 父评论ID(可为null)
|
||||
* @param rootId 根评论ID(可为null)
|
||||
* @return 评论ID
|
||||
*/
|
||||
Long addComment(Long userId, Long companionId, String content, Long parentId, Long rootId);
|
||||
|
||||
/**
|
||||
* 分页查询评论
|
||||
*
|
||||
* @param companionId AI陪伴角色ID
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页数量
|
||||
* @return 分页结果
|
||||
*/
|
||||
IPage<CommentVO> pageComments(Long companionId, Integer pageNum, Integer pageSize);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.yolo.keyborad.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.yolo.keyborad.mapper.KeyboardAiCompanionCommentMapper;
|
||||
import com.yolo.keyborad.model.entity.KeyboardAiCompanionComment;
|
||||
import com.yolo.keyborad.model.entity.KeyboardUser;
|
||||
import com.yolo.keyborad.model.vo.CommentVO;
|
||||
import com.yolo.keyborad.service.KeyboardAiCompanionCommentService;
|
||||
import com.yolo.keyborad.service.UserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26 20:31
|
||||
*/
|
||||
@Service
|
||||
public class KeyboardAiCompanionCommentServiceImpl extends ServiceImpl<KeyboardAiCompanionCommentMapper, KeyboardAiCompanionComment> implements KeyboardAiCompanionCommentService {
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
public Long addComment(Long userId, Long companionId, String content, Long parentId, Long rootId) {
|
||||
KeyboardAiCompanionComment comment = new KeyboardAiCompanionComment();
|
||||
comment.setUserId(userId);
|
||||
comment.setCompanionId(companionId);
|
||||
comment.setContent(content);
|
||||
comment.setParentId(parentId);
|
||||
comment.setRootId(rootId);
|
||||
comment.setStatus((short) 1);
|
||||
comment.setLikeCount(0);
|
||||
comment.setCreatedAt(new Date());
|
||||
this.save(comment);
|
||||
return comment.getId();
|
||||
}
|
||||
|
||||
@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)
|
||||
.isNull(KeyboardAiCompanionComment::getParentId)
|
||||
.orderByDesc(KeyboardAiCompanionComment::getCreatedAt);
|
||||
IPage<KeyboardAiCompanionComment> entityPage = this.page(page, queryWrapper);
|
||||
|
||||
// 获取所有用户ID
|
||||
List<Long> userIds = entityPage.getRecords().stream()
|
||||
.map(KeyboardAiCompanionComment::getUserId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 批量查询用户信息
|
||||
Map<Long, KeyboardUser> userMap = Map.of();
|
||||
if (!userIds.isEmpty()) {
|
||||
List<KeyboardUser> users = userService.listByIds(userIds);
|
||||
userMap = users.stream().collect(Collectors.toMap(KeyboardUser::getId, u -> u));
|
||||
}
|
||||
|
||||
// 转换为VO
|
||||
Map<Long, KeyboardUser> finalUserMap = userMap;
|
||||
return entityPage.convert(entity -> {
|
||||
CommentVO vo = new CommentVO();
|
||||
vo.setId(entity.getId());
|
||||
vo.setCompanionId(entity.getCompanionId());
|
||||
vo.setUserId(entity.getUserId());
|
||||
vo.setParentId(entity.getParentId());
|
||||
vo.setRootId(entity.getRootId());
|
||||
vo.setContent(entity.getContent());
|
||||
vo.setLikeCount(entity.getLikeCount());
|
||||
vo.setCreatedAt(entity.getCreatedAt());
|
||||
|
||||
// 填充用户信息
|
||||
KeyboardUser user = finalUserMap.get(entity.getUserId());
|
||||
if (user != null) {
|
||||
vo.setUserName(user.getNickName());
|
||||
vo.setUserAvatar(user.getAvatarUrl());
|
||||
}
|
||||
return vo;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.yolo.keyborad.mapper.KeyboardAiCompanionCommentMapper">
|
||||
<resultMap id="BaseResultMap" type="com.yolo.keyborad.model.entity.KeyboardAiCompanionComment">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table keyboard_ai_companion_comment-->
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="companion_id" jdbcType="BIGINT" property="companionId" />
|
||||
<result column="user_id" jdbcType="BIGINT" property="userId" />
|
||||
<result column="parent_id" jdbcType="BIGINT" property="parentId" />
|
||||
<result column="root_id" jdbcType="BIGINT" property="rootId" />
|
||||
<result column="content" jdbcType="VARCHAR" property="content" />
|
||||
<result column="like" jdbcType="BIGINT" property="like" />
|
||||
<result column="status" jdbcType="SMALLINT" property="status" />
|
||||
<result column="like_count" jdbcType="INTEGER" property="likeCount" />
|
||||
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
|
||||
<result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
<!--@mbg.generated-->
|
||||
id, companion_id, user_id, parent_id, root_id, content, "like", "status", like_count,
|
||||
created_at, updated_at
|
||||
</sql>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user