feat: 完善后端架构和service层实现

- 创建完整的entity实体类体系,包括所有业务实体
- 实现BaseEntity基类,统一管理公共字段
- 创建雪花算法ID生成器和自动填充处理器
- 简化所有mapper接口,只继承BaseMapper
- 重构service层,使用LambdaQueryWrapper进行数据库操作
- 创建BasePageRequest分页查询基类
- 完善用户上下文管理和JWT认证
- 新增WebSocket聊天功能和相关控制器
- 更新前端配置和组件,完善用户认证流程
- 同步数据库建表脚本
This commit is contained in:
2025-07-24 00:37:23 +08:00
parent 645036fcd2
commit 880e0e3c88
87 changed files with 8114 additions and 1106 deletions
@@ -0,0 +1,162 @@
package com.emotion.controller;
import com.emotion.common.Result;
import com.emotion.service.IAiService;
import com.emotion.service.IMessageService;
import com.emotion.service.IConversationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* AI聊天控制器
*
* @author emotion-museum
* @date 2025-07-23
*/
@Slf4j
@RestController
@RequestMapping("/api/ai")
public class AiChatController {
@Autowired
private IAiService aiService;
@Autowired
private IMessageService messageService;
@Autowired
private IConversationService conversationService;
/**
* 发送聊天消息
*/
@PostMapping("/chat")
public Result<Map<String, Object>> sendChatMessage(@RequestBody Map<String, String> request) {
try {
String conversationId = request.get("conversationId");
String message = request.get("message");
String userId = request.get("userId");
if (message == null || message.trim().isEmpty()) {
return Result.error("消息内容不能为空");
}
if (userId == null || userId.trim().isEmpty()) {
userId = "guest_" + System.currentTimeMillis();
}
log.info("收到AI聊天请求: conversationId={}, userId={}, message={}",
conversationId, userId, message);
// 调用AI服务
String aiReply = aiService.sendChatMessage(conversationId, message, userId);
Map<String, Object> response = new HashMap<>();
response.put("conversationId", conversationId);
response.put("userMessage", message);
response.put("aiReply", aiReply);
response.put("userId", userId);
response.put("timestamp", System.currentTimeMillis());
return Result.success(response);
} catch (Exception e) {
log.error("AI聊天请求处理失败", e);
return Result.error("AI聊天服务暂时不可用,请稍后再试");
}
}
/**
* 生成对话总结
*/
@PostMapping("/summary")
public Result<Map<String, Object>> generateSummary(@RequestBody Map<String, String> request) {
try {
String conversationId = request.get("conversationId");
String userId = request.get("userId");
if (conversationId == null || conversationId.trim().isEmpty()) {
return Result.error("会话ID不能为空");
}
if (userId == null || userId.trim().isEmpty()) {
userId = "guest_" + System.currentTimeMillis();
}
log.info("收到对话总结请求: conversationId={}, userId={}", conversationId, userId);
// 调用AI总结服务
String summary = aiService.generateConversationSummary(conversationId, userId);
Map<String, Object> response = new HashMap<>();
response.put("conversationId", conversationId);
response.put("summary", summary);
response.put("userId", userId);
response.put("timestamp", System.currentTimeMillis());
return Result.success(response);
} catch (Exception e) {
log.error("对话总结请求处理失败", e);
return Result.error("对话总结服务暂时不可用,请稍后再试");
}
}
/**
* 获取AI服务状态
*/
@GetMapping("/status")
public Result<Map<String, Object>> getServiceStatus() {
try {
boolean available = aiService.isServiceAvailable();
String status = aiService.getServiceStatus();
Map<String, Object> response = new HashMap<>();
response.put("available", available);
response.put("status", status);
response.put("timestamp", System.currentTimeMillis());
return Result.success(response);
} catch (Exception e) {
log.error("获取AI服务状态失败", e);
return Result.error("无法获取AI服务状态");
}
}
/**
* 获取聊天记录统计
*/
@GetMapping("/stats")
public Result<Map<String, Object>> getChatStats(@RequestParam(required = false) String userId,
@RequestParam(required = false) String conversationId) {
try {
Map<String, Object> stats = new HashMap<>();
if (userId != null && !userId.trim().isEmpty()) {
Long userConversationCount = conversationService.countByUserId(userId);
Long activeConversationCount = conversationService.countActiveByUserId(userId);
stats.put("userConversationCount", userConversationCount);
stats.put("activeConversationCount", activeConversationCount);
}
if (conversationId != null && !conversationId.trim().isEmpty()) {
Long conversationMessageCount = messageService.countByConversationId(conversationId);
stats.put("conversationMessageCount", conversationMessageCount);
}
stats.put("timestamp", System.currentTimeMillis());
return Result.success(stats);
} catch (Exception e) {
log.error("获取聊天统计失败", e);
return Result.error("无法获取聊天统计信息");
}
}
}
@@ -11,6 +11,11 @@ import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import com.emotion.util.JwtUtil;
import javax.servlet.http.HttpServletRequest;
/**
* 认证控制器
@@ -24,9 +29,15 @@ public class AuthController {
private static final Logger log = LoggerFactory.getLogger(AuthController.class);
// 验证码存储(生产环境应使用Redis)
private static final Map<String, String> captchaStore = new ConcurrentHashMap<>();
@Autowired
private UserService userService;
@Autowired
private JwtUtil jwtUtil;
/**
* 用户登录
*/
@@ -37,10 +48,30 @@ public class AuthController {
try {
String account = request.get("account");
String password = request.get("password");
String captcha = request.get("captcha");
String captchaKey = request.get("captchaKey");
if (account == null || password == null) {
return Result.error("账号和密码不能为空");
}
// 验证验证码
if (captcha == null || captchaKey == null) {
return Result.error("验证码不能为空");
}
String storedCaptcha = captchaStore.get(captchaKey);
if (storedCaptcha == null) {
return Result.error("验证码已过期");
}
if (!storedCaptcha.equals(captcha.toLowerCase())) {
captchaStore.remove(captchaKey); // 验证失败后移除验证码
return Result.error("验证码错误");
}
// 验证成功后移除验证码
captchaStore.remove(captchaKey);
// 查找用户
User user = userService.findByAccount(account);
@@ -56,9 +87,14 @@ public class AuthController {
// 更新最后活跃时间
userService.updateLastActiveTime(user.getId());
// 生成JWT token
String accessToken = jwtUtil.generateToken(user.getId(), user.getUsername());
String refreshToken = jwtUtil.generateRefreshToken(user.getId(), user.getUsername());
// 构建响应
Map<String, Object> response = new HashMap<>();
response.put("accessToken", "token-" + user.getId() + "-" + System.currentTimeMillis());
response.put("accessToken", accessToken);
response.put("refreshToken", refreshToken);
response.put("expiresIn", 86400L);
Map<String, Object> userInfo = new HashMap<>();
@@ -85,7 +121,7 @@ public class AuthController {
@PostMapping("/register")
public Result<Map<String, Object>> register(@RequestBody Map<String, String> request) {
log.info("用户注册请求: {}", request.get("account"));
try {
String account = request.get("account");
String password = request.get("password");
@@ -93,11 +129,31 @@ public class AuthController {
String email = request.get("email");
String phone = request.get("phone");
String nickname = request.get("nickname");
String captcha = request.get("captcha");
String captchaKey = request.get("captchaKey");
if (account == null || password == null) {
return Result.error("账号和密码不能为空");
}
// 验证验证码
if (captcha == null || captchaKey == null) {
return Result.error("验证码不能为空");
}
String storedCaptcha = captchaStore.get(captchaKey);
if (storedCaptcha == null) {
return Result.error("验证码已过期");
}
if (!storedCaptcha.equals(captcha.toLowerCase())) {
captchaStore.remove(captchaKey); // 验证失败后移除验证码
return Result.error("验证码错误");
}
// 验证成功后移除验证码
captchaStore.remove(captchaKey);
// 检查账号是否已存在
if (userService.accountExists(account)) {
return Result.error("账号已存在");
@@ -113,37 +169,112 @@ public class AuthController {
user.setNickname(nickname != null ? nickname : username != null ? username : account);
User createdUser = userService.createUser(user);
// 构建响应
// 生成JWT token(注册成功后自动登录)
String accessToken = jwtUtil.generateToken(createdUser.getId(), createdUser.getUsername());
String refreshToken = jwtUtil.generateRefreshToken(createdUser.getId(), createdUser.getUsername());
// 构建用户信息
Map<String, Object> userInfo = new HashMap<>();
userInfo.put("id", createdUser.getId());
userInfo.put("username", createdUser.getUsername());
userInfo.put("account", createdUser.getAccount());
userInfo.put("nickname", createdUser.getNickname());
userInfo.put("avatar", createdUser.getAvatar());
userInfo.put("status", createdUser.getStatus());
userInfo.put("createTime", createdUser.getCreateTime());
return Result.success("注册成功", userInfo);
// 构建完整响应(包含token信息)
Map<String, Object> response = new HashMap<>();
response.put("accessToken", accessToken);
response.put("refreshToken", refreshToken);
response.put("expiresIn", 86400L); // 24小时
response.put("userInfo", userInfo);
response.put("loginTime", LocalDateTime.now());
log.info("用户注册并自动登录成功: {}", createdUser.getAccount());
return Result.success("注册成功,已自动登录", response);
} catch (Exception e) {
log.error("用户注册失败: {}", e.getMessage());
return Result.error("注册失败: " + e.getMessage());
}
}
/**
* 获取当前用户信息
*/
@GetMapping("/user-info")
public Result<Map<String, Object>> getCurrentUserInfo(HttpServletRequest request) {
try {
// 从请求属性中获取用户信息(由JWT拦截器设置)
String userId = (String) request.getAttribute("userId");
String username = (String) request.getAttribute("username");
if (userId == null) {
return Result.error("用户未登录");
}
// 根据用户ID获取完整用户信息
User user = userService.findById(userId);
if (user == null) {
return Result.error("用户不存在");
}
// 构建用户信息响应
Map<String, Object> userInfo = new HashMap<>();
userInfo.put("id", user.getId());
userInfo.put("username", user.getUsername());
userInfo.put("account", user.getAccount());
userInfo.put("nickname", user.getNickname());
userInfo.put("avatar", user.getAvatar());
userInfo.put("email", user.getEmail());
userInfo.put("phone", user.getPhone());
userInfo.put("status", user.getStatus());
userInfo.put("createTime", user.getCreateTime());
return Result.success("获取用户信息成功", userInfo);
} catch (Exception e) {
log.error("获取用户信息失败: {}", e.getMessage());
return Result.error("获取用户信息失败");
}
}
/**
* 获取验证码
*/
@GetMapping("/captcha")
public Result<Map<String, Object>> getCaptcha() {
log.info("获取验证码请求");
try {
// 生成验证码
SpecCaptcha captcha = new SpecCaptcha(130, 48, 4);
captcha.setCharType(Captcha.TYPE_DEFAULT);
// 生成验证码key
String captchaKey = "captcha_" + System.currentTimeMillis();
String captchaText = captcha.text().toLowerCase();
// 存储验证码(5分钟过期)
captchaStore.put(captchaKey, captchaText);
// 5分钟后清理验证码
new Thread(() -> {
try {
Thread.sleep(300000); // 5分钟
captchaStore.remove(captchaKey);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
Map<String, Object> response = new HashMap<>();
response.put("captchaId", "captcha-" + System.currentTimeMillis());
response.put("captchaImage", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==");
response.put("type", "spec");
response.put("key", captchaKey);
response.put("image", captcha.toBase64().replace("data:image/png;base64,", ""));
response.put("expireTime", 300);
log.info("生成验证码成功,key: {}, text: {}", captchaKey, captchaText);
return Result.success("获取验证码成功", response);
} catch (Exception e) {
log.error("获取验证码失败: {}", e.getMessage());
@@ -0,0 +1,139 @@
package com.emotion.controller;
import com.emotion.dto.websocket.ChatRequest;
import com.emotion.dto.websocket.ConnectRequest;
import com.emotion.service.WebSocketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.stereotype.Controller;
import javax.validation.Valid;
import java.security.Principal;
/**
* 优化的WebSocket聊天控制器
* 使用规范的请求对象封装参数
*
* @author emotion-museum
* @date 2025-07-23
*/
@Slf4j
@Controller
public class ChatWebSocketController {
@Autowired
private WebSocketService webSocketService;
/**
* 处理聊天消息
* @param chatRequest 聊天请求对象
* @param headerAccessor 消息头访问器
* @param principal 用户主体
*/
@MessageMapping("/chat.send")
public void handleChatMessage(@Valid @Payload ChatRequest chatRequest,
SimpMessageHeaderAccessor headerAccessor,
Principal principal) {
try {
log.info("收到WebSocket聊天消息: {}", chatRequest);
// 获取会话ID
String sessionId = headerAccessor.getSessionId();
// 如果请求中没有发送者ID,尝试从Principal获取
if (chatRequest.getSenderId() == null && principal != null) {
chatRequest.setSenderId(principal.getName());
}
// 如果还是没有发送者ID,使用会话ID作为访客ID
if (chatRequest.getSenderId() == null) {
chatRequest.setSenderId("guest_" + sessionId);
chatRequest.setSenderType(ChatRequest.SenderType.GUEST);
}
// 设置时间戳
if (chatRequest.getTimestamp() == null) {
chatRequest.setTimestamp(System.currentTimeMillis());
}
// 处理聊天消息
webSocketService.handleChatMessage(chatRequest, sessionId, principal);
} catch (Exception e) {
log.error("处理WebSocket聊天消息失败", e);
}
}
/**
* 处理用户连接
* @param connectRequest 连接请求对象
* @param headerAccessor 消息头访问器
* @param principal 用户主体
*/
@MessageMapping("/chat.connect")
public void connectUser(@Payload ConnectRequest connectRequest,
SimpMessageHeaderAccessor headerAccessor,
Principal principal) {
try {
String sessionId = headerAccessor.getSessionId();
log.info("用户连接WebSocket: connectRequest={}, sessionId={}, principal={}",
connectRequest, sessionId, principal);
// 如果请求中没有用户ID,尝试从Principal获取
if (connectRequest.getUserId() == null && principal != null) {
connectRequest.setUserId(principal.getName());
}
// 设置连接时间戳
if (connectRequest.getTimestamp() == null) {
connectRequest.setTimestamp(System.currentTimeMillis());
}
// 处理用户连接
webSocketService.handleUserConnect(connectRequest, sessionId, principal);
} catch (Exception e) {
log.error("处理用户WebSocket连接失败", e);
}
}
/**
* 处理用户断开连接
* @param headerAccessor 消息头访问器
* @param principal 用户主体
*/
@MessageMapping("/chat.disconnect")
public void disconnectUser(SimpMessageHeaderAccessor headerAccessor, Principal principal) {
try {
String sessionId = headerAccessor.getSessionId();
log.info("用户断开WebSocket连接: sessionId={}, principal={}", sessionId, principal);
// 处理用户断开连接
webSocketService.handleUserDisconnect(sessionId, principal);
} catch (Exception e) {
log.error("处理用户WebSocket断开连接失败", e);
}
}
/**
* 处理心跳消息
* @param headerAccessor 消息头访问器
* @param principal 用户主体
*/
@MessageMapping("/chat.heartbeat")
public void heartbeat(SimpMessageHeaderAccessor headerAccessor, Principal principal) {
try {
String sessionId = headerAccessor.getSessionId();
// 处理心跳消息
webSocketService.handleHeartbeat(sessionId, principal);
} catch (Exception e) {
log.error("处理WebSocket心跳失败", e);
}
}
}
@@ -0,0 +1,220 @@
package com.emotion.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.emotion.common.Result;
import com.emotion.entity.Message;
import com.emotion.service.IMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 消息控制器
*
* @author emotion-museum
* @date 2025-07-23
*/
@Slf4j
@RestController
@RequestMapping("/api/message")
public class MessageController {
@Autowired
private IMessageService messageService;
/**
* 保存消息
*/
@PostMapping("/save")
public Result<Message> saveMessage(@RequestBody Map<String, String> request) {
try {
String conversationId = request.get("conversationId");
String content = request.get("content");
String type = request.get("type");
String sender = request.get("sender");
if (content == null || content.trim().isEmpty()) {
return Result.error("消息内容不能为空");
}
if (sender == null || sender.trim().isEmpty()) {
return Result.error("发送者不能为空");
}
Message message = messageService.saveMessage(conversationId, content, type, sender);
if (message != null) {
return Result.success(message);
} else {
return Result.error("保存消息失败");
}
} catch (Exception e) {
log.error("保存消息失败", e);
return Result.error("保存消息失败:" + e.getMessage());
}
}
/**
* 根据会话ID分页查询消息
*/
@GetMapping("/conversation/{conversationId}")
public Result<IPage<Message>> getMessagesByConversationId(
@PathVariable String conversationId,
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "20") Integer size) {
try {
Page<Message> page = new Page<>(current, size);
IPage<Message> result = messageService.getByConversationId(page, conversationId);
return Result.success(result);
} catch (Exception e) {
log.error("查询会话消息失败", e);
return Result.error("查询会话消息失败:" + e.getMessage());
}
}
/**
* 根据发送者分页查询消息
*/
@GetMapping("/sender/{sender}")
public Result<IPage<Message>> getMessagesBySender(
@PathVariable String sender,
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "20") Integer size) {
try {
Page<Message> page = new Page<>(current, size);
IPage<Message> result = messageService.getBySender(page, sender);
return Result.success(result);
} catch (Exception e) {
log.error("查询发送者消息失败", e);
return Result.error("查询发送者消息失败:" + e.getMessage());
}
}
/**
* 查询会话的最后一条消息
*/
@GetMapping("/last/{conversationId}")
public Result<Message> getLastMessage(@PathVariable String conversationId) {
try {
Message message = messageService.getLastMessageByConversationId(conversationId);
return Result.success(message);
} catch (Exception e) {
log.error("查询最后一条消息失败", e);
return Result.error("查询最后一条消息失败:" + e.getMessage());
}
}
/**
* 统计会话消息数量
*/
@GetMapping("/count/{conversationId}")
public Result<Long> countMessages(@PathVariable String conversationId) {
try {
Long count = messageService.countByConversationId(conversationId);
return Result.success(count);
} catch (Exception e) {
log.error("统计消息数量失败", e);
return Result.error("统计消息数量失败:" + e.getMessage());
}
}
/**
* 更新消息状态
*/
@PutMapping("/{messageId}/status")
public Result<Boolean> updateStatus(@PathVariable String messageId,
@RequestBody Map<String, String> request) {
try {
String status = request.get("status");
if (status == null || status.trim().isEmpty()) {
return Result.error("状态不能为空");
}
boolean success = messageService.updateStatus(messageId, status);
return Result.success(success);
} catch (Exception e) {
log.error("更新消息状态失败", e);
return Result.error("更新消息状态失败:" + e.getMessage());
}
}
/**
* 标记消息为已读
*/
@PutMapping("/{messageId}/read")
public Result<Boolean> markAsRead(@PathVariable String messageId) {
try {
boolean success = messageService.updateReadStatus(messageId, 1);
return Result.success(success);
} catch (Exception e) {
log.error("标记消息已读失败", e);
return Result.error("标记消息已读失败:" + e.getMessage());
}
}
/**
* 批量标记会话消息为已读
*/
@PutMapping("/conversation/{conversationId}/read")
public Result<Boolean> markConversationAsRead(@PathVariable String conversationId) {
try {
boolean success = messageService.markConversationMessagesAsRead(conversationId);
return Result.success(success);
} catch (Exception e) {
log.error("批量标记消息已读失败", e);
return Result.error("批量标记消息已读失败:" + e.getMessage());
}
}
/**
* 获取消息统计信息
*/
@GetMapping("/stats")
public Result<Map<String, Object>> getMessageStats(
@RequestParam(required = false) String conversationId,
@RequestParam(required = false) String sender) {
try {
Map<String, Object> stats = new HashMap<>();
if (conversationId != null && !conversationId.trim().isEmpty()) {
Long conversationCount = messageService.countByConversationId(conversationId);
stats.put("conversationMessageCount", conversationCount);
Message lastMessage = messageService.getLastMessageByConversationId(conversationId);
stats.put("lastMessage", lastMessage);
}
if (sender != null && !sender.trim().isEmpty()) {
Long senderCount = messageService.countBySender(sender);
stats.put("senderMessageCount", senderCount);
}
stats.put("timestamp", System.currentTimeMillis());
return Result.success(stats);
} catch (Exception e) {
log.error("获取消息统计失败", e);
return Result.error("获取消息统计失败:" + e.getMessage());
}
}
/**
* 删除会话的所有消息
*/
@DeleteMapping("/conversation/{conversationId}")
public Result<Boolean> deleteConversationMessages(@PathVariable String conversationId) {
try {
boolean success = messageService.deleteByConversationId(conversationId);
return Result.success(success);
} catch (Exception e) {
log.error("删除会话消息失败", e);
return Result.error("删除会话消息失败:" + e.getMessage());
}
}
}
@@ -1,7 +1,7 @@
package com.emotion.controller;
import com.emotion.common.Result;
import com.emotion.entity.SimpleUser;
import com.emotion.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
@@ -10,6 +10,8 @@ import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@@ -31,59 +33,9 @@ public class WebSocketController {
@Autowired
private AiService aiService;
/**
* 处理聊天消息
*/
@MessageMapping("/chat.send")
@SendTo("/topic/public")
public Map<String, Object> sendMessage(@Payload Map<String, Object> chatMessage) {
log.info("收到WebSocket消息: {}", chatMessage);
try {
String content = (String) chatMessage.get("content");
String sender = (String) chatMessage.get("sender");
String type = (String) chatMessage.get("type");
// 构建响应消息
Map<String, Object> response = new HashMap<>();
response.put("content", content);
response.put("sender", sender);
response.put("type", type);
response.put("timestamp", System.currentTimeMillis());
return response;
} catch (Exception e) {
log.error("处理WebSocket消息失败", e);
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("content", "消息处理失败");
errorResponse.put("type", "ERROR");
errorResponse.put("timestamp", System.currentTimeMillis());
return errorResponse;
}
}
// 已移除旧的WebSocket消息处理方法,使用新的ChatWebSocketController
/**
* 处理用户连接
*/
@MessageMapping("/chat.connect")
@SendTo("/topic/public")
public Map<String, Object> connectUser(@Payload Map<String, Object> chatMessage,
SimpMessageHeaderAccessor headerAccessor) {
String username = (String) chatMessage.get("sender");
// 在WebSocket会话中添加用户名
headerAccessor.getSessionAttributes().put("username", username);
log.info("用户连接: {}", username);
Map<String, Object> response = new HashMap<>();
response.put("content", username + " 加入了聊天");
response.put("type", "JOIN");
response.put("sender", "System");
response.put("timestamp", System.currentTimeMillis());
return response;
}
// 已移除旧的用户连接处理方法,使用新的ChatWebSocketController
/**
* 处理AI聊天消息
@@ -142,7 +94,22 @@ public class WebSocketController {
systemMessage.put("sender", "System");
systemMessage.put("type", "SYSTEM");
systemMessage.put("timestamp", System.currentTimeMillis());
messagingTemplate.convertAndSend(destination, systemMessage);
}
/**
* WebSocket状态监控接口
*/
@GetMapping("/api/ws/status")
@ResponseBody
public Map<String, Object> getWebSocketStatus() {
Map<String, Object> status = new HashMap<>();
status.put("status", "active");
status.put("timestamp", System.currentTimeMillis());
status.put("endpoint", "/ws/chat");
status.put("protocols", new String[]{"websocket", "sockjs"});
status.put("message", "WebSocket服务正常运行");
return status;
}
}