package handler import ( "net/http" "time" "github.com/gin-gonic/gin" "kefu-sys/server/internal/model" ) type WidgetHandler struct{} func NewWidgetHandler() *WidgetHandler { return &WidgetHandler{} } type WidgetInitReq struct { ChannelKey string `json:"channel_key" form:"channel_key"` VisitorName string `json:"visitor_name"` } type WidgetMessageReq struct { SessionID uint `json:"session_id" binding:"required"` Content string `json:"content" binding:"required"` Type string `json:"type"` } func (h *WidgetHandler) Init(c *gin.Context) { var req WidgetInitReq if err := c.ShouldBindQuery(&req); err != nil && c.ShouldBindJSON(&req) != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "参数错误"}) return } if req.ChannelKey == "" { req.ChannelKey = c.Query("channel_key") } var channel model.Channel if err := model.DB.Where("script_code LIKE ?", "%"+req.ChannelKey+"%").Or("script_code LIKE ?", "%"+req.ChannelKey+"%").First(&channel).Error; err != nil { // 如果没有匹配的渠道,使用第一个启用的渠道 if err := model.DB.Where("type = ? AND status = ?", "web", "enabled").First(&channel).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"code": 404, "message": "渠道不存在"}) return } } name := req.VisitorName if name == "" { name = "访客" } // 创建或查找客户 var customer model.Customer model.DB.Where("tenant_id = ? AND name = ? AND phone = ''", channel.TenantID, name).First(&customer) if customer.ID == 0 { customer = model.Customer{ TenantID: channel.TenantID, Name: name, Source: "网页", Status: "online", } model.DB.Create(&customer) } // 创建会话 session := model.Session{ TenantID: channel.TenantID, ChannelID: channel.ID, CustomerID: customer.ID, Status: "waiting", Priority: "normal", } model.DB.Create(&session) c.JSON(http.StatusOK, gin.H{ "code": 0, "data": gin.H{ "session_id": session.ID, "customer_id": customer.ID, "channel_id": channel.ID, "tenant_id": channel.TenantID, }, }) } func (h *WidgetHandler) SendMessage(c *gin.Context) { var req WidgetMessageReq if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "参数错误"}) return } if req.Type == "" { req.Type = "text" } var session model.Session if err := model.DB.First(&session, req.SessionID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"code": 404, "message": "会话不存在"}) return } // 如果是等待中的会话,更新为活跃 if session.Status == "waiting" { model.DB.Model(&session).Update("status", "active") } var maxSeq int model.DB.Model(&model.Message{}).Where("session_id = ?", session.ID).Select("COALESCE(MAX(seq), 0)").Scan(&maxSeq) custID := session.CustomerID msg := model.Message{ SessionID: session.ID, SenderType: "visitor", SenderID: &custID, Content: req.Content, Type: req.Type, Seq: maxSeq + 1, SentAt: time.Now(), } if err := model.DB.Create(&msg).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "发送失败"}) return } c.JSON(http.StatusOK, gin.H{"code": 0, "data": msg}) } func (h *WidgetHandler) GetMessages(c *gin.Context) { sessionID := c.Query("session_id") var messages []model.Message model.DB.Where("session_id = ?", sessionID).Order("seq asc").Find(&messages) c.JSON(http.StatusOK, gin.H{"code": 0, "data": messages}) }