天天看點

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

ASP.NET SignalR + LayIM 2.0 搭建Web “QQ”

前言

  前前一篇留了個小問題,在上一篇中忘了寫了,就是關于LayIM已經封裝好的上傳檔案或者圖檔的問題。對接好接口之後,如果上傳速度慢,界面就會出現假死情況,雖然檔案正在上傳。于是我就簡單做了個圖示替代來增強使用者體驗。

  上傳中。。。

  

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  上傳完成後

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  是不是很簡單啊,接下來進入正題。

業務介紹

  LayIM中的加好友可以說是不太必要的邏輯,而且其實大部分在模仿QQ,當然業務複雜度肯定沒法和QQ比。主線,就是使用者A請求添加使用者B為好友,使用者B收到消息提示之後點選同意或者拒絕或者直接忽略,然後在将消息回報到使用者A。就是這麼一個比較簡單的流程,不過細節還是比較多的。

實戰示範

  第一步,發送好友申請。

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  第二步,接收好友申請(小氣球為消息提示)

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  第三步:消息處理(這裡拒絕會輸入拒絕理由,忽略不做消息提示)

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  第四步:同意(拒絕)之後消息回傳。

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  第五步:流程結束

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

講解

  資料庫上的業務邏輯不多贅述,一般的設計隻要包含請求表和處理結果表就可以了,然後根據使用者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);
            }
        }      

  隻要實作了以上這個方法,不管我們是發送申請資訊,消息處理資訊還是其他資訊,都可以在背景調用。隻要該使用者線上,就能夠實作實時推送,如果不線上,即使推送了,也是收不到的。那就是曆史消息的功能了。這裡不再贅述。

  是以,當請求發送出去的時候,另外一個用戶端就會看到這麼一條消息:

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  對應界面上呢,就是那個右下角的小氣球閃爍,因為是截圖,是以閃爍效果看不出,雖然很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);
                    }

                }
            }
        }      

  是以,當處理完申請消息時候,申請方使用者就會收到如下的消息:

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

  用戶端消息處理:

          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源碼改造右鍵菜單--好友、組管理功能的實作。

ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作
ASP.NET SignalR 與 LayIM2.0 配合輕松實作Web聊天室(五) 之 加好友,加群流程,消息管理和即時消息提示的實作

   想要學習的小夥伴,可以關注我的部落格哦,我的QQ:645857874,Email:[email protected]

    GitHub:https://github.com/fanpan26/LayIM_NetClient/

多學點,總不會吃虧的。