handler.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package websocket
  2. import (
  3. "log"
  4. "net/http"
  5. "strconv"
  6. "github.com/2930134478/AI-CS/backend/repository"
  7. "github.com/2930134478/AI-CS/backend/utils"
  8. "github.com/gin-gonic/gin"
  9. "github.com/gorilla/websocket"
  10. )
  11. var upgrader = websocket.Upgrader{
  12. ReadBufferSize: 1024,
  13. WriteBufferSize: 1024,
  14. // 允许跨域连接
  15. CheckOrigin: func(r *http.Request) bool {
  16. return true
  17. },
  18. }
  19. // HandleWebSocket 处理 WebSocket 连接
  20. func HandleWebSocket(hub *Hub, userRepo *repository.UserRepository) gin.HandlerFunc {
  21. return func(c *gin.Context) {
  22. // 从查询参数获取对话ID
  23. conversationIDStr := c.Query("conversation_id")
  24. if conversationIDStr == "" {
  25. c.JSON(http.StatusBadRequest, gin.H{"error": "conversation_id 不能为空"})
  26. return
  27. }
  28. conversationID, err := strconv.ParseUint(conversationIDStr, 10, 32)
  29. if err != nil {
  30. c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 conversation_id"})
  31. return
  32. }
  33. // 从查询参数获取是否是访客(默认为 true,因为默认是访客连接)
  34. isVisitorStr := c.DefaultQuery("is_visitor", "true")
  35. isVisitor := isVisitorStr == "true" || isVisitorStr == "1"
  36. // 从查询参数获取客服ID(如果是客服连接,需要传递 agent_id)
  37. var agentID uint
  38. if !isVisitor {
  39. agentIDStr := c.Query("agent_id")
  40. if agentIDStr == "" {
  41. c.JSON(http.StatusBadRequest, gin.H{"error": "agent_id 不能为空"})
  42. return
  43. }
  44. parsed, parseErr := strconv.ParseUint(agentIDStr, 10, 32)
  45. if parseErr != nil || parsed == 0 {
  46. c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 agent_id"})
  47. return
  48. }
  49. agentID = uint(parsed)
  50. wsToken := c.Query("ws_token")
  51. if !utils.ValidateWSToken(wsToken, agentID) {
  52. c.JSON(http.StatusUnauthorized, gin.H{"error": "ws_token 无效或已过期"})
  53. return
  54. }
  55. if userRepo != nil {
  56. user, userErr := userRepo.GetByID(agentID)
  57. if userErr != nil || user == nil {
  58. c.JSON(http.StatusUnauthorized, gin.H{"error": "客服身份无效"})
  59. return
  60. }
  61. if user.Role != "admin" && user.Role != "agent" {
  62. c.JSON(http.StatusForbidden, gin.H{"error": "仅客服账号允许建立该连接"})
  63. return
  64. }
  65. }
  66. }
  67. // 升级 HTTP 连接为 WebSocket 连接
  68. conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
  69. if err != nil {
  70. log.Printf("WebSocket 升级失败: %v", err)
  71. return
  72. }
  73. // 创建客户端
  74. client := NewClient(hub, conn, uint(conversationID), isVisitor, agentID)
  75. // 注册客户端到 Hub
  76. client.hub.register <- client
  77. // 启动两个 goroutine:
  78. // 1. ReadPump:从客户端读取消息(主要是心跳包)
  79. // 2. WritePump:向客户端发送消息
  80. go client.WritePump()
  81. go client.ReadPump()
  82. log.Printf("✅ WebSocket 连接已建立: 对话ID=%d, 是访客=%v", conversationID, isVisitor)
  83. }
  84. }