基于.Net Core3.1 与signalR实现一个即时通讯工具(四)——功能实现

基于.Net Core3.1 与signalR实现一个即时通讯工具(四)——功能实现

源码下载地址

  1. 打开上一步创建的控制器:IMController,代码如下
using Microsoft.AspNetCore.SignalR;
using MySql.Data.MySqlClient.Memcached;
using SpoonRapidCore.DataBaseHelper;
using SRFEntity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SRF.IM.Hubs
{
    public class IMHub : Hub
    {
        #region 数据库操作类
        private ISqlSugarHelper<Base_User> userHelper = new SqlSugarHelper<Base_User>();
        private ISqlSugarHelper<Base_HistoryMeeting> meetingHelper = new SqlSugarHelper<Base_HistoryMeeting>();
        private SqlSugarHelper<Base_Msg> msgHelper = new SqlSugarHelper<Base_Msg>();
        #region

        #region 发送至客户端
        /// <summary>
        /// 像所有在线通讯广播
        /// </summary>
        /// <param name="Message"></param>
        /// <param name="Name"></param>
        /// <returns></returns>
        public async Task SendNotice(string Message, string Name = "系统提示")
        {
            await Clients.All.SendAsync("RNotice", Name, Message);
        }
        /// <summary>
        /// 通过连接ID向指定通讯发送消息
        /// </summary>
        /// <param name="ConnectionID"></param>
        /// <param name="SendUser"></param>
        /// <param name="Message"></param>
        /// <returns></returns>
        public async Task SendMessage(string ConnectionId,string SendUser, string Message)
        {
            await Clients.User(ConnectionId).SendAsync("RMessage",SendUser, Message);
        }

        /// <summary>
        /// 通过多个连接ID向指定通讯发送消息
        /// </summary>
        /// <param name="ConnectionIDs"></param>
        /// <param name="SendUser"></param>
        /// <param name="Message"></param>
        /// <returns></returns>
        public async Task SendMessages(List<string> ConnectionIds, string SendUser, string Message)
        {
            await Clients.Users(ConnectionIds).SendAsync("RMessages",SendUser, Message);
        }

        public async Task SendLog(string ConnectionId, string SendUser, string Message)
        {
            await Clients.User(ConnectionId).SendAsync("SendLog", SendUser, Message);
        }
        #endregion

        #region 服务端接受
        /// <summary>
        /// 客户端上线
        /// </summary>
        /// <param name="UserId"></param>
        /// <param name="LoginStatus"></param>
        /// <param name="UserName"></param>
        /// <returns></returns>
        public async Task ConnectedOn(string UserId, string LoginStatus,string UserName)
        {
            string connectionId = Context.ConnectionId;
            try
            {
                var isExist = userHelper.GetEntity(UserId);
                Base_User base_User = new Base_User
                {
                    ConnectId = connectionId,
                    IsOnline = 1,
                    LoginDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    UserId = UserId,
                };
                if (isExist == null)
                {
                    userHelper.SaveForm(base_User);
                }
                else
                {
                    isExist.ConnectId = connectionId;
                    isExist.IsOnline = 1;
                    isExist.LoginDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    isExist.UserId = UserId;

                    userHelper.UpdateEntity(isExist);
                }
                await SendLog(connectionId, UserId, "您已连接到IM,您的连接ID为:" + connectionId + ",您的登录状态为:" + LoginStatus);
            }
            catch (Exception ex)
            {
                await SendLog(connectionId, UserId, "连接失败!失败原因为:"+ex.Message);
            }
           
        }

        /// <summary>
        /// 会话上线
        /// </summary>
        /// <param name="UserId"></param>
        /// <param name="ToUserId"></param>
        /// <returns></returns>
        public async Task MeetingConnectOn(string UserId, string ToUserId)
        {
            try
            {
                string connectionId = Context.ConnectionId;
                /*判断该会话是存在*/
                StringBuilder H_SqlWhere=new StringBuilder();
                H_SqlWhere.AppendFormat(" AND MeetingOwn='{0}' AND UserId='{1}'",UserId,ToUserId);
                var HMeeting = meetingHelper.GetEntityByWhereSql(H_SqlWhere.ToString());
                if (HMeeting == null)
                {
                    HMeeting = new Base_HistoryMeeting
                    {
                        HistoryDate = DateTime.Now,
                        HistoryId = Guid.NewGuid().ToString(),
                        MeetingOwn = UserId,
                        UserId = ToUserId,
                        OwnCID = Context.ConnectionId,
                    };
                    meetingHelper.SaveForm(HMeeting);
                }
                else
                {
                    HMeeting.OwnCID = Context.ConnectionId;
                    HMeeting.HistoryDate = DateTime.Now;
                    meetingHelper.UpdateEntity(HMeeting);
                }
                /*所有会话设置已读*/
                StringBuilder MsgRead_StrSql = new StringBuilder();
                MsgRead_StrSql.AppendFormat("UPDATE dbo.Base_Msg SET MsgStatus=0  WHERE ToUser='{0}' AND FromUser='{1}' AND MsgStatus=1", UserId, ToUserId);
                msgHelper.ExecuteCommand(MsgRead_StrSql.ToString());
                await SendLog(Context.ConnectionId, UserId, "会话建立成功!");
            }
            catch (Exception ex)
            {
                await SendLog(Context.ConnectionId, UserId, "会话建立失败!失败原因为:" + ex.Message);
            }
        }
        /// <summary>
        /// 会话关闭
        /// </summary>
        /// <param name="UserId"></param>
        /// <param name="ToUserId"></param>
        /// <returns></returns>
        public async Task MeetingConnectOff(string UserId, string ToUserId)
        {
            try
            {
                StringBuilder GetConnectionIdStrSql = new StringBuilder();
                GetConnectionIdStrSql.AppendFormat(" AND MeetingOwn='{0}' AND UserId='{1}'", ToUserId, UserId);
                Base_HistoryMeeting ToUserMeeting = meetingHelper.GetEntityByWhereSql(GetConnectionIdStrSql.ToString());

                StringBuilder H_SqlWhere = new StringBuilder();
                H_SqlWhere.AppendFormat(" AND MeetingOwn='{0}' AND UserId='{1}'", UserId, ToUserId);
                var HMeeting = meetingHelper.GetEntityByWhereSql(H_SqlWhere.ToString());
                HMeeting.OwnCID = "";
                meetingHelper.UpdateEntity(HMeeting);
                //meetingHelper.DeleteByKey(HMeeting);
                await SendLog(Context.ConnectionId, UserId, "会话关闭成功");
            }
            catch (Exception ex)
            {
               await SendLog(Context.ConnectionId, UserId, "会话关闭失败!失败原因为:" + ex.Message);
            }
        }
        #endregion

        #region 服务端对连接管理
        public override async Task OnConnectedAsync()
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
            await base.OnConnectedAsync();
        }
        public override async Task OnDisconnectedAsync(Exception exception)
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
            await base.OnDisconnectedAsync(exception);
        }
        #endregion
    }
}
#endregion
  1. 打开Index.cshtml

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>

    <link rel="stylesheet" href="~/lib/layui-v2.5.6/layui/css/layui.css" />
    <script src="~/lib/layer-v3.1.1/layer/layer.js"></script>
    <script src="~/lib/layui-v2.5.6/layui/layui.js"></script>
    <script src="~/js/requst.js"></script>
    <script src="~/js/SRFIM.js"></script>
    <link rel="stylesheet" href="~/css/SRFIM.css" />
    <script src="~/lib/jquery-cookies/jquery.cookie-v1.4.1.js"></script>
