zoukankan      html  css  js  c++  java
  • NET SignalR 与 LayIM2.0

    ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(五) 之 加好友,加群流程,消息管理和即时消息提示的实现

     

    前言

      前前一篇留了个小问题,在上一篇中忘了写了,就是关于LayIM已经封装好的上传文件或者图片的问题。对接好接口之后,如果上传速度慢,界面就会出现假死情况,虽然文件正在上传。于是我就简单做了个图标替代来增强用户体验。

      上传中。。。

      

      上传完成后

      

      是不是很简单啊,接下来进入正题。

    业务介绍

      LayIM中的加好友可以说是不太必要的逻辑,而且其实大部分在模仿QQ,当然业务复杂度肯定没法和QQ比。主线,就是用户A请求添加用户B为好友,用户B收到消息提示之后点击同意或者拒绝或者直接忽略,然后在将消息反馈到用户A。就是这么一个比较简单的流程,不过细节还是比较多的。

    实战演示

      第一步,发送好友申请。

      

      第二步,接收好友申请(小气球为消息提示)

      

      第三步:消息处理(这里拒绝会输入拒绝理由,忽略不做消息提示)

      

      第四步:同意(拒绝)之后消息回传。

      

      第五步:流程结束

      

    讲解

      数据库上的业务逻辑不多赘述,一般的设计只要包含请求表和处理结果表就可以了,然后根据用户id去查询他自己未处理的消息。可能看上面的图看不出哪里即时来,其实我在截图过程中,全程两个浏览器并没有刷新页面,完全是依靠后台的Hub消息推送来实现。在这之前呢,我们要做好准备工作,就是使用自定义用户Id,也就是我们数据库中的userId,而不是Hub中给我们的Guid。我们重写 接口 IUserIdProvider的GetUserId的方法就可以了。

    复制代码
    namespace Microsoft.AspNet.SignalR
    {
        public interface IUserIdProvider
        {
            string GetUserId(IRequest request);
        }
    }
    复制代码

      添加自定义类继承自接口 IUserIdProvider

    复制代码
     public class LayIMUserFactory : IUserIdProvider
        {
            /// <summary>
            /// 自定义获取用户ID方法
            /// </summary>
            /// <param name="request"></param>
            /// <returns></returns>
            public string GetUserId(IRequest request)
            {
                //直接读取Cookie中的userid,然后将userid返回,否则返回空,未登录
                if (request.GetHttpContext().Request.Cookies[LayIMConst.LayIM_SignalR_UserId] != null)
                {
                    return request.GetHttpContext().Request.Cookies[LayIMConst.LayIM_SignalR_UserId].Value;
                }
                return "";
            }
        }
    复制代码

      然后在startup文件中,我们注册一下这个类

    复制代码
      public void Configuration(IAppBuilder app)
            {
                ///注册自定义用户ID方法
                var userIdProvider = new LayIMUserFactory();
                GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => userIdProvider);
                //ConfigureAuth(app);
                //其他代码
            }
    复制代码

      同理呢,在ChatServer.LayIMHub 中,我们也是读取cookie中的用户Id

    复制代码
     public string CurrentUserId
            {
                get
                {
                    
                    var cookie = Context.Request.GetHttpContext().Request.Cookies[LayIMConst.LayIM_SignalR_UserId];
                    if (cookie != null) { return cookie.Value; }
                    return "";
                }
            }
    复制代码

      然后针对某一个用户发送消息的时候调用

     Clients.User(CurrentUserId).receiveMessage("你好,我给你发送了一个消息,用Client.User发给你的");

      这样做有什么好处呢,因为如果用户连接Hub服务器后,刷新页面的话,用户的ConnectionId是会变的,但是如果用我们自定义的userId来发送消息,只要是同一个用户,都能够使用UserId来进行发送消息的操作,省去了对ConnectionId的处理。所以这个场景很适合用在添加好友过程中的消息提醒上。比如,我们申请已经提交,那么后台就需要给被申请人发送一个提示消息:

    复制代码
       public static void SendMessage(object message, string userId, ChatToClientType type, bool moreUser = false)
            {
                //构造消息体
                ToClientMessageResult result = new ToClientMessageResult
                {
                    msg = message,
                    msgtype = type,
                    other = null
                };
                //获取当前的Hub对象
                IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<LayIMHub>();
                // 给多个用户发送消息
                if (moreUser)
                {
                    hub.Clients.Users(userId.Split(',').ToList()).receiveMessage(result);
                }
                else
                {
                    //给单个用户发送消息
                    hub.Clients.User(userId).receiveMessage(result);
                }
            }
    复制代码

      只要实现了以上这个方法,不管我们是发送申请信息,消息处理信息还是其他信息,都可以在后台调用。只要该用户在线,就能够实现实时推送,如果不在线,即使推送了,也是收不到的。那就是历史消息的功能了。这里不再赘述。

      所以,当请求发送出去的时候,另外一个客户端就会看到这么一条消息:

      

      对应界面上呢,就是那个右下角的小气球闪烁,因为是截图,所以闪烁效果看不出,虽然很low。。实现方法 是用setInterval 然后控制文字实现的。

      

    复制代码
                    var i = 0;
                    var blings = function () {
                //html交替变换,一会是图标一会是空,就会有图标闪动的效果,不过如果有一个漂亮的gif就更好了。 $('.layim-tool-apply').attr('title', msg).html(i % 2 ? '' : '&#xe606;'); i++; } other.msgTipInterval = setInterval(blings, 500);
    复制代码

      至于用户打开消息界面,因为是另外一个界面,所以直接读取该用户需要处理的消息即可,当用户同意或者拒绝该请求时,后台同样调用:

    复制代码
     public static void SendMessage(ApplyHandledMessgae message)
            {
                short agreeFlag = 1;
                short refuseFlag = 2;
                //只有有消息,并且同意
                if (message.id > 0)
                {
                    var userid = message.applyuid.ToString();
                    if (message.result == refuseFlag)
                    {
                        //如果是被拒绝,只需要发送一条提示消息即可
                      
                        var msg = new ApplySendedMessage
                        {
                            msg = "您的" + (message.applytype == 0 ? "好友" : "加群") + "请求已经被处理,请点击查看详情"
                        };
                        SendMessage(msg, userid, ChatToClientType.ApplyHandledToClient);
    
                    }
                    else if (message.result == agreeFlag)
                    {
                        //如果同意了,判断如果是加群,需要给群发送消息:某某某已经加入群,如果是加好友,发送一条消息,我们已经成为好友了,开始聊天吧。
                        var msg = "您的" + (message.applytype == 0 ? "好友" : "加群") + "请求已经被处理,请点击查看详情";
                        if (message.applytype == ApplyType.Friend.GetHashCode())
                        {
                            //这里的friend是为了配合 LayIM的 addList接口
                            SendMessage(new { friend = message.friend, msg =msg  }, userid, ChatToClientType.ApplyHandledToClient);
                        }
                        else {
                            //发送群信息 group也是为了配合Layim的addList接口
                            SendMessage(new { group = message.group, msg = msg }, userid, ChatToClientType.ApplyHandledToClient);
                        }
    
                    }
                }
            }
    复制代码

      所以,当处理完申请消息时候,申请方用户就会收到如下的消息:

      客户端消息处理:

    复制代码
                console.log("收到申请被处理的消息");
                        //开始闪烁右下角消息图标
                        global.other.startTips(result.msg.msg);
                        if (result.msg.friend) {
                            result.msg.friend.remark = result.msg.friend.sign;
                            //调用layim接口,将好友直接添加到相应的好友组里面
                            global.layim.addList(result.msg.friend);
                        }
                        if (result.msg.group) {
                            //调用layim接口,将群组直接添加到相应的好友组里面
                            global.layim.addList(result.msg.group);
                        }
    复制代码

      到这里,基本上加好友流程就完成了,加群同理,不过加群不同的是,群主和管理员都可以审批,所以会出现给多个用户发送即时消息的情况。处理的时候也得注意重复操作的问题。

      所以,本篇的核心内容就是Hub在后台的调用,以及自定义UserId的使用方法。不过好像我们还少些东西,比如说,提示群里的其他成员:xxx已经加入群。或者自动给申请成功的好友发送一条:“我们已经是好友了,开始聊天吧。”的消息。

    总结

      万变不离其宗,其实只要掌握了,消息推送机制,能够实现客户端与服务器端的联通。消息推送做任何业务都可以游刃有余。今天的加好友流程就到这里了。你会了吗?

          下篇预告【中级】ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(六) 之 Layim源码改造右键菜单--好友、组管理功能的实现。

      

  • 相关阅读:
    2、容器初探
    3、二叉树:先序,中序,后序循环遍历详解
    Hebbian Learning Rule
    论文笔记 Weakly-Supervised Spatial Context Networks
    在Caffe添加Python layer详细步骤
    论文笔记 Learning to Compare Image Patches via Convolutional Neural Networks
    Deconvolution 反卷积理解
    论文笔记 Feature Pyramid Networks for Object Detection
    Caffe2 初识
    论文笔记 Densely Connected Convolutional Networks
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5767826.html
Copyright © 2011-2022 走看看