Compare commits
4 Commits
ecab353802
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 392d9ecfe8 | |||
| 6a773ee0ca | |||
| 7d23b6be0f | |||
| 408d4d4bc1 |
@@ -75,7 +75,10 @@ public enum ErrorCode {
|
|||||||
AUDIO_FILE_EMPTY(40016, "音频文件不能为空"),
|
AUDIO_FILE_EMPTY(40016, "音频文件不能为空"),
|
||||||
AUDIO_FILE_TOO_LARGE(40017, "音频文件过大"),
|
AUDIO_FILE_TOO_LARGE(40017, "音频文件过大"),
|
||||||
AUDIO_FORMAT_NOT_SUPPORTED(40018, "音频格式不支持"),
|
AUDIO_FORMAT_NOT_SUPPORTED(40018, "音频格式不支持"),
|
||||||
STT_SERVICE_ERROR(50031, "语音转文字服务异常");
|
STT_SERVICE_ERROR(50031, "语音转文字服务异常"),
|
||||||
|
REPORT_TYPE_INVALID(40020, "举报类型无效"),
|
||||||
|
REPORT_COMPANION_ID_EMPTY(40021, "被举报的AI角色ID不能为空"),
|
||||||
|
REPORT_TYPE_EMPTY(40022, "举报类型不能为空");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态码
|
* 状态码
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import com.yolo.keyborad.common.ResultUtils;
|
|||||||
import com.yolo.keyborad.exception.BusinessException;
|
import com.yolo.keyborad.exception.BusinessException;
|
||||||
import com.yolo.keyborad.model.dto.PageDTO;
|
import com.yolo.keyborad.model.dto.PageDTO;
|
||||||
import com.yolo.keyborad.model.dto.companion.CompanionLikeReq;
|
import com.yolo.keyborad.model.dto.companion.CompanionLikeReq;
|
||||||
|
import com.yolo.keyborad.model.dto.companion.CompanionReportReq;
|
||||||
import com.yolo.keyborad.model.vo.AiCompanionVO;
|
import com.yolo.keyborad.model.vo.AiCompanionVO;
|
||||||
import com.yolo.keyborad.service.KeyboardAiCompanionLikeService;
|
import com.yolo.keyborad.service.KeyboardAiCompanionLikeService;
|
||||||
|
import com.yolo.keyborad.service.KeyboardAiCompanionReportService;
|
||||||
import com.yolo.keyborad.service.KeyboardAiCompanionService;
|
import com.yolo.keyborad.service.KeyboardAiCompanionService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -35,6 +37,9 @@ public class AiCompanionController {
|
|||||||
@Resource
|
@Resource
|
||||||
private KeyboardAiCompanionLikeService aiCompanionLikeService;
|
private KeyboardAiCompanionLikeService aiCompanionLikeService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KeyboardAiCompanionReportService aiCompanionReportService;
|
||||||
|
|
||||||
@PostMapping("/page")
|
@PostMapping("/page")
|
||||||
@Operation(summary = "分页查询AI陪聊角色", description = "分页查询已上线的AI陪聊角色列表,包含点赞数、评论数和当前用户点赞状态")
|
@Operation(summary = "分页查询AI陪聊角色", description = "分页查询已上线的AI陪聊角色列表,包含点赞数、评论数和当前用户点赞状态")
|
||||||
public BaseResponse<IPage<AiCompanionVO>> pageList(@RequestBody PageDTO pageDTO) {
|
public BaseResponse<IPage<AiCompanionVO>> pageList(@RequestBody PageDTO pageDTO) {
|
||||||
@@ -81,4 +86,12 @@ public class AiCompanionController {
|
|||||||
AiCompanionVO result = aiCompanionService.getCompanionById(userId, companionId);
|
AiCompanionVO result = aiCompanionService.getCompanionById(userId, companionId);
|
||||||
return ResultUtils.success(result);
|
return ResultUtils.success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/report")
|
||||||
|
@Operation(summary = "举报AI角色", description = "举报AI角色,支持多种举报类型(可多选):1=色情低俗, 2=政治敏感, 3=暴力恐怖, 4=侵权/冒充, 5=价值观问题, 99=其他")
|
||||||
|
public BaseResponse<Long> reportCompanion(@RequestBody CompanionReportReq req) {
|
||||||
|
Long userId = StpUtil.getLoginIdAsLong();
|
||||||
|
Long reportId = aiCompanionReportService.reportCompanion(userId, req);
|
||||||
|
return ResultUtils.success(reportId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.yolo.keyborad.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardAiCompanionReport;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/1/29 16:17
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface KeyboardAiCompanionReportMapper extends BaseMapper<KeyboardAiCompanionReport> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.yolo.keyborad.model.dto.companion;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/1/29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "AI角色举报请求")
|
||||||
|
public class CompanionReportReq {
|
||||||
|
|
||||||
|
@Schema(description = "AI角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Long companionId;
|
||||||
|
|
||||||
|
@Schema(description = "举报类型列表:1=色情低俗, 2=政治敏感, 3=暴力恐怖, 4=侵权/冒充, 5=价值观问题, 99=其他,支持多选", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private List<Short> reportTypes;
|
||||||
|
|
||||||
|
@Schema(description = "详细描述")
|
||||||
|
private String reportDesc;
|
||||||
|
|
||||||
|
@Schema(description = "聊天上下文快照JSON")
|
||||||
|
private String chatContext;
|
||||||
|
|
||||||
|
@Schema(description = "图片证据URL")
|
||||||
|
private String evidenceImageUrl;
|
||||||
|
}
|
||||||
@@ -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/29 16:17
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI角色举报记录表
|
||||||
|
*/
|
||||||
|
@Schema(description="AI角色举报记录表")
|
||||||
|
@Data
|
||||||
|
@TableName(value = "keyboard_ai_companion_report")
|
||||||
|
public class KeyboardAiCompanionReport {
|
||||||
|
/**
|
||||||
|
* 举报记录唯一ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
@Schema(description="举报记录唯一ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被举报的AI角色ID(逻辑关联 keyboard_ai_companion.id,无物理外键)
|
||||||
|
*/
|
||||||
|
@TableField(value = "companion_id")
|
||||||
|
@Schema(description="被举报的AI角色ID(逻辑关联 keyboard_ai_companion.id,无物理外键)")
|
||||||
|
private Long companionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起举报的用户ID(逻辑关联用户表)
|
||||||
|
*/
|
||||||
|
@TableField(value = "user_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=其他,多选时逗号分隔")
|
||||||
|
private String reportType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户填写的详细举报描述
|
||||||
|
*/
|
||||||
|
@TableField(value = "report_desc")
|
||||||
|
@Schema(description="用户填写的详细举报描述")
|
||||||
|
private String reportDesc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 违规现场:举报时的聊天上下文快照(建议存JSON字符串),用于审核取证
|
||||||
|
*/
|
||||||
|
@TableField(value = "chat_context")
|
||||||
|
@Schema(description="违规现场:举报时的聊天上下文快照(建议存JSON字符串),用于审核取证")
|
||||||
|
private String chatContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片证据:用户上传的截图URL
|
||||||
|
*/
|
||||||
|
@TableField(value = "evidence_image_url")
|
||||||
|
@Schema(description="图片证据:用户上传的截图URL")
|
||||||
|
private String evidenceImageUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理状态:0=待处理, 1=违规确立(已处罚), 2=无效举报/已驳回, 3=已忽略
|
||||||
|
*/
|
||||||
|
@TableField(value = "\"status\"")
|
||||||
|
@Schema(description="处理状态:0=待处理, 1=违规确立(已处罚), 2=无效举报/已驳回, 3=已忽略")
|
||||||
|
private Short status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员处理备注(记录处理理由或处罚措施)
|
||||||
|
*/
|
||||||
|
@TableField(value = "admin_remark")
|
||||||
|
@Schema(description="管理员处理备注(记录处理理由或处罚措施)")
|
||||||
|
private String adminRemark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 举报提交时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "created_at")
|
||||||
|
@Schema(description="举报提交时间")
|
||||||
|
private Date createdAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后更新时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "updated_at")
|
||||||
|
@Schema(description="最后更新时间")
|
||||||
|
private Date updatedAt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.yolo.keyborad.service;
|
||||||
|
|
||||||
|
import com.yolo.keyborad.model.dto.companion.CompanionReportReq;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardAiCompanionReport;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/1/29 16:17
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface KeyboardAiCompanionReportService extends IService<KeyboardAiCompanionReport>{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 举报AI角色
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param req 举报请求
|
||||||
|
* @return 举报记录ID
|
||||||
|
*/
|
||||||
|
Long reportCompanion(Long userId, CompanionReportReq req);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,8 +7,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.yolo.keyborad.mapper.KeyboardAiChatMessageMapper;
|
import com.yolo.keyborad.mapper.KeyboardAiChatMessageMapper;
|
||||||
import com.yolo.keyborad.model.entity.KeyboardAiChatMessage;
|
import com.yolo.keyborad.model.entity.KeyboardAiChatMessage;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardAiChatSession;
|
||||||
import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
||||||
import com.yolo.keyborad.service.KeyboardAiChatMessageService;
|
import com.yolo.keyborad.service.KeyboardAiChatMessageService;
|
||||||
|
import com.yolo.keyborad.service.KeyboardAiChatSessionService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -21,22 +24,52 @@ import java.util.List;
|
|||||||
@Service
|
@Service
|
||||||
public class KeyboardAiChatMessageServiceImpl extends ServiceImpl<KeyboardAiChatMessageMapper, KeyboardAiChatMessage> implements KeyboardAiChatMessageService {
|
public class KeyboardAiChatMessageServiceImpl extends ServiceImpl<KeyboardAiChatMessageMapper, KeyboardAiChatMessage> implements KeyboardAiChatMessageService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KeyboardAiChatSessionService sessionService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<ChatMessageHistoryVO> pageHistory(Long userId, Long companionId, Integer pageNum, Integer pageSize) {
|
public IPage<ChatMessageHistoryVO> pageHistory(Long userId, Long companionId, Integer pageNum, Integer pageSize) {
|
||||||
|
// 获取当前活跃会话
|
||||||
|
LambdaQueryWrapper<KeyboardAiChatSession> sessionWrapper = new LambdaQueryWrapper<>();
|
||||||
|
sessionWrapper.eq(KeyboardAiChatSession::getUserId, userId)
|
||||||
|
.eq(KeyboardAiChatSession::getCompanionId, companionId)
|
||||||
|
.eq(KeyboardAiChatSession::getIsActive, true);
|
||||||
|
KeyboardAiChatSession activeSession = sessionService.getOne(sessionWrapper);
|
||||||
|
|
||||||
|
// 如果没有活跃会话,返回空分页
|
||||||
|
if (activeSession == null) {
|
||||||
|
return new Page<ChatMessageHistoryVO>(pageNum, pageSize).setRecords(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
Page<KeyboardAiChatMessage> page = new Page<>(pageNum, pageSize);
|
Page<KeyboardAiChatMessage> page = new Page<>(pageNum, pageSize);
|
||||||
LambdaQueryWrapper<KeyboardAiChatMessage> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<KeyboardAiChatMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId)
|
queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId)
|
||||||
.eq(KeyboardAiChatMessage::getCompanionId, companionId)
|
.eq(KeyboardAiChatMessage::getCompanionId, companionId)
|
||||||
.orderByDesc(KeyboardAiChatMessage::getCreatedAt);
|
.eq(KeyboardAiChatMessage::getSessionId, activeSession.getId())
|
||||||
|
.orderByAsc(KeyboardAiChatMessage::getCreatedAt)
|
||||||
|
.orderByAsc(KeyboardAiChatMessage::getId);
|
||||||
IPage<KeyboardAiChatMessage> entityPage = this.page(page, queryWrapper);
|
IPage<KeyboardAiChatMessage> entityPage = this.page(page, queryWrapper);
|
||||||
return entityPage.convert(entity -> BeanUtil.copyProperties(entity, ChatMessageHistoryVO.class));
|
return entityPage.convert(entity -> BeanUtil.copyProperties(entity, ChatMessageHistoryVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<KeyboardAiChatMessage> getRecentMessages(Long userId, Long companionId, int limit) {
|
public List<KeyboardAiChatMessage> getRecentMessages(Long userId, Long companionId, int limit) {
|
||||||
|
// 获取当前活跃会话
|
||||||
|
LambdaQueryWrapper<KeyboardAiChatSession> sessionWrapper = new LambdaQueryWrapper<>();
|
||||||
|
sessionWrapper.eq(KeyboardAiChatSession::getUserId, userId)
|
||||||
|
.eq(KeyboardAiChatSession::getCompanionId, companionId)
|
||||||
|
.eq(KeyboardAiChatSession::getIsActive, true);
|
||||||
|
KeyboardAiChatSession activeSession = sessionService.getOne(sessionWrapper);
|
||||||
|
|
||||||
|
// 如果没有活跃会话,返回空列表
|
||||||
|
if (activeSession == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
LambdaQueryWrapper<KeyboardAiChatMessage> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<KeyboardAiChatMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId)
|
queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId)
|
||||||
.eq(KeyboardAiChatMessage::getCompanionId, companionId)
|
.eq(KeyboardAiChatMessage::getCompanionId, companionId)
|
||||||
|
.eq(KeyboardAiChatMessage::getSessionId, activeSession.getId())
|
||||||
.orderByDesc(KeyboardAiChatMessage::getCreatedAt)
|
.orderByDesc(KeyboardAiChatMessage::getCreatedAt)
|
||||||
.last("LIMIT " + limit);
|
.last("LIMIT " + limit);
|
||||||
List<KeyboardAiChatMessage> messages = this.list(queryWrapper);
|
List<KeyboardAiChatMessage> messages = this.list(queryWrapper);
|
||||||
@@ -47,14 +80,31 @@ public class KeyboardAiChatMessageServiceImpl extends ServiceImpl<KeyboardAiChat
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Long> getChattedCompanionIds(Long userId) {
|
public List<Long> getChattedCompanionIds(Long userId) {
|
||||||
// 使用原生SQL查询用户聊过天的所有角色ID,按最近聊天时间倒序
|
// 1. 查询用户所有活跃会话
|
||||||
|
LambdaQueryWrapper<KeyboardAiChatSession> sessionWrapper = new LambdaQueryWrapper<>();
|
||||||
|
sessionWrapper.eq(KeyboardAiChatSession::getUserId, userId)
|
||||||
|
.eq(KeyboardAiChatSession::getIsActive, true);
|
||||||
|
List<KeyboardAiChatSession> activeSessions = sessionService.list(sessionWrapper);
|
||||||
|
|
||||||
|
// 2. 如果没有活跃会话,返回空列表
|
||||||
|
if (activeSessions == null || activeSessions.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 提取活跃会话的 sessionId 列表
|
||||||
|
List<Long> activeSessionIds = activeSessions.stream()
|
||||||
|
.map(KeyboardAiChatSession::getId)
|
||||||
|
.collect(java.util.stream.Collectors.toList());
|
||||||
|
|
||||||
|
// 4. 查询这些会话中的消息,获取 companionId,按最近聊天时间倒序
|
||||||
LambdaQueryWrapper<KeyboardAiChatMessage> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<KeyboardAiChatMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId)
|
queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId)
|
||||||
.select(KeyboardAiChatMessage::getCompanionId)
|
.in(KeyboardAiChatMessage::getSessionId, activeSessionIds)
|
||||||
.groupBy(KeyboardAiChatMessage::getCompanionId)
|
.orderByDesc(KeyboardAiChatMessage::getCreatedAt);
|
||||||
.orderByDesc(KeyboardAiChatMessage::getCompanionId);
|
|
||||||
|
|
||||||
List<KeyboardAiChatMessage> messages = this.list(queryWrapper);
|
List<KeyboardAiChatMessage> messages = this.list(queryWrapper);
|
||||||
|
|
||||||
|
// 5. 去重并保持顺序(按最近聊天时间)
|
||||||
return messages.stream()
|
return messages.stream()
|
||||||
.map(KeyboardAiChatMessage::getCompanionId)
|
.map(KeyboardAiChatMessage::getCompanionId)
|
||||||
.distinct()
|
.distinct()
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.yolo.keyborad.service.impl;
|
||||||
|
|
||||||
|
import com.yolo.keyborad.common.ErrorCode;
|
||||||
|
import com.yolo.keyborad.exception.BusinessException;
|
||||||
|
import com.yolo.keyborad.model.dto.companion.CompanionReportReq;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardAiCompanion;
|
||||||
|
import com.yolo.keyborad.service.KeyboardAiCompanionService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.yolo.keyborad.mapper.KeyboardAiCompanionReportMapper;
|
||||||
|
import com.yolo.keyborad.model.entity.KeyboardAiCompanionReport;
|
||||||
|
import com.yolo.keyborad.service.KeyboardAiCompanionReportService;
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2026/1/29 16:17
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class KeyboardAiCompanionReportServiceImpl extends ServiceImpl<KeyboardAiCompanionReportMapper, KeyboardAiCompanionReport> implements KeyboardAiCompanionReportService{
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KeyboardAiCompanionService aiCompanionService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long reportCompanion(Long userId, CompanionReportReq req) {
|
||||||
|
// 校验 companionId 不为空
|
||||||
|
if (req.getCompanionId() == null) {
|
||||||
|
throw new BusinessException(ErrorCode.REPORT_COMPANION_ID_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验 reportTypes 不为空
|
||||||
|
if (req.getReportTypes() == null || req.getReportTypes().isEmpty()) {
|
||||||
|
throw new BusinessException(ErrorCode.REPORT_TYPE_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验每个 reportType 在有效范围内(1,2,3,4,5,99)
|
||||||
|
List<Short> validTypes = List.of((short) 1, (short) 2, (short) 3, (short) 4, (short) 5, (short) 99);
|
||||||
|
for (Short type : req.getReportTypes()) {
|
||||||
|
if (!validTypes.contains(type)) {
|
||||||
|
throw new BusinessException(ErrorCode.REPORT_TYPE_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验 AI 角色是否存在
|
||||||
|
KeyboardAiCompanion companion = aiCompanionService.getById(req.getCompanionId());
|
||||||
|
if (companion == null) {
|
||||||
|
throw new BusinessException(ErrorCode.COMPANION_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建举报记录
|
||||||
|
KeyboardAiCompanionReport report = new KeyboardAiCompanionReport();
|
||||||
|
report.setUserId(userId);
|
||||||
|
report.setCompanionId(req.getCompanionId());
|
||||||
|
|
||||||
|
// 将 List<Short> 转换为逗号分隔的字符串
|
||||||
|
String reportTypeStr = req.getReportTypes().stream()
|
||||||
|
.map(String::valueOf)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
report.setReportType(reportTypeStr);
|
||||||
|
|
||||||
|
report.setReportDesc(req.getReportDesc());
|
||||||
|
report.setChatContext(req.getChatContext());
|
||||||
|
report.setEvidenceImageUrl(req.getEvidenceImageUrl());
|
||||||
|
report.setStatus((short) 0); // 待处理
|
||||||
|
report.setCreatedAt(new Date());
|
||||||
|
|
||||||
|
// 保存并返回 ID
|
||||||
|
this.save(report);
|
||||||
|
return report.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.KeyboardAiCompanionReportMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="com.yolo.keyborad.model.entity.KeyboardAiCompanionReport">
|
||||||
|
<!--@mbg.generated-->
|
||||||
|
<!--@Table keyboard_ai_companion_report-->
|
||||||
|
<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="report_type" jdbcType="SMALLINT" property="reportType" />
|
||||||
|
<result column="report_desc" jdbcType="VARCHAR" property="reportDesc" />
|
||||||
|
<result column="chat_context" jdbcType="VARCHAR" property="chatContext" />
|
||||||
|
<result column="evidence_image_url" jdbcType="VARCHAR" property="evidenceImageUrl" />
|
||||||
|
<result column="status" jdbcType="SMALLINT" property="status" />
|
||||||
|
<result column="admin_remark" jdbcType="VARCHAR" property="adminRemark" />
|
||||||
|
<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, report_type, report_desc, chat_context, evidence_image_url,
|
||||||
|
"status", admin_remark, created_at, updated_at
|
||||||
|
</sql>
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user