</head>
<body>
    <div id="LoginForm" style="display:none">
        <form class="layui-form" style="padding:10px;">
            <div class="layui-form-item">
                <label class="layui-form-label" style="display:block">用户名</label>
                <div class="layui-input-block" style="width:100%;">
                    <input id="LoginName" type="text" name="title" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">密码框</label>
                <div class="layui-input-block">
                    <input id="Password" type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
                </div>
            </div>
        </form>
        <button class="layui-btn layui-btn-normal layui-btn-sm" style="width:90%;margin-left:5%" onclick="GoLogin()">即刻登录</button>
    </div>
    <button class="layui-btn" onclick="isLogin()" style="margin:40px;">Ring</button>

</body>
</html>
<style>
    .layui-input-block {
        margin-left: 0px;
    }

    .layui-form-label {
        width: auto;
    }
</style>
  1. 打开ChatIndex.cshtml

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>chatIndex</title>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/jquery-cookies/jquery.cookie-v1.4.1.js"></script>
    <script src="~/lib/microsoft/signalr/dist/browser/signalr.min.js"></script>
    <script src="~/js/IM.js"></script>
    <link rel="stylesheet" href="~/lib/layui-v2.5.6/layui/css/layui.css" />
    <script src="~/lib/layer-v3.1.1/layer/layer.js"></script>
    <script src="~/lib/layui-v2.5.6/layui/layui.js"></script>
    <script src="~/js/SRFIM.js"></script>
    <link rel="stylesheet" href="~/lib/optiscroll/dist/optiscroll.css" />
    <script src="~/lib/optiscroll/dist/jquery.optiscroll.min.js"></script>
    <link rel="stylesheet" href="~/css/SRFIM.css" />
    <script src="~/js/requst.js"></script>
