diff --git a/src/main/java/com/wecom/robot/config/GlobalExceptionHandler.java b/src/main/java/com/wecom/robot/config/GlobalExceptionHandler.java new file mode 100644 index 0000000..db17d99 --- /dev/null +++ b/src/main/java/com/wecom/robot/config/GlobalExceptionHandler.java @@ -0,0 +1,46 @@ +package com.wecom.robot.config; + +import com.wecom.robot.dto.ApiResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import java.util.stream.Collectors; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ApiResponse handleValidationException(MethodArgumentNotValidException ex) { + String message = ex.getBindingResult().getFieldErrors().stream() + .map(FieldError::getDefaultMessage) + .collect(Collectors.joining("; ")); + log.warn("参数校验失败: {}", message); + return ApiResponse.error(400, message); + } + + @ExceptionHandler(ConstraintViolationException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ApiResponse handleConstraintViolationException(ConstraintViolationException ex) { + String message = ex.getConstraintViolations().stream() + .map(ConstraintViolation::getMessage) + .collect(Collectors.joining("; ")); + log.warn("约束校验失败: {}", message); + return ApiResponse.error(400, message); + } + + @ExceptionHandler(Exception.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ApiResponse handleException(Exception ex) { + log.error("服务器内部错误", ex); + return ApiResponse.error(500, "服务器内部错误"); + } +} diff --git a/src/main/java/com/wecom/robot/controller/SessionController.java b/src/main/java/com/wecom/robot/controller/SessionController.java index f1e453f..4ddd9ff 100644 --- a/src/main/java/com/wecom/robot/controller/SessionController.java +++ b/src/main/java/com/wecom/robot/controller/SessionController.java @@ -13,6 +13,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; import java.util.List; import java.util.stream.Collectors; @@ -31,7 +32,8 @@ public class SessionController { @GetMapping public ApiResponse> getSessions( @RequestParam(required = false) String status, - @RequestParam(required = false) String csId) { + @RequestParam(required = false) String csId, + @RequestParam(required = false) String channelType) { LambdaQueryWrapper query = new LambdaQueryWrapper<>(); if (status != null) { @@ -42,6 +44,10 @@ public class SessionController { query.eq(Session::getManualCsId, csId); } + if (channelType != null) { + query.eq(Session::getChannelType, channelType); + } + query.orderByDesc(Session::getUpdatedAt); List sessions = sessionMapper.selectList(query); @@ -51,6 +57,7 @@ public class SessionController { info.setSessionId(session.getSessionId()); info.setCustomerId(session.getCustomerId()); info.setKfId(session.getKfId()); + info.setChannelType(session.getChannelType()); info.setStatus(session.getStatus()); info.setManualCsId(session.getManualCsId()); info.setCreatedAt(session.getCreatedAt()); @@ -87,6 +94,7 @@ public class SessionController { info.setSessionId(session.getSessionId()); info.setCustomerId(session.getCustomerId()); info.setKfId(session.getKfId()); + info.setChannelType(session.getChannelType()); info.setStatus(session.getStatus()); info.setManualCsId(session.getManualCsId()); info.setCreatedAt(session.getCreatedAt()); @@ -120,12 +128,9 @@ public class SessionController { } @PostMapping("/{sessionId}/accept") - public ApiResponse acceptSession(@PathVariable String sessionId, @RequestBody AcceptSessionRequest request) { - String csId = request.getCsId(); - if (csId == null || csId.isEmpty()) { - return ApiResponse.error(400, "客服ID不能为空"); - } - + public ApiResponse acceptSession( + @PathVariable String sessionId, + @Valid @RequestBody AcceptSessionRequest request) { Session session = sessionMapper.selectById(sessionId); if (session == null) { return ApiResponse.error(404, "会话不存在"); @@ -135,14 +140,16 @@ public class SessionController { return ApiResponse.error(400, "会话状态不正确"); } - sessionManagerService.acceptTransfer(sessionId, csId); - webSocketService.notifySessionAccepted(sessionId, csId); + sessionManagerService.acceptTransfer(sessionId, request.getCsId()); + webSocketService.notifySessionAccepted(sessionId, request.getCsId()); return ApiResponse.success(null); } @PostMapping("/{sessionId}/message") - public ApiResponse sendMessage(@PathVariable String sessionId, @RequestBody SendMessageRequest request) { + public ApiResponse sendMessage( + @PathVariable String sessionId, + @Valid @RequestBody SendMessageRequest request) { Session session = sessionMapper.selectById(sessionId); if (session == null) { return ApiResponse.error(404, "会话不存在"); @@ -159,7 +166,7 @@ public class SessionController { ); if (!success) { - return ApiResponse.error("消息发送失败"); + return ApiResponse.error(500, "消息发送失败"); } sessionManagerService.saveMessage( diff --git a/src/main/java/com/wecom/robot/dto/AcceptSessionRequest.java b/src/main/java/com/wecom/robot/dto/AcceptSessionRequest.java index 7cf1efc..8162911 100644 --- a/src/main/java/com/wecom/robot/dto/AcceptSessionRequest.java +++ b/src/main/java/com/wecom/robot/dto/AcceptSessionRequest.java @@ -2,8 +2,13 @@ package com.wecom.robot.dto; import lombok.Data; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + @Data public class AcceptSessionRequest { + @NotBlank(message = "客服ID不能为空") + @Size(min = 1, max = 64, message = "客服ID长度必须在1-64之间") private String csId; } diff --git a/src/main/java/com/wecom/robot/dto/ApiResponse.java b/src/main/java/com/wecom/robot/dto/ApiResponse.java index 3868657..367c811 100644 --- a/src/main/java/com/wecom/robot/dto/ApiResponse.java +++ b/src/main/java/com/wecom/robot/dto/ApiResponse.java @@ -11,7 +11,7 @@ public class ApiResponse { public static ApiResponse success(T data) { ApiResponse response = new ApiResponse<>(); - response.setCode(200); + response.setCode(0); response.setMessage("success"); response.setData(data); return response; diff --git a/src/main/java/com/wecom/robot/dto/MessageInfo.java b/src/main/java/com/wecom/robot/dto/MessageInfo.java index 9ad7a8e..becc891 100644 --- a/src/main/java/com/wecom/robot/dto/MessageInfo.java +++ b/src/main/java/com/wecom/robot/dto/MessageInfo.java @@ -2,16 +2,31 @@ package com.wecom.robot.dto; import lombok.Data; -import java.time.LocalDateTime; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; @Data public class MessageInfo { + @NotBlank + @Size(min = 1, max = 128) private String msgId; + + @NotBlank + @Size(min = 1, max = 64) private String sessionId; + + @NotBlank private String senderType; + + @Size(max = 64) private String senderId; + + @NotBlank + @Size(min = 1, max = 4096) private String content; + private String msgType; - private LocalDateTime createdAt; + + private java.time.LocalDateTime createdAt; } diff --git a/src/main/java/com/wecom/robot/dto/SendMessageRequest.java b/src/main/java/com/wecom/robot/dto/SendMessageRequest.java index 65f653c..c9badc3 100644 --- a/src/main/java/com/wecom/robot/dto/SendMessageRequest.java +++ b/src/main/java/com/wecom/robot/dto/SendMessageRequest.java @@ -2,9 +2,15 @@ package com.wecom.robot.dto; import lombok.Data; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + @Data public class SendMessageRequest { + @NotBlank(message = "消息内容不能为空") + @Size(min = 1, max = 4096, message = "消息内容长度必须在1-4096之间") private String content; + private String msgType; } diff --git a/src/main/java/com/wecom/robot/dto/SessionInfo.java b/src/main/java/com/wecom/robot/dto/SessionInfo.java index 425c092..0b7a912 100644 --- a/src/main/java/com/wecom/robot/dto/SessionInfo.java +++ b/src/main/java/com/wecom/robot/dto/SessionInfo.java @@ -2,20 +2,43 @@ package com.wecom.robot.dto; import lombok.Data; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.time.LocalDateTime; @Data public class SessionInfo { + @NotBlank + @Size(min = 1, max = 64) private String sessionId; + + @NotBlank + @Size(min = 1, max = 64) private String customerId; + + @Size(max = 64) private String kfId; + + @Size(max = 64) + private String channelType; + + @NotBlank private String status; + + @Size(max = 64) private String manualCsId; - private LocalDateTime createdAt; - private LocalDateTime updatedAt; - private String metadata; - private int messageCount; + + @Size(max = 4096) private String lastMessage; + private LocalDateTime lastMessageTime; + + private int messageCount; + + private LocalDateTime createdAt; + + private LocalDateTime updatedAt; + + private String metadata; }