You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
335 lines
7.4 KiB
335 lines
7.4 KiB
|
1 year ago
|
package handler
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"mime"
|
||
|
|
"net/http"
|
||
|
|
"os"
|
||
|
|
"server/call"
|
||
|
|
"server/common"
|
||
|
|
"server/config"
|
||
|
|
"server/db"
|
||
|
|
"server/modules/web/app"
|
||
|
|
"server/modules/web/values"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
"github.com/liangdas/mqant/log"
|
||
|
|
"gorm.io/gorm"
|
||
|
|
)
|
||
|
|
|
||
|
|
// 加载客服系统配置
|
||
|
|
func GetCustomerConfig(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
var resp values.GetCustomerConfigResp
|
||
|
|
resp.Config = call.GetConfigCustomer()
|
||
|
|
a.Data = resp
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取客服机器人消息
|
||
|
|
func GetCustomerRobotList(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
req := new(values.GetCustomerRobotReq)
|
||
|
|
if !a.SB(req) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
var resp values.GetCustomerRobotResp
|
||
|
|
|
||
|
|
if req.ParentId == 0 {
|
||
|
|
resp.List = call.GetCustomerRobot(req.ParentId)
|
||
|
|
if len(resp.List) > 0 {
|
||
|
|
resp.Parent = resp.List[0]
|
||
|
|
}
|
||
|
|
resp.List = call.GetCustomerRobot(resp.List[0].ID)
|
||
|
|
} else {
|
||
|
|
resp.List = call.GetCustomerRobot(req.ParentId)
|
||
|
|
resp.Parent = call.GetCustomerRobotById(req.ParentId)
|
||
|
|
}
|
||
|
|
a.Data = resp
|
||
|
|
}
|
||
|
|
|
||
|
|
// 机器人客服消息
|
||
|
|
func GetCustomerRobotMsg(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
req := new(values.GetCustomerRobotMsgReq)
|
||
|
|
if !a.SB(req) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
var resp values.GetCustomerRobotMsgResp
|
||
|
|
resp.Content = call.GetCustomerRobotMsg(req.Id)
|
||
|
|
|
||
|
|
// 获取玩家vip等级
|
||
|
|
vip := call.GetVIP(a.UID)
|
||
|
|
|
||
|
|
data := &common.CustomerOrder{Uid: a.UID, Start: time.Now().Unix(), Vip: vip.Level, Status: common.CustomerOrderCreate}
|
||
|
|
|
||
|
|
// 创建机器人订单
|
||
|
|
err := db.Mysql().Create(data)
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
}
|
||
|
|
|
||
|
|
// 10秒内玩家没有选择满意是否就默认完成工单
|
||
|
|
time.AfterFunc(10*time.Second, func() {
|
||
|
|
err = db.Mysql().Update(data, map[string]interface{}{
|
||
|
|
"status": common.CustomerOrderComplete,
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
a.Data = resp
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取聊天历史
|
||
|
|
func GetCustomerHistory(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
req := new(values.GetCustomerHistoryReq)
|
||
|
|
if !a.SB(req) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
var resp values.GetCustomerHistoryResp
|
||
|
|
Count, err := db.Mysql().QueryList(req.Page-1, req.Num, fmt.Sprintf("title = %v", a.UID), "id DESC", &common.CustomerChatData{}, &resp.List)
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
a.Code = values.CodeRetry
|
||
|
|
return
|
||
|
|
}
|
||
|
|
resp.Count = Count
|
||
|
|
|
||
|
|
// 查询玩家上一次客服处理是否结束
|
||
|
|
data := &common.CustomerOrder{Uid: a.UID}
|
||
|
|
err = db.Mysql().GetLast(data)
|
||
|
|
if err != nil {
|
||
|
|
if err != gorm.ErrRecordNotFound {
|
||
|
|
log.Error(err.Error())
|
||
|
|
a.Code = values.CodeRetry
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 是否客服黑名单
|
||
|
|
if db.Mysql().Exist(&common.CustomerBlackUser{Uid: a.UID}) {
|
||
|
|
resp.IsBlack = true
|
||
|
|
}
|
||
|
|
|
||
|
|
resp.Status = data.Status
|
||
|
|
|
||
|
|
// 是否客服黑名单
|
||
|
|
if db.Mysql().Exist(&common.CustomerBlackUser{Uid: a.UID}) {
|
||
|
|
resp.IsBlack = true
|
||
|
|
}
|
||
|
|
|
||
|
|
a.Data = resp
|
||
|
|
}
|
||
|
|
|
||
|
|
// 上传图片
|
||
|
|
func UploadImage(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
|
||
|
|
// 解析请求中的 multipart/form-data
|
||
|
|
err := c.Request.ParseMultipartForm(10 << 20) // 限制上传文件的大小为 10MB
|
||
|
|
if err != nil {
|
||
|
|
log.Error("图片超过10Mb, err:%v", err.Error())
|
||
|
|
a.Code = values.CodeParam
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 打开上传的文件
|
||
|
|
file, header, err := c.Request.FormFile("file")
|
||
|
|
if err != nil {
|
||
|
|
log.Error("打开上传图片失败, err:%v", err.Error())
|
||
|
|
a.Code = values.CodeParam
|
||
|
|
return
|
||
|
|
}
|
||
|
|
defer file.Close()
|
||
|
|
|
||
|
|
// 获取上传文件的 MIME 类型
|
||
|
|
contentType := header.Header.Get("Content-Type")
|
||
|
|
// 根据 MIME 类型获取文件扩展名
|
||
|
|
ext, err := mime.ExtensionsByType(contentType)
|
||
|
|
if err != nil || len(ext) == 0 {
|
||
|
|
log.Error("获取上传图片格式失败, err:%v", err.Error())
|
||
|
|
a.Code = values.CodeParam
|
||
|
|
return
|
||
|
|
}
|
||
|
|
imageName := call.SnowNode().Generate().String() + ext[0]
|
||
|
|
// 读取上传的文件内容
|
||
|
|
data, err := io.ReadAll(file)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("读取图片内容失败, err:%v", err.Error())
|
||
|
|
a.Code = values.CodeRetry
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取当前日期
|
||
|
|
now := time.Now()
|
||
|
|
zeroTime := now.Format("20060102")
|
||
|
|
rounded := now.Hour()
|
||
|
|
dir := fmt.Sprintf("%v/%v/%v", "images", zeroTime, rounded)
|
||
|
|
|
||
|
|
// 创建保存文件的目标文件
|
||
|
|
err = createDirIfNotExist(dir)
|
||
|
|
if err != nil {
|
||
|
|
log.Error("创建图片保存目录, err:%v", err.Error())
|
||
|
|
a.Code = values.CodeParam
|
||
|
|
return
|
||
|
|
}
|
||
|
|
// 将上传的文件复制到目标文件
|
||
|
|
err = os.WriteFile(dir+"/"+imageName, data, 0644) // 写入文件
|
||
|
|
if err != nil {
|
||
|
|
a.Code = values.CodeRetry
|
||
|
|
return
|
||
|
|
}
|
||
|
|
name := strings.Replace(dir+"/"+imageName, "/", ",", -1)
|
||
|
|
a.Data = config.GetConfig().Web.ImageURL + name
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检测文件目录是否存在
|
||
|
|
func createDirIfNotExist(path string) error {
|
||
|
|
// 检查目录是否存在
|
||
|
|
_, err := os.Stat(path)
|
||
|
|
if err == nil {
|
||
|
|
// 目录已存在,直接返回
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
// 目录不存在,创建目录
|
||
|
|
if os.IsNotExist(err) {
|
||
|
|
err = os.MkdirAll(path, 0755)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取图片
|
||
|
|
func DownloadImage(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
|
||
|
|
name := c.Query("path")
|
||
|
|
path := strings.Replace(name, ",", "/", -1)
|
||
|
|
|
||
|
|
// 打开要返回的图片文件
|
||
|
|
file, err := os.Open(path)
|
||
|
|
if err != nil {
|
||
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
defer file.Close()
|
||
|
|
|
||
|
|
// 读取图片文件的内容
|
||
|
|
data, err := io.ReadAll(file)
|
||
|
|
if err != nil {
|
||
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
arr := strings.Split(path, ".")
|
||
|
|
|
||
|
|
// 返回图片
|
||
|
|
c.Data(http.StatusOK, "image/"+arr[len(arr)-1], data)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 消息已读
|
||
|
|
func ReadMessage(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
req := &values.ReadMessageReq{}
|
||
|
|
if !a.SB(req) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
for i := 0; i < len(req.List); i++ {
|
||
|
|
err := db.Mysql().Update(&common.CustomerChatData{ID: req.List[i], Title: a.UID}, map[string]interface{}{"is_read": true})
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 玩家发送消息
|
||
|
|
func SendMessage(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
req := &values.SendMessageReq{}
|
||
|
|
if !a.SB(req) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
req.Title = a.UID
|
||
|
|
req.Uid = a.UID
|
||
|
|
req.Time = time.Now().Unix()
|
||
|
|
err := db.Mysql().Create(&req)
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
a.Code = values.CodeRetry
|
||
|
|
return
|
||
|
|
}
|
||
|
|
err = db.Mysql().UpdateW(&common.CustomerOrder{}, map[string]interface{}{
|
||
|
|
"un_read": gorm.Expr("un_read + 1"),
|
||
|
|
}, fmt.Sprintf("uid = %v AND status < %v", a.UID, common.CustomerOrderComplete))
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
}
|
||
|
|
a.Data = req.ID
|
||
|
|
}
|
||
|
|
|
||
|
|
// 转接人工服务
|
||
|
|
func CreateCustomerOrder(c *gin.Context) {
|
||
|
|
a := app.NewApp(c)
|
||
|
|
defer func() {
|
||
|
|
a.ResponseB()
|
||
|
|
}()
|
||
|
|
|
||
|
|
if db.Mysql().Exist(&common.CustomerBlackUser{Uid: a.UID}) {
|
||
|
|
// 该用户在黑名单
|
||
|
|
log.Info("uid:%v 客服黑名单用户,不创建人工服务", a.UID)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查询玩家上一次客服是否结束
|
||
|
|
var order []*common.CustomerOrder
|
||
|
|
|
||
|
|
count, err := db.Mysql().QueryList(0, 1, fmt.Sprintf("uid = %v AND status != %v", a.UID, common.CustomerOrderComplete), "", &common.CustomerOrder{}, &order)
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
a.Code = values.CodeRetry
|
||
|
|
return
|
||
|
|
} else {
|
||
|
|
if count == 0 {
|
||
|
|
vip := call.GetVIP(a.UID)
|
||
|
|
err = db.Mysql().Create(&common.CustomerOrder{Uid: a.UID, Start: time.Now().Unix(), Vip: vip.Level, Status: common.CustomerOrderCreate})
|
||
|
|
if err != nil {
|
||
|
|
log.Error(err.Error())
|
||
|
|
a.Code = values.CodeRetry
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|