</head>
<body>
    <div class="top">
        <div class="top_headpicBox">
            <img src="~/images/u=1529359824,2671467657&fm=26&gp=0.jpg" class="top_headpic" />
        </div>
        <div class="demepart_info">
            <c>UI绘制部门员工:日近长安远</c>
        </div>
    </div>

    <div>
        <div class="layui-tab layui-tab-brief" lay-filter="mainBox">
            <ul class="layui-tab-title">
                <li class="layui-this" style="width:75px"><i class="layui-icon layui-icon-reply-fill" style="font-size: 20px;color:#555555"></i></li>
                <li style="width:75px"><i class="layui-icon layui-icon-group " style="font-size: 20px;color:#555555"></i> </li>
                <li style="width:75px"><i class="layui-icon layui-icon-template-1" style="font-size: 20px;color:#555555"></i> </li>
            </ul>
            <div class="layui-tab-content">
                <div class="layui-tab-item layui-show">
                    <div class="historyBox optiscroll" id="historyBox" style="height: 320px;overflow:hidden;">
                        <ul>
                        </ul>
                        <div style="width:315px;margin-top: 40px;">
                            <hr class="layui-bg-gray" style="width: 80%;margin-left: 10%;">
                            <div class="history_bottom">没有更多消息了</div>
                        </div>
                    </div>
                </div>

                <div class="layui-tab-item ">
                    <div class="groupBox optiscroll" id="groupBox" style="height: 320px;overflow:hidden;width: 315px;">
                        <ul>
                            <li id="8277e0910d75015645465616e091ad" class=" ">
                                <div style="width: 315px;">
                                    <div class="groupBox_headpicBox">
                                        <img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3114504376,226392045&fm=26&gp=0.jpg"
                                             class="groupBox_headpic">
                                    </div>
                                    <div class="groupBox_msgBox">
                                        <div class="groupBox_msgName">测试小组001</div>
                                        <div class="groupBox_msgDetail">张三:?[图片]上次说的方案你看了吗</div>
                                    </div>
                                    <div style="width:20px;float: left;">
                                        <span class="layui-badge layui-bg-gray groupBox_msgCount">20</span>
                                        <i rel="8277e0910d750195b448797616e091ad" class="layui-icon layui-icon-close-fill groupBox_closeBtn"></i>
                                    </div>
                                </div>
                            </li>
                        </ul>
                    </div>

                </div>
                <div class="layui-tab-item">内容3</div>
            </div>

        </div>
    </div>
