直播商城源码,实现商城客服聊天,发送文字、图片的功能

 

1.实现的思路

由于之前写python的时候接触过websocket,但是当时是使用类似于广播的机制的,没有做过一对一的聊天.但是既然知道了广播,那一对一也就不是什么难事了

首先客户端连接上来时,服务器会实例化每个客户端的连接,并且保存这些连接,这时候只需要前端发送消息时,带有联系人的id 这样就可以根据id 找到联系人发送消息了

 

2.Demo 示例

下面是gin 实现的一个接口,使用 ws协议 连接该接口,然后就可以保存一个ws的连接

 

1
<br>// 把 http 升级为 ws<br>func Login(c *gin.Context)  {<br>tid := c.Query("tid")<br>userID , err := strconv.ParseInt(tid, 10, 64)<br>if err != nil {<br>c.JSON(http.StatusOK, gin.H{"code": 10, "arg-err": db.InvalidArgument})<br>return<br>}<br>Logger.Info(" ------ 请求头 ------", c.Request.Header)<br>Logger.Info("ws 连接请求")<br>userInfo, err := db.FindUser(userID)<br>if err != nil {<br>Logger.Info("ws 连接失败,找不到用户信息", err)<br>c.JSON(http.StatusOK, gin.H{"code": 10, "arg-err": db.InvalidArgument})<br>return<br>}<br>conn, err := Upgrader.Upgrade(c.Writer, c.Request, nil)<br>if err != nil {<br>Logger.Error("http 协议升级为ws 协议失败:", err)<br>return<br>}<br>uniqueID := utils.UUID()<br>wsClient := &Client{ID: utils.UUID(), Socket: conn, Send: make(chan []byte), UserInfo:userInfo, ConnID:uniqueID}<br>go wsClient.Read()<br>Manager.Register <- wsClient<br>Logger.Infof("ws 登陆成功 ip %v 用户id %v", conn.RemoteAddr(), *wsClient.UserInfo.TID)<br>}

聊天功能demo

聊天功能主要是每个连接开了一个go 协程去检查该连接是否有消息,如果有消息 则检查它要发给哪个用户,找到那个用户的连接,发过去即可

 

1
<br>func (c *Client) Read() {<br>defer func() {<br>Manager.Unregister <- c<br>c.Socket.Close()<br>}()<br>for {<br>Logger.Infof("用户 %v 等待消息中....", *c.UserInfo.TID)<br>_, message, err := c.Socket.ReadMessage()<br>if err != nil {<br>Logger.Error("读取消息失败 ", err)<br>Manager.Unregister <- c<br>c.Socket.Close()<br>break<br>}<br>Logger.Info("====== ws 消息 ====== ", string(message))<br>var content Message<br>err = json.Unmarshal(message, &content)<br>if err != nil {<br>Logger.Error("接收消息失败 ", err)<br>continue<br>}<br>if content.Content == "logout" {<br>Manager.Unregister <- c<br>c.Socket.Close()<br>break<br>}<br>if (content.Recipient == 0 || len(content.Content) == 0) && len(content.Image) < 0 {<br>Logger.Error("无效的消息 ")<br>continue<br>}<br>// 保存聊天记录<br>unRead := db.MessageUnRead<br>msgType := content.Type<br>chat := &db.Chat{}<br>fromUser := c.UserInfo.TID<br>chat.FromUser = fromUser<br>chat.ToUser = &content.Recipient<br>chat.Content = &content.Content<br>chat.Image = &content.Image<br>chat.Status = &unRead<br>chat.Type = &msgType<br>db.SaveChat(chat)<br>now := time.Now()<br>nowTimeStamp := db.JSONTime{Time:now}<br>content.MsgID = *chat.TID<br>content.Timestamp = nowTimeStamp<br>content.Sender = *fromUser<br>// 转发给另外一端<br>Logger.Infof("用户 %v 发消息 %v 给另外一个用户 %v ", *fromUser, content.Content, content.Recipient)<br>Manager.ChatTo(content.Recipient, &content)<br>}<br>}<br>func (manager *ClientManager) ChatTo(userID int64, msg *Message) {<br>manager.Clients.Range(func(k, v interface{}) bool {<br>if v != nil {<br>conn := v.(*Client)<br>if *conn.UserInfo.TID == userID {<br>message, err := json.Marshal(msg)<br>if err != nil {<br>Logger.Error("聊天失败")<br>return true<br>}<br>Logger.Info("发送给 ", *conn.UserInfo.TID)<br>err = conn.Socket.WriteMessage(websocket.TextMessage, message)<br>if err != nil {<br>Logger.Error("消息转发失败 ", err)<br>}<br>}<br>}<br>return true<br>})<br>}

 

关于离线消息的处理

当联系人不在线时,我的处理方案是将聊天数据保存下来标记该消息未读,提供一个接口查询用户未读消息,当下次用户登陆时前端发http 请求未读消息即可

 

关于图片发送

这里我的处理方案是,写一个接口提供给前端上传图片上传成功时返回图片路径,前端发来的聊天内容只有图片的url,后续聊天图片显示通过url 请求图片即可

以上就是直播商城源码,实现商城客服聊天,发送文字、图片的功能, 更多内容欢迎关注之后的文章

 

posted @   云豹科技-苏凌霄  阅读(197)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示