135 lines
3.5 KiB
Go
135 lines
3.5 KiB
Go
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})
|
|
}
|