</body>
</html>
<script>
    $(function () {
        connectOn();
        InitPage();
        $('#historyBox').optiscroll();
        $('#groupBox').optiscroll();
    })

    //上线
    function connectOn() {
        var IMUID = $.cookie('IMUID')
        var IMUName = $.cookie('IMUName')
        $(".demepart_info").html(IMUName);
        connection.start().then(function () {
            connection.invoke("ConnectedOn", IMUID, "隐身", IMUName).catch(function (err) {
            });
        }).catch(function () {
            alert("连接失败!请尝试刷新后重试!");
        });
    }

    //接收到新的消息
    connection.on("RNMessage", function (SendUserId, Message, base_User, unReadNums) {
        var ele = $("#" + SendUserId);
       
        if (ele.length == 0) {
            var fillHtml = '';
            fillHtml += '<li id="' + base_User.userId + '">';
            fillHtml += '   <div style="width: 315px;">';
            fillHtml += '       <div class="historyBox_headpicBox">';
            fillHtml += '           <img src="' + base_User.userHeadpic + '" class="historyBox_headpic">';
            fillHtml += '       </div>';
            fillHtml += '       <div class="historyBox_msgBox">';
            fillHtml += '           <div class="historyBox_msgName">' + base_User.userName + '</div>';
            fillHtml += '           <div class="historyBox_msgDetail">' + Message + '</div>';
            fillHtml += '       </div>';
            fillHtml += '       <div style="width: 20px;float: left;">';
            fillHtml += '           <span class="layui-badge historyBox_msgCount" style="display:none;line-height:62px">0</span>';
            fillHtml += '           <i rel="' + base_User.userId + '" class="layui-icon layui-icon-close-fill historyBox_closeBtn"></i>';
            fillHtml += '       </div>';
            fillHtml += '   </div>';
            fillHtml += '</li>';
            var isHasChild = $("#historyBox ul li");
           
            if (isHasChild.length == 0) {
                $("#historyBox ul ").html(fillHtml);
            }
            else {
                $("#historyBox ul li").before(fillHtml);
            }
            
          
        }
        else {
            var firstEleId = $("#historyBox ul li:first").attr('id');
            if (firstEleId != SendUserId) {
                $("#" + SendUserId).remove();
                $("#historyBox ul li").before(ele);
            }
            
        }
        BindHistoryEvent();
        var childrenCountNode = $("#" + SendUserId).children().children().children(".historyBox_msgCount");
        var childrenMsgNode = $("#" + SendUserId).children().children().children(".historyBox_msgDetail");
        var childrenCloseBtnNode = $("#" + SendUserId).children().children().children(".historyBox_closeBtn");
        var childrenImgNode = $("#" + SendUserId).children().children(".historyBox_headpicBox").children(".historyBox_headpic");

        childrenImgNode.addClass("layui-anim layui-anim-fadein layui-anim-loop");
        childrenMsgNode.html(Message);
        var oldCount = childrenCountNode.html();
        var msgCount = parseInt(oldCount) + 1;
        childrenCountNode.html(unReadNums).show();
        childrenCloseBtnNode.css("line-height", "15px");
    });

    //发送消息时 更新自己的主页面会话记录最后一条消息
    connection.on("RSIndexMessage", function (SendUserId, Message) {
        $("#" + SendUserId).children().children().children('.historyBox_msgDetail').html(Message);
      
    });

    connection.on("LoginOut", function () {
        parent.layer.closeAll();
        clearAllCookie();
        setTimeout(function () {
            parent.layer.msg('您的账号已在别处登录,本地强制下线!', { icon: 3, time: 5000 });
        },2000)
    });

    function InitPage() {
        GetMeeting();
    }


