新增聊天历史表
This commit is contained in:
parent
fc0aa3d6da
commit
42eb1c21e2
|
|
@ -1,29 +0,0 @@
|
||||||
package cn.qihangerp.erp.config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import cn.qihangerp.erp.serviceImpl.ConversationHistoryManager;
|
|
||||||
import cn.qihangerp.erp.serviceImpl.SessionManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AI相关配置类
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class AiConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 会话管理服务Bean
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public SessionManager sessionManager() {
|
|
||||||
return new SessionManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对话历史管理服务Bean
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public ConversationHistoryManager conversationHistoryManager() {
|
|
||||||
return new ConversationHistoryManager();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -123,7 +123,7 @@ public class SseController {
|
||||||
log.info("用户 {} 的会话ID: {}", userId, sessionId);
|
log.info("用户 {} 的会话ID: {}", userId, sessionId);
|
||||||
|
|
||||||
// 添加用户消息到对话历史
|
// 添加用户消息到对话历史
|
||||||
conversationHistoryManager.addMessage(sessionId, "user", message);
|
conversationHistoryManager.addMessage(userId, sessionId, "user", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取对话历史
|
// 获取对话历史
|
||||||
|
|
@ -138,7 +138,7 @@ public class SseController {
|
||||||
|
|
||||||
// 如果有会话ID,添加AI回复到对话历史
|
// 如果有会话ID,添加AI回复到对话历史
|
||||||
if (sessionId != null) {
|
if (sessionId != null) {
|
||||||
conversationHistoryManager.addMessage(sessionId, "assistant", response);
|
conversationHistoryManager.addMessage(userId, sessionId, "assistant", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查响应是否已经是JSON格式(以{开头)
|
// 检查响应是否已经是JSON格式(以{开头)
|
||||||
|
|
@ -160,6 +160,16 @@ public class SseController {
|
||||||
return "消息发送成功";
|
return "消息发送成功";
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("消息处理失败: {}", e.getMessage());
|
log.error("消息处理失败: {}", e.getMessage());
|
||||||
|
try {
|
||||||
|
// 发送错误信息到前端
|
||||||
|
String errorMessage = e.getMessage();
|
||||||
|
String jsonError = String.format("{\"error\": \"%s\"}", errorMessage.replace("\"", "\\\"").replace("\n", "\\n"));
|
||||||
|
emitter.send(SseEmitter.event()
|
||||||
|
.name("error")
|
||||||
|
.data(jsonError));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error("发送错误信息失败: {}", ex.getMessage());
|
||||||
|
}
|
||||||
emitters.remove(clientId);
|
emitters.remove(clientId);
|
||||||
clientUserIdMap.remove(clientId);
|
clientUserIdMap.remove(clientId);
|
||||||
return "消息发送失败: " + e.getMessage();
|
return "消息发送失败: " + e.getMessage();
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,22 @@
|
||||||
package cn.qihangerp.erp.serviceImpl;
|
package cn.qihangerp.erp.serviceImpl;
|
||||||
|
|
||||||
|
import cn.qihangerp.service.IAiConversationHistoryService;
|
||||||
|
import cn.qihangerp.model.entity.AiConversationHistory;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.stream.Collectors;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对话历史管理服务,用于保存和管理用户的对话历史
|
* 对话历史管理服务,用于保存和管理用户的对话历史
|
||||||
*/
|
*/
|
||||||
|
@Component
|
||||||
|
@AllArgsConstructor
|
||||||
public class ConversationHistoryManager {
|
public class ConversationHistoryManager {
|
||||||
private static final Map<String, List<Message>> sessionHistoryMap = new ConcurrentHashMap<>();
|
|
||||||
private static final AtomicLong messageIdCounter = new AtomicLong(0);
|
private final IAiConversationHistoryService aiConversationHistoryService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 消息实体类
|
* 消息实体类
|
||||||
|
|
@ -22,8 +27,15 @@ public class ConversationHistoryManager {
|
||||||
private String content;
|
private String content;
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
|
|
||||||
|
public Message(long id, String role, String content, long timestamp) {
|
||||||
|
this.id = id;
|
||||||
|
this.role = role;
|
||||||
|
this.content = content;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
public Message(String role, String content) {
|
public Message(String role, String content) {
|
||||||
this.id = messageIdCounter.incrementAndGet();
|
this.id = 0;
|
||||||
this.role = role;
|
this.role = role;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.timestamp = System.currentTimeMillis();
|
this.timestamp = System.currentTimeMillis();
|
||||||
|
|
@ -56,8 +68,22 @@ public class ConversationHistoryManager {
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sessionHistoryMap.computeIfAbsent(sessionId, k -> new ArrayList<>())
|
// 这里简化处理,暂时不传入userId,实际使用时需要从会话中获取
|
||||||
.add(new Message(role, content));
|
aiConversationHistoryService.saveMessage(0L, sessionId, role, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加消息到对话历史(带用户ID)
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @param role 角色
|
||||||
|
* @param content 消息内容
|
||||||
|
*/
|
||||||
|
public void addMessage(Long userId, String sessionId, String role, String content) {
|
||||||
|
if (sessionId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aiConversationHistoryService.saveMessage(userId, sessionId, role, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -69,7 +95,10 @@ public class ConversationHistoryManager {
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
return sessionHistoryMap.getOrDefault(sessionId, new ArrayList<>());
|
List<AiConversationHistory> historyList = aiConversationHistoryService.getBySessionId(sessionId);
|
||||||
|
return historyList.stream()
|
||||||
|
.map(history -> new Message(history.getId(), history.getRole(), history.getContent(), history.getTimestamp()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -82,9 +111,13 @@ public class ConversationHistoryManager {
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
List<Message> history = sessionHistoryMap.getOrDefault(sessionId, new ArrayList<>());
|
List<AiConversationHistory> historyList = aiConversationHistoryService.getRecentBySessionId(sessionId, limit);
|
||||||
int startIndex = Math.max(0, history.size() - limit);
|
// 反转列表,使时间戳从早到晚排序
|
||||||
return history.subList(startIndex, history.size());
|
List<Message> messages = historyList.stream()
|
||||||
|
.map(history -> new Message(history.getId(), history.getRole(), history.getContent(), history.getTimestamp()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
java.util.Collections.reverse(messages);
|
||||||
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -93,7 +126,7 @@ public class ConversationHistoryManager {
|
||||||
*/
|
*/
|
||||||
public void clearConversationHistory(String sessionId) {
|
public void clearConversationHistory(String sessionId) {
|
||||||
if (sessionId != null) {
|
if (sessionId != null) {
|
||||||
sessionHistoryMap.remove(sessionId);
|
aiConversationHistoryService.deleteBySessionId(sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +139,7 @@ public class ConversationHistoryManager {
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
List<Message> history = sessionHistoryMap.get(sessionId);
|
List<AiConversationHistory> historyList = aiConversationHistoryService.getBySessionId(sessionId);
|
||||||
return history != null ? history.size() : 0;
|
return historyList.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,10 +3,12 @@ package cn.qihangerp.erp.serviceImpl;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 会话管理服务,用于管理用户的会话ID
|
* 会话管理服务,用于管理用户的会话ID
|
||||||
*/
|
*/
|
||||||
|
@Component
|
||||||
public class SessionManager {
|
public class SessionManager {
|
||||||
private static final Map<Long, String> userIdSessionMap = new ConcurrentHashMap<>();
|
private static final Map<Long, String> userIdSessionMap = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, Long> sessionUserIdMap = new ConcurrentHashMap<>();
|
private static final Map<String, Long> sessionUserIdMap = new ConcurrentHashMap<>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package cn.qihangerp.mapper;
|
||||||
|
|
||||||
|
import cn.qihangerp.model.entity.AiConversationHistory;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI聊天历史Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface AiConversationHistoryMapper extends BaseMapper<AiConversationHistory> {
|
||||||
|
/**
|
||||||
|
* 根据会话ID获取聊天历史
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @return 聊天历史列表
|
||||||
|
*/
|
||||||
|
List<AiConversationHistory> selectBySessionId(@Param("sessionId") String sessionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据会话ID获取最近的聊天历史
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @param limit 限制数量
|
||||||
|
* @return 最近的聊天历史列表
|
||||||
|
*/
|
||||||
|
List<AiConversationHistory> selectRecentBySessionId(@Param("sessionId") String sessionId, @Param("limit") int limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户ID获取会话ID列表
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 会话ID列表
|
||||||
|
*/
|
||||||
|
List<String> selectSessionIdsByUserId(@Param("userId") Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据会话ID删除聊天历史
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @return 删除的记录数
|
||||||
|
*/
|
||||||
|
int deleteBySessionId(@Param("sessionId") String sessionId);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?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="cn.qihangerp.mapper.AiConversationHistoryMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="cn.qihangerp.model.entity.AiConversationHistory">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="userId" column="user_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="sessionId" column="session_id" jdbcType="VARCHAR"/>
|
||||||
|
<result property="role" column="role" jdbcType="VARCHAR"/>
|
||||||
|
<result property="content" column="content" jdbcType="LONGVARCHAR"/>
|
||||||
|
<result property="timestamp" column="timestamp" jdbcType="BIGINT"/>
|
||||||
|
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id, user_id, session_id, role, content, timestamp, create_time, update_time
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectBySessionId" parameterType="String" resultMap="BaseResultMap">
|
||||||
|
select
|
||||||
|
<include refid="Base_Column_List"/>
|
||||||
|
from ai_conversation_history
|
||||||
|
where session_id = #{sessionId}
|
||||||
|
order by timestamp asc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectRecentBySessionId" parameterType="map" resultMap="BaseResultMap">
|
||||||
|
select
|
||||||
|
<include refid="Base_Column_List"/>
|
||||||
|
from ai_conversation_history
|
||||||
|
where session_id = #{sessionId}
|
||||||
|
order by timestamp desc
|
||||||
|
limit #{limit}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectSessionIdsByUserId" parameterType="Long" resultType="String">
|
||||||
|
select distinct session_id
|
||||||
|
from ai_conversation_history
|
||||||
|
where user_id = #{userId}
|
||||||
|
order by create_time desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<delete id="deleteBySessionId" parameterType="String">
|
||||||
|
delete from ai_conversation_history
|
||||||
|
where session_id = #{sessionId}
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
CREATE TABLE `ai_conversation_history` (
|
||||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id,自增',
|
||||||
|
`user_id` bigint(20) NOT NULL COMMENT '用户id',
|
||||||
|
`session_id` varchar(36) NOT NULL COMMENT '会话id',
|
||||||
|
`role` varchar(20) NOT NULL COMMENT '角色:user或assistant',
|
||||||
|
`content` text NOT NULL COMMENT '消息内容',
|
||||||
|
`timestamp` bigint(20) NOT NULL COMMENT '消息时间戳',
|
||||||
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_session_id` (`session_id`),
|
||||||
|
KEY `idx_user_id` (`user_id`),
|
||||||
|
KEY `idx_timestamp` (`timestamp`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI聊天历史表';
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package cn.qihangerp.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 lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI聊天历史表
|
||||||
|
* @TableName ai_conversation_history
|
||||||
|
*/
|
||||||
|
@TableName(value = "ai_conversation_history")
|
||||||
|
@Data
|
||||||
|
public class AiConversationHistory implements Serializable {
|
||||||
|
/**
|
||||||
|
* 主键id,自增
|
||||||
|
*/
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户id
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话id
|
||||||
|
*/
|
||||||
|
private String sessionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色:user或assistant
|
||||||
|
*/
|
||||||
|
private String role;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息时间戳
|
||||||
|
*/
|
||||||
|
private Long timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package cn.qihangerp.service;
|
||||||
|
|
||||||
|
import cn.qihangerp.model.entity.AiConversationHistory;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI聊天历史Service
|
||||||
|
*/
|
||||||
|
public interface IAiConversationHistoryService extends IService<AiConversationHistory> {
|
||||||
|
/**
|
||||||
|
* 根据会话ID获取聊天历史
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @return 聊天历史列表
|
||||||
|
*/
|
||||||
|
List<AiConversationHistory> getBySessionId(String sessionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据会话ID获取最近的聊天历史
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @param limit 限制数量
|
||||||
|
* @return 最近的聊天历史列表
|
||||||
|
*/
|
||||||
|
List<AiConversationHistory> getRecentBySessionId(String sessionId, int limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户ID获取会话ID列表
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 会话ID列表
|
||||||
|
*/
|
||||||
|
List<String> getSessionIdsByUserId(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据会话ID删除聊天历史
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @return 删除的记录数
|
||||||
|
*/
|
||||||
|
int deleteBySessionId(String sessionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存聊天消息
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @param role 角色
|
||||||
|
* @param content 内容
|
||||||
|
* @return 保存的消息
|
||||||
|
*/
|
||||||
|
AiConversationHistory saveMessage(Long userId, String sessionId, String role, String content);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package cn.qihangerp.service.impl;
|
||||||
|
|
||||||
|
import cn.qihangerp.mapper.AiConversationHistoryMapper;
|
||||||
|
import cn.qihangerp.model.entity.AiConversationHistory;
|
||||||
|
import cn.qihangerp.service.IAiConversationHistoryService;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI聊天历史Service实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AiConversationHistoryServiceImpl extends ServiceImpl<AiConversationHistoryMapper, AiConversationHistory> implements IAiConversationHistoryService {
|
||||||
|
|
||||||
|
private final AiConversationHistoryMapper aiConversationHistoryMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiConversationHistory> getBySessionId(String sessionId) {
|
||||||
|
return aiConversationHistoryMapper.selectBySessionId(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiConversationHistory> getRecentBySessionId(String sessionId, int limit) {
|
||||||
|
return aiConversationHistoryMapper.selectRecentBySessionId(sessionId, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSessionIdsByUserId(Long userId) {
|
||||||
|
return aiConversationHistoryMapper.selectSessionIdsByUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteBySessionId(String sessionId) {
|
||||||
|
return aiConversationHistoryMapper.deleteBySessionId(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AiConversationHistory saveMessage(Long userId, String sessionId, String role, String content) {
|
||||||
|
AiConversationHistory history = new AiConversationHistory();
|
||||||
|
history.setUserId(userId);
|
||||||
|
history.setSessionId(sessionId);
|
||||||
|
history.setRole(role);
|
||||||
|
history.setContent(content);
|
||||||
|
history.setTimestamp(System.currentTimeMillis());
|
||||||
|
history.setCreateTime(new Date());
|
||||||
|
history.setUpdateTime(new Date());
|
||||||
|
save(history);
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -269,7 +269,33 @@ export default {
|
||||||
console.log('收到心跳:', event.data);
|
console.log('收到心跳:', event.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听错误
|
// 监听后端发送的错误信息
|
||||||
|
this.sse.addEventListener('error', (event) => {
|
||||||
|
console.log('收到错误信息:', event.data);
|
||||||
|
try {
|
||||||
|
// 解析错误信息
|
||||||
|
const errorData = JSON.parse(event.data);
|
||||||
|
if (errorData.error) {
|
||||||
|
// 移除正在思考的消息
|
||||||
|
if (this.isLoading) {
|
||||||
|
this.messages = this.messages.filter(msg => !msg.isLoading);
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
// 显示错误信息
|
||||||
|
this.messages.push({
|
||||||
|
content: `错误: ${errorData.error}`,
|
||||||
|
time: this.formatTime(new Date()),
|
||||||
|
isMe: false,
|
||||||
|
avatar: ''
|
||||||
|
});
|
||||||
|
this.scrollToBottom();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析错误信息失败:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听连接错误
|
||||||
this.sse.onerror = (error) => {
|
this.sse.onerror = (error) => {
|
||||||
console.error('SSE连接错误:', error);
|
console.error('SSE连接错误:', error);
|
||||||
this.isSseConnected = false;
|
this.isSseConnected = false;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue