diff --git a/src/main/java/com/yolo/keyborad/controller/AiCompanionCommentController.java b/src/main/java/com/yolo/keyborad/controller/AiCompanionCommentController.java index 5b7aae2..bb7eb28 100644 --- a/src/main/java/com/yolo/keyborad/controller/AiCompanionCommentController.java +++ b/src/main/java/com/yolo/keyborad/controller/AiCompanionCommentController.java @@ -10,7 +10,9 @@ import com.yolo.keyborad.exception.BusinessException; import com.yolo.keyborad.model.dto.comment.CommentAddReq; import com.yolo.keyborad.model.dto.comment.CommentLikeReq; import com.yolo.keyborad.model.dto.comment.CommentPageReq; +import com.yolo.keyborad.model.dto.comment.CommentReportReq; import com.yolo.keyborad.model.vo.CommentVO; +import com.yolo.keyborad.service.KeyboardAiCommentReportService; import com.yolo.keyborad.service.KeyboardAiCompanionCommentService; import com.yolo.keyborad.service.KeyboardAiCompanionCommentLikeService; import io.swagger.v3.oas.annotations.Operation; @@ -35,6 +37,9 @@ public class AiCompanionCommentController { @Resource private KeyboardAiCompanionCommentLikeService commentLikeService; + @Resource + private KeyboardAiCommentReportService commentReportService; + @PostMapping("/add") @Operation(summary = "发表评论", description = "用户对AI陪聊角色发表评论") public BaseResponse addComment(@RequestBody CommentAddReq req) { @@ -75,4 +80,12 @@ public class AiCompanionCommentController { boolean result = commentLikeService.toggleLike(userId, req.getCommentId()); return ResultUtils.success(result); } + + @PostMapping("/report") + @Operation(summary = "举报评论", description = "举报AI陪聊角色评论,支持多种举报类型(可多选):1=色情低俗, 2=政治敏感, 3=暴力恐怖, 4=侵权/冒充, 5=价值观问题, 99=其他") + public BaseResponse reportComment(@RequestBody CommentReportReq req) { + Long userId = StpUtil.getLoginIdAsLong(); + Long reportId = commentReportService.reportComment(userId, req); + return ResultUtils.success(reportId); + } } diff --git a/src/main/java/com/yolo/keyborad/mapper/KeyboardAiCommentReportMapper.java b/src/main/java/com/yolo/keyborad/mapper/KeyboardAiCommentReportMapper.java index cb7e12a..3982912 100644 --- a/src/main/java/com/yolo/keyborad/mapper/KeyboardAiCommentReportMapper.java +++ b/src/main/java/com/yolo/keyborad/mapper/KeyboardAiCommentReportMapper.java @@ -4,9 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.yolo.keyborad.model.entity.KeyboardAiCommentReport; /* -* @author: ziin -* @date: 2026/3/20 15:07 -*/ - + * @author: ziin + * @date: 2026/3/20 + */ public interface KeyboardAiCommentReportMapper extends BaseMapper { -} \ No newline at end of file +} diff --git a/src/main/java/com/yolo/keyborad/model/dto/comment/CommentReportReq.java b/src/main/java/com/yolo/keyborad/model/dto/comment/CommentReportReq.java new file mode 100644 index 0000000..75bf4a2 --- /dev/null +++ b/src/main/java/com/yolo/keyborad/model/dto/comment/CommentReportReq.java @@ -0,0 +1,30 @@ +package com.yolo.keyborad.model.dto.comment; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/* + * @author: ziin + * @date: 2026/3/20 + */ +@Data +@Schema(description = "评论举报请求") +public class CommentReportReq { + + @Schema(description = "评论ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Long commentId; + + @Schema(description = "举报类型列表:1=色情低俗, 2=政治敏感, 3=暴力恐怖, 4=侵权/冒充, 5=价值观问题, 99=其他,支持多选", requiredMode = Schema.RequiredMode.REQUIRED) + private List reportTypes; + + @Schema(description = "详细描述") + private String reportDesc; + + @Schema(description = "评论上下文快照JSON") + private String chatContext; + + @Schema(description = "图片证据URL") + private String evidenceImageUrl; +} diff --git a/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCommentReport.java b/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCommentReport.java index a567482..7d7a767 100644 --- a/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCommentReport.java +++ b/src/main/java/com/yolo/keyborad/model/entity/KeyboardAiCommentReport.java @@ -5,95 +5,64 @@ 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; +import java.util.Date; + /* -* @author: ziin -* @date: 2026/3/20 15:07 -*/ - -/** - * AI角色评论举报记录表 + * @author: ziin + * @date: 2026/3/20 + */ + +/** + * AI评论举报记录表 */ -@Schema(description="AI角色评论举报记录表") @Data +@Schema(description = "AI评论举报记录表") @TableName(value = "keyboard_ai_comment_report") public class KeyboardAiCommentReport { - /** - * 举报记录唯一ID - */ + @TableId(value = "id", type = IdType.AUTO) - @Schema(description="举报记录唯一ID") + @Schema(description = "举报记录唯一ID") private Long id; - /** - * 被举报的评论Id - */ @TableField(value = "comment_id") - @Schema(description="被举报的评论Id") + @Schema(description = "被举报的评论ID") private Long commentId; - /** - * 发起举报的用户ID(逻辑关联用户表) - */ @TableField(value = "user_id") - @Schema(description="发起举报的用户ID(逻辑关联用户表)") + @Schema(description = "发起举报的用户ID") private Long userId; - /** - * 举报类型:1=色情低俗, 2=政治敏感, 3=暴力恐怖, 4=侵权/冒充, 5=价值观问题, 99=其他 - */ @TableField(value = "report_type") - @Schema(description="举报类型:1=色情低俗, 2=政治敏感, 3=暴力恐怖, 4=侵权/冒充, 5=价值观问题, 99=其他") + @Schema(description = "举报类型,多选时逗号分隔") private String reportType; - /** - * 用户填写的详细举报描述 - */ @TableField(value = "report_desc") - @Schema(description="用户填写的详细举报描述") + @Schema(description = "用户填写的详细举报描述") private String reportDesc; - /** - * 违规现场:举报时的评论的内容,用于审核取证 - */ - @TableField(value = "comment_context") - @Schema(description="违规现场:举报时的评论的内容,用于审核取证") - private String commentContext; + @TableField(value = "chat_context") + @Schema(description = "评论上下文快照JSON") + private String chatContext; - /** - * 图片证据:用户上传的截图URL - */ @TableField(value = "evidence_image_url") - @Schema(description="图片证据:用户上传的截图URL") + @Schema(description = "图片证据URL") private String evidenceImageUrl; - /** - * 处理状态:0=待处理, 1=违规确立(已处罚), 2=无效举报/已驳回, 3=已忽略 - */ @TableField(value = "\"status\"") - @Schema(description="处理状态:0=待处理, 1=违规确立(已处罚), 2=无效举报/已驳回, 3=已忽略") + @Schema(description = "处理状态:0=待处理, 1=违规确立, 2=无效举报, 3=已忽略") private Short status; - /** - * 管理员处理备注(记录处理理由或处罚措施) - */ @TableField(value = "admin_remark") - @Schema(description="管理员处理备注(记录处理理由或处罚措施)") + @Schema(description = "管理员处理备注") private String adminRemark; - /** - * 举报提交时间 - */ @TableField(value = "created_at") - @Schema(description="举报提交时间") + @Schema(description = "举报提交时间") private Date createdAt; - /** - * 最后更新时间 - */ @TableField(value = "updated_at") - @Schema(description="最后更新时间") + @Schema(description = "最后更新时间") private Date updatedAt; -} \ No newline at end of file +} diff --git a/src/main/java/com/yolo/keyborad/service/KeyboardAiCommentReportService.java b/src/main/java/com/yolo/keyborad/service/KeyboardAiCommentReportService.java index e322fb5..933ddd8 100644 --- a/src/main/java/com/yolo/keyborad/service/KeyboardAiCommentReportService.java +++ b/src/main/java/com/yolo/keyborad/service/KeyboardAiCommentReportService.java @@ -1,13 +1,21 @@ package com.yolo.keyborad.service; -import com.yolo.keyborad.model.entity.KeyboardAiCommentReport; import com.baomidou.mybatisplus.extension.service.IService; - /* -* @author: ziin -* @date: 2026/3/20 15:07 -*/ - -public interface KeyboardAiCommentReportService extends IService{ +import com.yolo.keyborad.model.dto.comment.CommentReportReq; +import com.yolo.keyborad.model.entity.KeyboardAiCommentReport; +/* + * @author: ziin + * @date: 2026/3/20 + */ +public interface KeyboardAiCommentReportService extends IService { + /** + * 举报评论 + * + * @param userId 用户ID + * @param req 举报请求 + * @return 举报记录ID + */ + Long reportComment(Long userId, CommentReportReq req); } diff --git a/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiCommentReportServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiCommentReportServiceImpl.java index 225a8ac..a5eb51b 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiCommentReportServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiCommentReportServiceImpl.java @@ -1,18 +1,78 @@ package com.yolo.keyborad.service.impl; -import org.springframework.stereotype.Service; -import org.springframework.beans.factory.annotation.Autowired; -import java.util.List; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.yolo.keyborad.model.entity.KeyboardAiCommentReport; +import com.yolo.keyborad.common.ErrorCode; +import com.yolo.keyborad.exception.BusinessException; import com.yolo.keyborad.mapper.KeyboardAiCommentReportMapper; +import com.yolo.keyborad.model.dto.comment.CommentReportReq; +import com.yolo.keyborad.model.entity.KeyboardAiCommentReport; +import com.yolo.keyborad.model.entity.KeyboardAiCompanionComment; import com.yolo.keyborad.service.KeyboardAiCommentReportService; -/* -* @author: ziin -* @date: 2026/3/20 15:07 -*/ - -@Service -public class KeyboardAiCommentReportServiceImpl extends ServiceImpl implements KeyboardAiCommentReportService{ +import com.yolo.keyborad.service.KeyboardAiCompanionCommentService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import java.util.Date; +import java.util.Set; +import java.util.stream.Collectors; + +/* + * @author: ziin + * @date: 2026/3/20 + */ +@Service +public class KeyboardAiCommentReportServiceImpl extends ServiceImpl + implements KeyboardAiCommentReportService { + + private static final short PENDING_STATUS = 0; + + private static final Set VALID_REPORT_TYPES = Set.of( + (short) 1, (short) 2, (short) 3, (short) 4, (short) 5, (short) 99 + ); + + @Resource + private KeyboardAiCompanionCommentService commentService; + + @Override + public Long reportComment(Long userId, CommentReportReq req) { + validateRequest(req); + + KeyboardAiCompanionComment comment = commentService.getById(req.getCommentId()); + if (comment == null) { + throw new BusinessException(ErrorCode.COMMENT_NOT_FOUND); + } + + KeyboardAiCommentReport report = buildReport(userId, req); + boolean saved = this.save(report); + if (!saved) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + return report.getId(); + } + + private void validateRequest(CommentReportReq req) { + if (req.getCommentId() == null) { + throw new BusinessException(ErrorCode.COMMENT_ID_EMPTY); + } + if (req.getReportTypes() == null || req.getReportTypes().isEmpty()) { + throw new BusinessException(ErrorCode.REPORT_TYPE_EMPTY); + } + boolean hasInvalidType = req.getReportTypes().stream().anyMatch(type -> !VALID_REPORT_TYPES.contains(type)); + if (hasInvalidType) { + throw new BusinessException(ErrorCode.REPORT_TYPE_INVALID); + } + } + + private KeyboardAiCommentReport buildReport(Long userId, CommentReportReq req) { + KeyboardAiCommentReport report = new KeyboardAiCommentReport(); + report.setUserId(userId); + 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.setStatus(PENDING_STATUS); + report.setCreatedAt(new Date()); + return report; + } } diff --git a/src/main/resources/mapper/KeyboardAiCommentReportMapper.xml b/src/main/resources/mapper/KeyboardAiCommentReportMapper.xml index 9ebfb3c..aa25a3e 100644 --- a/src/main/resources/mapper/KeyboardAiCommentReportMapper.xml +++ b/src/main/resources/mapper/KeyboardAiCommentReportMapper.xml @@ -2,14 +2,12 @@ - - - + @@ -17,8 +15,7 @@ - - id, comment_id, user_id, report_type, report_desc, comment_context, evidence_image_url, + id, comment_id, user_id, report_type, report_desc, chat_context, evidence_image_url, "status", admin_remark, created_at, updated_at - \ No newline at end of file +