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 ? ‘‘ : ‘‘);
                    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源码改造右键菜单--好友、组管理功能的实现。

  

   想要学习的小伙伴,可以关注我的博客哦,我的QQ:645857874,Email:[email protected]

时间: 2024-07-31 14:23:01

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

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取)

大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言  ASP.NET SignalR WebIM系列第二篇.本篇会带领大家将 LayIM界面中的数据动态化.当然还不涉及即时消息通讯,如果你已经搞定了数据界面,那么本文您可以简单的看一下,或者略过. 进入正题,layim帮我们定义好了数据规则,我们只要写一个接口实现那个json规范就可以了,剩下的事情就交给layim去做,看一下json格式.(对应文件夹:demo/json/getLi

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十四)之漏掉的客服消息

前言 不知不觉已经十四篇了,其实已经没有什么可写了.但是突然发现layim中带的客服功能没有用到.于是乎,抽点时间完成吧.其实之前的工作已经把客服功能完成了一大半,剩下的我们稍微调整即可.今天的演示我们放在后边,直接进入讲解. 客服思路讲解 大家去一些公司网站都会发现,网页侧面或者自动弹出一些客服聊天框,人家很热情的和你交谈.我们也可以用layim来实现.首先,页面添加一个按钮,点击按钮触发客服模式. <a onclick="javascript:global.other.kefu(148

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(七) 之 历史记录查询(时间,关键字,图片,文件),关键字高亮显示。

前言 上一篇讲解了如何自定义右键菜单,都是前端的内容,本篇内容就一个:查询.聊天历史纪录查询,在之前介绍查找好友的那篇博客里已经提到过 Elasticsearch,今天它又要上场了.对于Elasticsearch不感冒的同学呢,本篇可以不用看啦. from baidu: ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列(不断更新中)

项目简介 利用ASP.NET SignalR技术与Layim前端im框架实现的一个简单的web聊天室,包括单聊,群聊,加好友,加群,好友搜索,管理,群组管理,好友权限设置等功能.涉及技术: ElasticSearch 搜索,支持各种条件搜索,效率高,速度快,稳准狠. Redis缓存,统计在线好友,登录token等 RabbitMQ消息队列,发送消息通过队列降低数据库访问压力,或者延迟执行任务. ASP.NET MVC,UI架构. 以及普通的三层架构等.CRUD 当然其中的这些技术也是纯粹为了使用

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(四) 之 用户搜索(Elasticsearch),加好友流程(1)。

前面几篇基本已经实现了大部分即时通讯功能:聊天,群聊,发送文件,图片,消息.不过这些业务都是比较粗犷的.下面我们就把业务细化,之前用的是死数据,那我们就从加好友开始吧.加好友,首先你得知道你要加谁.Layim界面右下角有个+号,点击它之后就会弹出查找好友的界面,不过那个界面需要自定义.由于前端不是我的强项,勉强凑了个页面.不过不要在意这些细节.这些都不重要,今天主要介绍一下ElasticSearch搜索解决方案.它是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十一) 代码重构使用反射工厂解耦

前言 自从此博客发表以及代码开源以来,得到了许多人的关注.也没许多吧,反正在我意料之外的.包括几位大牛帮我做订阅号推广,真的很感谢他们.另外,还有几个高手给我提了一些架构上的问题.其实本身这个项目是没有做什么架构设计的.只是简单分了分层.不过我在经过仔细思考之后决定对项目架构做些调整,当然在我的技术范围之内,我相信还会有第二次,第三次甚至更多重构,我希望把他变得更加完美. 重构思路 对于重构思路,我首先想到的是,让程序能够支持多种数据库,比如我现在用的是SQLServer,而好多朋友用MySQL

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言

前端时间听一个技术朋友说 LayIM 2.0 发布了,听到这个消息抓紧去官网看了一下.(http://layim.layui.com/)哎呀呀,还要购买授权[大家支持一下哦],果断买了企业版,喜欢钻研的我没有源码怎么行,说来也惭愧,发布好久了我才知道.之前写过一系列的博客,当时是ASP.NET SignalR 结合 LayIM 1.0 的一个小程序.看了一下最新版本的LayIM,太赞了.我电脑里的VS已经蠢蠢欲动了.话不多说,先预览一下效果. 主聊天界面: 好友列表界面:        以及自定

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列。开源啦!!!

自此系列博客开写以来,好多同学关心开源问题,之前由于网络问题,发布到Github上老是失败,今天终于在精简了好多无用的文件之后发布上去了. 注意:layim源代码并不开源,由于版权问题,请大家去官网了解详情,本人并非layui作者,原作者贤心.开源内容为 后台部分. 详情移步:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列(不断更新中) GitHub:https://github.com/fanpan26/LayIM_NetClient/ QQ交流群:1

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(三) 之 实现单聊,群聊,发送图片,文件。

上篇讲解了如何搭建聊天服务器,以及客户端js怎么和layui的语法配合.服务器已经连接上了,那么聊天还会远吗? 进入正题,正如上一篇提到的我们用 Client.Group(groupId)的方法向客户端推送消息.本篇就先不把业务搞复杂了,就默认现在两个用户都各自打开了对方的聊天窗口,那么聊天过程是这样的. 同理,B给A发消息也是这个流程,因为无论如何,A(ID)和B(ID)都会按照规则生成同一个组名.其中由于LayIM已经帮我们在客户端做好了发送消息并且将消息展示在面板上,所以我们要做的就是当接