From aaf5d3bea497e86ec9b5035e6550a1762f0687e5 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 26 Jan 2026 18:38:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(chat):=20=E6=96=B0=E5=A2=9E=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E6=9F=A5=E8=AF=A2=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../keyborad/config/SaTokenConfigure.java | 3 +- .../keyborad/controller/ChatController.java | 20 +++++++++++ .../model/dto/chat/ChatHistoryPageReq.java | 22 +++++++++++++ .../model/vo/ChatMessageHistoryVO.java | 27 +++++++++++++++ .../service/KeyboardAiChatMessageService.java | 23 +++++++++---- .../KeyboardAiChatMessageServiceImpl.java | 33 +++++++++++++------ 6 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/yolo/keyborad/model/dto/chat/ChatHistoryPageReq.java create mode 100644 src/main/java/com/yolo/keyborad/model/vo/ChatMessageHistoryVO.java diff --git a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java index 7a2a1ec..7f69056 100644 --- a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java +++ b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java @@ -112,7 +112,8 @@ public class SaTokenConfigure implements WebMvcConfigurer { "/chat/message", "/chat/voice", "/chat/audio/*", - "/ai-companion/page" + "/ai-companion/page", + "/chat/history" }; } @Bean diff --git a/src/main/java/com/yolo/keyborad/controller/ChatController.java b/src/main/java/com/yolo/keyborad/controller/ChatController.java index b0c3fdc..a9f5c8e 100644 --- a/src/main/java/com/yolo/keyborad/controller/ChatController.java +++ b/src/main/java/com/yolo/keyborad/controller/ChatController.java @@ -3,19 +3,23 @@ package com.yolo.keyborad.controller; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.util.IdUtil; 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.mapper.QdrantPayloadMapper; +import com.yolo.keyborad.model.dto.chat.ChatHistoryPageReq; import com.yolo.keyborad.model.dto.chat.ChatMessageReq; import com.yolo.keyborad.model.dto.chat.ChatReq; import com.yolo.keyborad.model.dto.chat.ChatSaveReq; import com.yolo.keyborad.model.dto.chat.ChatStreamMessage; import com.yolo.keyborad.model.vo.AudioTaskVO; +import com.yolo.keyborad.model.vo.ChatMessageHistoryVO; import com.yolo.keyborad.model.vo.ChatMessageVO; import com.yolo.keyborad.model.vo.ChatVoiceVO; import com.yolo.keyborad.service.ChatService; +import com.yolo.keyborad.service.KeyboardAiChatMessageService; import com.yolo.keyborad.service.impl.QdrantVectorService; import io.qdrant.client.grpc.JsonWithInt; import io.swagger.v3.oas.annotations.Operation; @@ -48,6 +52,9 @@ public class ChatController { @Resource private ChatService chatService; + @Resource + private KeyboardAiChatMessageService aiChatMessageService; + @PostMapping("/message") @Operation(summary = "同步对话", description = "发送消息给大模型,同步返回 AI 响应,异步生成音频") @@ -111,4 +118,17 @@ public class ChatController { log.info("聊天嵌入保存成功,用户ID: {}, 文本长度: {}", chatSaveReq.getUserId(), chatSaveReq.getUserText().length()); return ResultUtils.success(true); } + + @PostMapping("/history") + @Operation(summary = "分页查询聊天记录", description = "分页查询用户与AI陪聊角色的聊天记录") + public BaseResponse> pageHistory(@RequestBody ChatHistoryPageReq req) { + if (req.getCompanionId() == null) { + throw new BusinessException(ErrorCode.COMPANION_ID_EMPTY); + } + + Long userId = StpUtil.getLoginIdAsLong(); + IPage result = aiChatMessageService.pageHistory( + userId, req.getCompanionId(), req.getPageNum(), req.getPageSize()); + return ResultUtils.success(result); + } } diff --git a/src/main/java/com/yolo/keyborad/model/dto/chat/ChatHistoryPageReq.java b/src/main/java/com/yolo/keyborad/model/dto/chat/ChatHistoryPageReq.java new file mode 100644 index 0000000..61089c6 --- /dev/null +++ b/src/main/java/com/yolo/keyborad/model/dto/chat/ChatHistoryPageReq.java @@ -0,0 +1,22 @@ +package com.yolo.keyborad.model.dto.chat; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/* + * @author: ziin + * @date: 2026/1/26 + */ +@Data +@Schema(description = "聊天记录分页查询请求") +public class ChatHistoryPageReq { + + @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; +} diff --git a/src/main/java/com/yolo/keyborad/model/vo/ChatMessageHistoryVO.java b/src/main/java/com/yolo/keyborad/model/vo/ChatMessageHistoryVO.java new file mode 100644 index 0000000..318c9ef --- /dev/null +++ b/src/main/java/com/yolo/keyborad/model/vo/ChatMessageHistoryVO.java @@ -0,0 +1,27 @@ +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 ChatMessageHistoryVO { + + @Schema(description = "消息ID") + private Long id; + + @Schema(description = "消息发送方:1=用户,2=AI") + private Short sender; + + @Schema(description = "聊天消息内容") + private String content; + + @Schema(description = "消息创建时间") + private Date createdAt; +} diff --git a/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java b/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java index 5e509b7..47b604b 100644 --- a/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java +++ b/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java @@ -1,13 +1,24 @@ package com.yolo.keyborad.service; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.yolo.keyborad.model.entity.KeyboardAiChatMessage; import com.baomidou.mybatisplus.extension.service.IService; - /* -* @author: ziin -* @date: 2026/1/26 17:00 -*/ - -public interface KeyboardAiChatMessageService extends IService{ +import com.yolo.keyborad.model.vo.ChatMessageHistoryVO; +/* + * @author: ziin + * @date: 2026/1/26 17:00 + */ +public interface KeyboardAiChatMessageService extends IService { + /** + * 分页查询用户与AI的聊天记录 + * + * @param userId 用户ID + * @param companionId AI陪聊角色ID + * @param pageNum 页码 + * @param pageSize 每页数量 + * @return 分页结果 + */ + IPage pageHistory(Long userId, Long companionId, Integer pageNum, Integer pageSize); } diff --git a/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java index a3fbdef..45e1b08 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java @@ -1,18 +1,31 @@ package com.yolo.keyborad.service.impl; -import org.springframework.stereotype.Service; -import org.springframework.beans.factory.annotation.Autowired; -import java.util.List; +import cn.hutool.core.bean.BeanUtil; +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.KeyboardAiChatMessageMapper; import com.yolo.keyborad.model.entity.KeyboardAiChatMessage; +import com.yolo.keyborad.model.vo.ChatMessageHistoryVO; import com.yolo.keyborad.service.KeyboardAiChatMessageService; -/* -* @author: ziin -* @date: 2026/1/26 17:00 -*/ - -@Service -public class KeyboardAiChatMessageServiceImpl extends ServiceImpl implements KeyboardAiChatMessageService{ +import org.springframework.stereotype.Service; +/* + * @author: ziin + * @date: 2026/1/26 17:00 + */ +@Service +public class KeyboardAiChatMessageServiceImpl extends ServiceImpl implements KeyboardAiChatMessageService { + + @Override + public IPage pageHistory(Long userId, Long companionId, Integer pageNum, Integer pageSize) { + Page page = new Page<>(pageNum, pageSize); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId) + .eq(KeyboardAiChatMessage::getCompanionId, companionId) + .orderByDesc(KeyboardAiChatMessage::getCreatedAt); + IPage entityPage = this.page(page, queryWrapper); + return entityPage.convert(entity -> BeanUtil.copyProperties(entity, ChatMessageHistoryVO.class)); + } }