diff --git a/controller/offline_message.go b/controller/offline_message.go
index 674cf3c..e4a87da 100644
--- a/controller/offline_message.go
+++ b/controller/offline_message.go
@@ -6,7 +6,6 @@ import (
"github.com/gin-gonic/gin"
"goflylivechat/models"
"goflylivechat/tools"
- "goflylivechat/ws"
"log"
"strconv"
"time"
@@ -420,44 +419,6 @@ func BatchMarkOfflineMessagesAsRead(c *gin.Context) {
})
}
-func CheckKefuOnline(c *gin.Context) {
- kefuId := c.Query("kefu_id")
- if kefuId == "" {
- c.JSON(200, gin.H{
- "code": 400,
- "msg": "客服ID不能为空",
- })
- return
- }
-
- kefuInfo := models.FindUser(kefuId)
- if kefuInfo.ID == 0 {
- c.JSON(200, gin.H{
- "code": 404,
- "msg": "客服不存在",
- })
- return
- }
-
- isOnline := false
- for name := range ws.KefuList {
- if name == kefuId {
- isOnline = true
- break
- }
- }
-
- c.JSON(200, gin.H{
- "code": 200,
- "msg": "ok",
- "result": gin.H{
- "kefu_id": kefuId,
- "nickname": kefuInfo.Nickname,
- "avator": kefuInfo.Avator,
- "is_online": isOnline,
- },
- })
-}
func SendOfflineMessageNotice(kefuName, visitorName, content string) {
smtp := models.FindConfig("NoticeEmailSmtp")
diff --git a/goflylivechat.exe b/goflylivechat.exe
index 9b335fe..ecb8d45 100644
Binary files a/goflylivechat.exe and b/goflylivechat.exe differ
diff --git a/router/api.go b/router/api.go
index ee038e0..d151cb7 100644
--- a/router/api.go
+++ b/router/api.go
@@ -93,8 +93,7 @@ func InitApiRouter(engine *gin.Engine) {
}
//离线留言接口 - 访客端
engine.POST("/offline_message", middleware.Ipblack, controller.SubmitOfflineMessage)
- engine.GET("/kefu/online", controller.CheckKefuOnline)
-
+
//离线留言接口 - 客服端(需要认证)
offlineMessageGroup := engine.Group("/offline_messages")
offlineMessageGroup.Use(middleware.JwtApiMiddleware)
diff --git a/static/templates/chat_page.html b/static/templates/chat_page.html
index 16e64b7..eabd08d 100644
--- a/static/templates/chat_page.html
+++ b/static/templates/chat_page.html
@@ -232,6 +232,14 @@
this.socketClosed=false;
this.focusSendConn=false;
const redata = JSON.parse(e.data);
+ if (redata.type == "kefu_status") {
+ let data = redata.data;
+ this.handleKefuStatus(data);
+ }
+ if (redata.type == "kefu_status_change") {
+ let data = redata.data;
+ this.handleKefuStatus(data);
+ }
if (redata.type == "kfOnline") {
let msg = redata.data
if(this.showKfonline && this.visitor.to_id==msg.id){
@@ -305,6 +313,19 @@
}
window.parent.postMessage(redata,"*");
},
+ handleKefuStatus:function(data) {
+ if(data && data.is_online) {
+ this.showOfflineMessageForm = false;
+ if(data.avator) {
+ this.kefuInfo.avatar = data.avator;
+ }
+ } else {
+ this.showOfflineMessageForm = true;
+ if(data && data.avator) {
+ this.kefuInfo.avatar = data.avator;
+ }
+ }
+ },
chatToUser:function() {
var messageContent=this.messageContent.trim("\r\n");
messageContent=messageContent.replace("\n","");
@@ -667,24 +688,6 @@
$(".chatBox").append("
");
this.scrollBottom();
},
- checkKefuOnline:function() {
- let _this = this;
- $.get("/kefu/online?kefu_id="+KEFU_ID, function(res) {
- if(res.code == 200 && res.result) {
- if(res.result.is_online) {
- _this.showOfflineMessageForm = false;
- _this.getUserInfo();
- } else {
- _this.showOfflineMessageForm = true;
- _this.kefuInfo.avatar = res.result.avator;
- }
- } else {
- _this.showOfflineMessageForm = true;
- }
- }).fail(function() {
- _this.showOfflineMessageForm = true;
- });
- },
submitOfflineMessage:function() {
let _this = this;
this.$refs.offlineMessageForm.validate(function(valid) {
@@ -742,7 +745,15 @@
message: '正在尝试重新连接...',
type: 'info'
});
- this.checkKefuOnline();
+ if(this.socket && this.socket.readyState === WebSocket.OPEN) {
+ let msg = {
+ type: "check_kefu_status",
+ data: KEFU_ID
+ };
+ this.socket.send(JSON.stringify(msg));
+ } else {
+ this.initConn();
+ }
},
},
mounted:function() {
@@ -751,7 +762,7 @@
},
created: function () {
this.init();
- this.checkKefuOnline();
+ this.getUserInfo();
}
})
diff --git a/ws/user.go b/ws/user.go
index 37e1c9a..16cfb80 100644
--- a/ws/user.go
+++ b/ws/user.go
@@ -41,6 +41,7 @@ func NewKefuServer(c *gin.Context) {
messageType, receive, err := conn.ReadMessage()
if err != nil {
log.Println("ws/user.go ", err)
+ RemoveKefuFromList(kefuInfo.Name)
conn.Close()
return
}
@@ -66,6 +67,18 @@ func AddKefuToList(kefu *User) {
}
}
KefuList[kefu.Id] = kefu
+
+ // 广播客服上线状态给所有该客服的访客
+ BroadcastKefuOnlineStatus(kefu.Id, true)
+}
+
+func RemoveKefuFromList(kefuId string) {
+ _, ok := KefuList[kefuId]
+ if ok {
+ delete(KefuList, kefuId)
+ // 广播客服离线状态给所有该客服的访客
+ BroadcastKefuOnlineStatus(kefuId, false)
+ }
}
// 给指定客服发消息
@@ -103,16 +116,26 @@ func SendPingToKefuClient() {
Type: "many pong",
}
str, _ := json.Marshal(msg)
+
+ // 收集需要删除的客服ID
+ var toRemove []string
+
for kefuId, kefu := range KefuList {
if kefu == nil {
+ toRemove = append(toRemove, kefuId)
continue
}
kefu.Mux.Lock()
- defer kefu.Mux.Unlock()
err := kefu.Conn.WriteMessage(websocket.TextMessage, str)
+ kefu.Mux.Unlock()
if err != nil {
log.Println("定时发送ping给客服,失败", err.Error())
- delete(KefuList, kefuId)
+ toRemove = append(toRemove, kefuId)
}
}
+
+ // 从列表中移除并广播离线状态
+ for _, kefuId := range toRemove {
+ RemoveKefuFromList(kefuId)
+ }
}
diff --git a/ws/visitor.go b/ws/visitor.go
index 2cc3d6e..b3c55ff 100644
--- a/ws/visitor.go
+++ b/ws/visitor.go
@@ -79,6 +79,10 @@ func AddVisitorToList(user *User) {
}
}
ClientList[user.Id] = user
+
+ // 发送客服在线状态给访客
+ SendKefuStatusToVisitor(user, user.To_id)
+
lastMessage := models.FindLastMessageByVisitorId(user.Id)
userInfo := make(map[string]string)
userInfo["uid"] = user.Id
@@ -203,3 +207,72 @@ func CleanVisitorExpire() {
}
}()
}
+
+func SendKefuStatusToVisitor(visitor *User, kefuId string) {
+ if visitor == nil || visitor.Conn == nil {
+ return
+ }
+ _, online := KefuList[kefuId]
+ kefuInfo := models.FindUser(kefuId)
+ msg := TypeMessage{
+ Type: "kefu_status",
+ Data: map[string]interface{}{
+ "kefu_id": kefuId,
+ "is_online": online,
+ "nickname": kefuInfo.Nickname,
+ "avator": kefuInfo.Avator,
+ },
+ }
+ str, _ := json.Marshal(msg)
+ visitor.Conn.WriteMessage(websocket.TextMessage, str)
+}
+
+func BroadcastKefuOnlineStatus(kefuId string, isOnline bool) {
+ kefuInfo := models.FindUser(kefuId)
+ msg := TypeMessage{
+ Type: "kefu_status_change",
+ Data: map[string]interface{}{
+ "kefu_id": kefuId,
+ "is_online": isOnline,
+ "nickname": kefuInfo.Nickname,
+ "avator": kefuInfo.Avator,
+ },
+ }
+ str, _ := json.Marshal(msg)
+
+ for _, visitor := range ClientList {
+ if visitor.To_id == kefuId && visitor.Conn != nil {
+ visitor.Conn.WriteMessage(websocket.TextMessage, str)
+ }
+ }
+}
+
+func HandleCheckKefuStatus(conn *websocket.Conn, data interface{}) {
+ var kefuId string
+ switch v := data.(type) {
+ case string:
+ kefuId = v
+ case map[string]interface{}:
+ if id, ok := v["kefu_id"].(string); ok {
+ kefuId = id
+ }
+ }
+
+ if kefuId == "" {
+ return
+ }
+
+ _, online := KefuList[kefuId]
+ kefuInfo := models.FindUser(kefuId)
+ msg := TypeMessage{
+ Type: "kefu_status",
+ Data: map[string]interface{}{
+ "kefu_id": kefuId,
+ "is_online": online,
+ "nickname": kefuInfo.Nickname,
+ "avator": kefuInfo.Avator,
+ },
+ }
+ str, _ := json.Marshal(msg)
+ conn.WriteMessage(websocket.TextMessage, str)
+}
diff --git a/ws/ws.go b/ws/ws.go
index e207e57..80cec2f 100644
--- a/ws/ws.go
+++ b/ws/ws.go
@@ -134,6 +134,8 @@ func WsServerBackend() {
if tools.LimitFreqSingle("inputing:"+from, 1, 2) {
OneKefuMessage(to, message.content)
}
+ case "check_kefu_status":
+ HandleCheckKefuStatus(conn, typeMsg.Data)
}
}