From ecab3538027d044f73ecbb507aefd4c1342aea80 Mon Sep 17 00:00:00 2001 From: ziin Date: Wed, 28 Jan 2026 17:56:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(chat):=20=E6=96=B0=E5=A2=9E=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E4=BC=9A=E8=AF=9D=E6=8E=A5=E5=8F=A3=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=B8=BB=E9=94=AE=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatController 增加 /session/reset 端点,支持用户主动重置与 AI 角色的会话 - 会话重置逻辑:将当前活跃会话置为失效,并创建版本号递增的新会话 - 新增 SessionResetReq DTO 与 ChatSessionVO 返回视图 - KeyboardAiChatSession 主键生成策略由 AUTO 改为 ASSIGN_ID,适配分布式场景 --- .../keyborad/controller/ChatController.java | 26 +++++++++++++ .../model/dto/chat/SessionResetReq.java | 16 ++++++++ .../yolo/keyborad/model/vo/ChatSessionVO.java | 29 ++++++++++++++ .../service/KeyboardAiChatSessionService.java | 9 +++++ .../KeyboardAiChatSessionServiceImpl.java | 39 +++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 src/main/java/com/yolo/keyborad/model/dto/chat/SessionResetReq.java create mode 100644 src/main/java/com/yolo/keyborad/model/vo/ChatSessionVO.java diff --git a/src/main/java/com/yolo/keyborad/controller/ChatController.java b/src/main/java/com/yolo/keyborad/controller/ChatController.java index a9f5c8e..1825196 100644 --- a/src/main/java/com/yolo/keyborad/controller/ChatController.java +++ b/src/main/java/com/yolo/keyborad/controller/ChatController.java @@ -14,12 +14,15 @@ 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.dto.chat.SessionResetReq; 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.ChatSessionVO; import com.yolo.keyborad.model.vo.ChatVoiceVO; import com.yolo.keyborad.service.ChatService; import com.yolo.keyborad.service.KeyboardAiChatMessageService; +import com.yolo.keyborad.service.KeyboardAiChatSessionService; import com.yolo.keyborad.service.impl.QdrantVectorService; import io.qdrant.client.grpc.JsonWithInt; import io.swagger.v3.oas.annotations.Operation; @@ -55,6 +58,9 @@ public class ChatController { @Resource private KeyboardAiChatMessageService aiChatMessageService; + @Resource + private KeyboardAiChatSessionService aiChatSessionService; + @PostMapping("/message") @Operation(summary = "同步对话", description = "发送消息给大模型,同步返回 AI 响应,异步生成音频") @@ -131,4 +137,24 @@ public class ChatController { userId, req.getCompanionId(), req.getPageNum(), req.getPageSize()); return ResultUtils.success(result); } + + @PostMapping("/session/reset") + @Operation(summary = "重置会话", description = "重置与AI角色的聊天会话,将当前会话设为不活跃并创建新会话,后续聊天记录将绑定到新会话") + public BaseResponse resetSession(@RequestBody SessionResetReq req) { + if (req.getCompanionId() == null) { + throw new BusinessException(ErrorCode.COMPANION_ID_EMPTY); + } + + Long userId = StpUtil.getLoginIdAsLong(); + var newSession = aiChatSessionService.resetSession(userId, req.getCompanionId()); + + ChatSessionVO vo = ChatSessionVO.builder() + .sessionId(newSession.getId()) + .companionId(newSession.getCompanionId()) + .resetVersion(newSession.getResetVersion()) + .createdAt(newSession.getCreatedAt()) + .build(); + + return ResultUtils.success(vo); + } } diff --git a/src/main/java/com/yolo/keyborad/model/dto/chat/SessionResetReq.java b/src/main/java/com/yolo/keyborad/model/dto/chat/SessionResetReq.java new file mode 100644 index 0000000..d82af66 --- /dev/null +++ b/src/main/java/com/yolo/keyborad/model/dto/chat/SessionResetReq.java @@ -0,0 +1,16 @@ +package com.yolo.keyborad.model.dto.chat; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/* + * @author: ziin + * @date: 2026/1/28 + */ +@Data +@Schema(description = "会话重置请求") +public class SessionResetReq { + + @Schema(description = "AI陪聊角色ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Long companionId; +} diff --git a/src/main/java/com/yolo/keyborad/model/vo/ChatSessionVO.java b/src/main/java/com/yolo/keyborad/model/vo/ChatSessionVO.java new file mode 100644 index 0000000..d88634a --- /dev/null +++ b/src/main/java/com/yolo/keyborad/model/vo/ChatSessionVO.java @@ -0,0 +1,29 @@ +package com.yolo.keyborad.model.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.Date; + +/* + * @author: ziin + * @date: 2026/1/28 + */ +@Data +@Builder +@Schema(description = "会话信息VO") +public class ChatSessionVO { + + @Schema(description = "会话ID") + private Long sessionId; + + @Schema(description = "AI陪聊角色ID") + private Long companionId; + + @Schema(description = "会话版本号") + private Integer resetVersion; + + @Schema(description = "会话创建时间") + private Date createdAt; +} diff --git a/src/main/java/com/yolo/keyborad/service/KeyboardAiChatSessionService.java b/src/main/java/com/yolo/keyborad/service/KeyboardAiChatSessionService.java index b997878..58e6d36 100644 --- a/src/main/java/com/yolo/keyborad/service/KeyboardAiChatSessionService.java +++ b/src/main/java/com/yolo/keyborad/service/KeyboardAiChatSessionService.java @@ -26,4 +26,13 @@ public interface KeyboardAiChatSessionService extends IService queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(KeyboardAiChatSession::getUserId, userId) + .eq(KeyboardAiChatSession::getCompanionId, companionId) + .eq(KeyboardAiChatSession::getIsActive, true); + KeyboardAiChatSession activeSession = this.getOne(queryWrapper); + + // 如果存在活跃会话,将其设为不活跃 + if (activeSession != null) { + activeSession.setIsActive(false); + activeSession.setEndedAt(now); + this.updateById(activeSession); + } + + // 查询该用户与该角色的最大版本号 + LambdaQueryWrapper maxVersionWrapper = new LambdaQueryWrapper<>(); + maxVersionWrapper.eq(KeyboardAiChatSession::getUserId, userId) + .eq(KeyboardAiChatSession::getCompanionId, companionId) + .orderByDesc(KeyboardAiChatSession::getResetVersion) + .last("LIMIT 1"); + KeyboardAiChatSession lastSession = this.getOne(maxVersionWrapper); + int newVersion = lastSession != null ? lastSession.getResetVersion() + 1 : 1; + + // 创建新的活跃会话 + KeyboardAiChatSession newSession = new KeyboardAiChatSession(); + newSession.setUserId(userId); + newSession.setCompanionId(companionId); + newSession.setResetVersion(newVersion); + newSession.setIsActive(true); + newSession.setCreatedAt(now); + this.save(newSession); + + return newSession; + } }