</script>


  1. 打开ChatBox.cshtml

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ChatBox</title>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <link rel="stylesheet" href="~/lib/layui-v2.5.6/layui/css/layui.css" />
    <script src="~/lib/layer-v3.1.1/layer/layer.js"></script>
    <script src="~/lib/layui-v2.5.6/layui/layui.js"></script>
    <script src="~/js/SRFIM.js"></script>
    <link rel="stylesheet" href="~/lib/optiscroll/dist/optiscroll.css" />
    <script src="~/lib/optiscroll/dist/jquery.optiscroll.min.js"></script>
    <link rel="stylesheet" href="~/css/SRFIM.css" />
    <script src="~/lib/jquery-cookies/jquery.cookie-v1.4.1.js"></script>
    <script src="~/js/requst.js"></script>
    <script src="~/lib/microsoft/signalr/dist/browser/signalr.min.js"></script>
    <script src="~/js/IM.js"></script>
    <script src="~/js/web.js"></script>
</head>
<body>
    <div style="height: 300px;">
        <div style="height: 300px;" id="historyMsgBox" class="optiscroll">
            <ul style="padding-top: 10px;padding-bottom: 20px;" id="msgContentBox">
                
            </ul>
        </div>
    </div>
    <div style="" id="toolBar">
        <blockquote class="layui-elem-quote" style="margin-bottom: 0px;border-left-color: #1e9fff;padding: 10px;">
            功能区
            <button type="button" class="layui-btn layui-btn-sm layui-btn-primary">
                <i class="layui-icon layui-icon-time" style=""></i>
            </button>
        </blockquote>
    </div>
    <div style="padding: 2px;">
        <textarea id="sendBox" style="display: none;height: 100px;"></textarea>
    </div>
</body>
</html>
<script>
    var connection_main = null;
    var editEle = null;
    var editEleIndex = null;
    var myOptiscrollInstance = null;
    var ToUserId = GetQuery('ToUserId');
    var IMUID = $.cookie('IMUID');
    layui.use('layedit', function () {
        editEle = layui.layedit;
        editEle.set({
            uploadImage: {
                url: '/IM/SendMsgBoxImgUpload?UserId=' + IMUID + "&ToUserId=" + ToUserId, //接口url, 
                type: ''
            }
        });
        editEleIndex = editEle.build('sendBox', {

        });
    });

    var IMUID = $.cookie('IMUID')
    var IMUName = $.cookie('IMUName')
   
    connection.start().then(function () {
        connection.invoke("MeetingConnectOn", IMUID, ToUserId).catch(function (err) {
        });
    }).catch(function () {
        alert("连接失败!请尝试刷新后重试!");
    });

    connection.on("RMessage", function (Message) {
        receiveMsg(Message);
    });
   
    var mockReceiveId = null;
    $(function () {
        $(document).keyup(function (event) {
            if (event.keyCode == 13) {
                alert(1);
            }
        });

        GetMsg();
        var element = document.querySelector('#historyMsgBox')
        myOptiscrollInstance = new Optiscroll(element);
        myOptiscrollInstance.scrollTo(false, 5000);


        
    })
    //获得消息
    function GetMsg() {
        $.getData({
            url: '/IM/GetMyHistoryMsg?UserId=' + IMUID + '&ToUserId=' + ToUserId,
            success: function (data) {
                var fillHtml = '';
                var msgList = data.msgHistoryList;
                for (var i = data.count - 1; i >= 0; i--) {

                    if (i % 7 == 0)
                        fillHtml += '<li class="bubble_center">' + msgList[i].MsgSendDate + '</li>'
                    var isOwn = msgList[i].own;
                    if (isOwn == 0) {
                        fillHtml += '<li class="bubble_right" id="' + msgList[i].MsgId + '"><span>' + msgList[i].MsgContent + '</span></li>';
                    }
                    else
                        fillHtml += '<li class="bubble_left" id="' + msgList[i].MsgId + '"><span>' + msgList[i].MsgContent + '</span></li>';
                }
                $("#msgContentBox").html(fillHtml);
                BindHistoryMsgEvent();
            },
            fail: function () {

            }
        });
    }
    var sendCount = 0;
    //发送消息
    function sendMsg(connection, toUserId) {
        sendCount++;
        var sendContent = editEle.getContent(editEleIndex);
        if (sendContent == "" || sendContent == "<br>")
            return false;

        var postData = {
            Message: sendContent,
            UserId: IMUID,
            ToUserId: toUserId
        };
        $.postData({
            //url: '/IM/SendMessage?UserId=' + IMUID + '&Message=' + sendContent + '&ToUserId=' + toUserId,
            url: '/IM/SendMessage',
            async: false,
            data: postData,
            success: function (data) {
                if (data.isSuccess) {
                    var fillHtml = '';
                    if (sendCount % 7 == 0) {
                        fillHtml += '<li class="bubble_center">' + data.msgSendDate + '</li>'
                    }
                    fillHtml += '<li id="' + data.msgId + '" class="bubble_right layui-anim  layui-anim-upbit">';
                    fillHtml += '<i class="' + data.msgId + '" style="font-size:10px;color:#e4e4e4">正在发送中...&nbsp;</i>';
                    fillHtml += '<span>' + sendContent + '</span>';
                    fillHtml += '</li>';
                    $("#msgContentBox").append(fillHtml);
                    setTimeout(function () {
                        fillHtml += '';
                        $("#" + data.msgId).children('.' + data.msgId).html('<i  style="font-size: 10px; color:#e4e4e4">已送达&nbsp;</i>&nbsp;&nbsp;&nbsp;&nbsp;');
                        $("#" + data.msgId).children('.' + data.msgId).fadeOut(300);
                    }, 600)
                    myOptiscrollInstance.scrollTo(false, 5000);
                    editEle.clearContent(editEleIndex);
                }
                else {
                    var fillHtml = '';
                    if (sendCount % 7 == 0) {
                        fillHtml += '<li class="bubble_center">' + msgList[i].MsgSendDate + '</li>'
                    }
                    fillHtml += '<li id="' + data.msgId + '" class="bubble_right layui-anim  layui-anim-upbit">';
                    fillHtml += '<i class="' + data.msgId + '" style="font-size:10px;color:#e4e4e4">正在发送中...&nbsp;</i>';
                    fillHtml += '<span style="background-color:red">' + sendContent + '</span>';
                    fillHtml += '</li>';

                    $("#msgContentBox").append(fillHtml);
                    myOptiscrollInstance.scrollTo(false, 5000);
                    editEle.clearContent(editEleIndex);

                    setTimeout(function () {
                        $("#" + data.msgId).children('.' + data.msgId).html('<b style="color:red">!</b>&nbsp;&nbsp;&nbsp;&nbsp;');
                    }, 600)
                }
                BindHistoryMsgEvent();
            },
            fail: function () {

            }
        })
    }
    //接收消息
    function receiveMsg(receiveContent) {
        if (receiveContent == "" || receiveContent == "<br>")
            return false;
        var fillHtml = '';
        fillHtml += '<li class="bubble_left  layui-anim  layui-anim-upbit"><span>' + receiveContent + '</span></li>';
        $("#msgContentBox").append(fillHtml);
        myOptiscrollInstance.scrollTo(false, 5000);
    }
    //关闭窗口
    function closeChatBox(ToUserId) {
        var UserId = IMUID;
        connection.invoke("MeetingConnectOff", UserId, ToUserId).catch(function (err) {
        });
    }
</script>
<style>
</style>

  1. 引用的js/css文件如下
1.IM.js
2.requst.js 封装的ajax请求类
3.SRFIM.js
4.web.js web常用方法
5.SRFIM.css 页面样式

资源下载地址:
引用文件资源类

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值