web版聊天功能简单实现

一、问题

核心点:如何找到要发送的人?

要完成一个功能我觉得首先要分析该功能的逻辑及技术难点,而不是盲目的直接就撸代码,这样非常浪费时间。个人觉得web版聊天功能没什么实际应用场景,以前看过中国移动好像有过这种东西,所以就简单实现了下

解决:使用缓存存储当前聊天状态

    public class SignalRMessageGroups
    {
        public string ConnectionId { get; set; }
        public long UserId { get; set; }
        public string GroupName { get; set; }
        public static List<SignalRMessageGroups> UserGroups = new List<SignalRMessageGroups>();
    }

  将当前聊天信息存储在内存中,当然你也可以持久化到其它地方,思路是一样的

二、具体实现代码

 使用SignalR进行通讯,具体逻辑不描述(注释都有),因为是在自己的项目实现的,所以只显示部分代码,非常简单的东西,可能js和css写起来麻烦些

Hub代码:

[Authorize]
    public class ChatHub: Hub
    {
        private readonly IOaChatService _chatService;

        public ChatHub(IOaChatService chatService)
        {
            this._chatService = chatService;
        }

        public override async Task OnConnectedAsync()
        {
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception ex)
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, "ChatHubGroup");
            var curUser = SignalRMessageGroups.UserGroups.FirstOrDefault(m => m.ConnectionId == Context.ConnectionId && m.GroupName == "ChatHubGroup");
            if (curUser != null)
            {
                SignalRMessageGroups.UserGroups.Remove(curUser);
            }
            await base.OnDisconnectedAsync(ex);
        }

        /// <summary>
        /// 信息发送
        /// </summary>
        /// <param name="receiver">接收人</param>
        /// <param name="sender">发送人</param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessage(long receiver,long sender, string message)
        {
            //判断接收的人是否在线
            var receiveUser = SignalRMessageGroups.UserGroups.FirstOrDefault(m => m.UserId == receiver && m.GroupName == "ChatHubGroup");
            if (receiveUser != null)
            {
                await Clients.Client(receiveUser.ConnectionId).SendAsync("ReceiveChater", new
                {
                    sender,
                    message,
                    time = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")
                });
                await _chatService.InsertAsync(new Model.OaChat
                {
                    Receiver = receiver,
                    Sender = sender,
                    Message = message
                });
            }
            else
            {
                //发送邮件/短信提醒
            }
        }

        public async Task InitMessage(long userid)
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, "ChatHubGroup");
            var curUser = SignalRMessageGroups.UserGroups.FirstOrDefault(m => m.UserId == userid && m.GroupName == "ChatHubGroup");
            if (curUser != null)
            {
                SignalRMessageGroups.UserGroups.Remove(curUser);
            }
            SignalRMessageGroups.UserGroups.Add(new SignalRMessageGroups
            {
                ConnectionId = Context.ConnectionId,
                GroupName = "ChatHubGroup",
                UserId = userid
            });
            //刷新在线用户列表

            await Clients.All.SendAsync("RefreshOnliner", userid);
        }
    }

  接口(获取在线人员)

[Authorize]
    [Route("api/Chat/[action]")]
    [Produces("application/json")]
    [ApiController]
    public class ChatController : ControllerBase
    {
        private ISystemService _systemService;
        private readonly IOaChatService _chatService;
        private IHubContext<ChatHub> _hubContext;

        public ChatController(IServiceProvider serviceProvider, ISystemService systemService,IOaChatService chatService)
        {
            _hubContext = serviceProvider.GetService<IHubContext<ChatHub>>();
            this._systemService = systemService;
            this._chatService = chatService;
        }

        /// <summary>
        /// 获取全部聊天用户
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<ChatUserViewModel>> GetChatUserAsync([FromBody]List<long> chattinguserids)
        {
            //获取用户
            var allUsers = await _systemService.GetAllUserAsync();
            List<ChatUserViewModel> chatUsers = allUsers.Select(m => new ChatUserViewModel
            {
                UserId = m.UserId,
                UserName = m.UserName,
                HeadImg = m.HeadImg,
                CreateTime = m.CreateTime,
                IsChatting = 0,
                IsOnline = 0
            }).ToList();
            var userids = SignalRMessageGroups.UserGroups.Where(m => m.GroupName == "ChatHubGroup").Select(m => m.UserId);

            foreach (var item in chatUsers)
            {
                if (userids.Contains(item.UserId))
                {
                    item.IsOnline = 1;
                }
                if (chattinguserids.HasItems() && chattinguserids.Contains(item.UserId))
                {
                    item.IsChatting = 1;
                }
            }
            return chatUsers.OrderByDescending(m => m.IsChatting).ThenByDescending(m => m.IsOnline).ThenBy(m => m.CreateTime).ToList(); ;
        }


        [HttpGet]
        public async Task<List<ChatUserListDto>> GetChatListAsync([FromQuery]ChatUserListSearchDto model)
        {
            return await _chatService.GetChatListAsync(model);
        }
    }

  页面代码(css、js代码较多)

@{
    ViewData["Title"] = "聊天";
    Layout = "~/Views/Shared/_LayoutJQ.cshtml";
    UserIdentity user = ViewBag.User;
}
@inject MsSystem.Web.Infrastructure.TokenClient tokenClient
@inject Microsoft.Extensions.Configuration.IConfiguration configuration
@section css{ 
    <style>
        body {
            background:#fff !important;
        }
        .ibox-content{
            border:none !important;
        }
        .chat-main {
            display: inline-block;
            background: #eee;
            border-radius: 3px;
        }
        .chat-main-left {
            width: 200px;
            float: left;
            overflow-y: auto;
            display: none;
            border: 1px solid #ddd;
            box-shadow: 0px 0px 10px #ddd;
            border-right: none;
        }
        .chat-main-right {
            width: 600px;
            float: left;
            height: 550px;
            border: 1px solid #ddd;
            box-shadow: 0px 0px 10px #ddd;
            border-radius: 3px;
        }

        .chat-users{
            margin-left:0px;
            height:550px;
        }
        .chat-user {
            cursor: pointer;
            margin: 10px;
            border-radius: 3px;
        }
        .chat-user.active {
            background: #fff;
            border-radius: 4px;
        }
        .currentUser {
            background: #eee;
            font-size: 12px;
            text-align: left;
            line-height: 60px;
            height: 60px;
            color: #333;
            font-weight: bold;
            opacity: .8;
        }
        .currentUser img{
            width:45px;
            height:45px;
            margin-left:10px;
        }
        .message-count {
            background: red;
            color: #fff;
            width: 15px;
            height: 15px;
            text-align: center;
            border-radius: 50%;
            display: none;
            margin: 2px;
            line-height: 15px;
        }
        .chatim {
            position: absolute;
            right: 0px;
            background: #fff;
            width: 260px;
            border-radius: 3px;
            bottom: 0px;
        }
            .chatim.active {
                box-shadow: 0px 0px 10px #eee;
                border: 1px solid #eee;
            }
        .chatim-title {
            height: 55px;
            line-height: 55px;
            background: #eee;
            padding-left: 10px;
        }
        .chatim-body {
            height: 450px;
            overflow-y: auto;
        }
        .chatim-userbox {
            margin: 10px;
        }
        .chatim-userbox-category{
            cursor:pointer;
        }
        .chatim-userbox-online a{
            color:#333;
        }
        .chatim-userbox-notonline a{
            color:#ddd;
        }
        .chatim ul {
            list-style: none;
            margin: 0px;
            padding: 0px;
        }
        .chatim ul li{
            cursor:pointer;
            margin:10px;
        }
        .chat-user:not(.active):hover {
            background: #fff;
        }
        .chat-user a{
            margin-left:10px;
        }
        .chat-user-name {
            text-align: left;
        }
            .chat-user-name .chat-close {
                width: 16px;
                height: 16px;
                line-height: 16px;
                border-radius: 50%;
                background: #ddd;
                color: #fff;
                font-size: 12px;
                margin-left: 30px;
                position: relative;
                text-align: center;
                float: right;
                display:none;
            }
            .chat-user-name:hover .chat-close {
                display: inline-block;
                background: #FF0000;
            }
        .chatim-user img {
            width: 35px;
            height: 35px;
        }
        .message-input{
            border-right:none;
            border-left:none;
        }
        #sendMessage {
            position: relative;
            top: -35px;
            float: right;
            border-radius: 0px;
            width: 70px;
        }
        .chatim-title-username{
            font-size:16px;
            font-weight:bold;
            margin:0px 10px;
        }
        .chatim-title img{
            width:40px;
            height:40px;
            margin-top:-3px;
        }
        .chatim-user span{
            margin:0px 10px;
        }
        .chatim-userbox-category span {
            width: 12px;
            display: inline-block;
            font-size: 14px;
        }
        .chatim-footer{
            text-align:center;
            padding-bottom:10px;
        }
            .chatim-footer a {
                font-size: 18px;
                color: #fff;
                cursor: pointer;
                width: 38px;
                height: 38px;
                display: inline-block;
                line-height: 38px;
                border-radius: 50%;
                background: #0e9aef;
                box-shadow: 0px 0px 5px #0e9aef;
                text-align: center;
            }
        .more-msg {
            font-size: 12px;
            color: #4ea9e9;
        }
        .more-msg:hover{
            text-decoration:underline;
            color: #4ea9e9;
        }
    </style>
}
@section scripts{
    <script src="/lib/signalr/dist/browser/signalr.min.js"></script>
    <script>
        $(function () {
            var chattinguserids = [];
            var currentUserid = "@user.UserId";
            const connection = new signalR.HubConnectionBuilder()
                .withUrl("http://localhost:5000/hub/oa/chatHub", {
                    transport: signalR.HttpTransportType.LongPolling,
                    accessTokenFactory: () => {
                        return "Authorization", getToken();
                    }
                }).build();
            connection.start().then(function () {
                connection.invoke('InitMessage', currentUserid);
                }).catch(function (err) {
                return console.error(err.toString());
                });
            //获取聊天信息
            connection.on("ReceiveChater", function (data) {
                //判断是否已打开
                var _target = $('.users-list .chat-user[data-userid=' + data.sender + ']');
                var userlength = $('.users-list .chat-user').length;
                if (_target[0] == undefined) {
                    var issactive = userlength == 0 ? true : false;
                    var username = $('.chatim-body a[data-userid=' + data.sender + ']').text();
                    var img = $('.chatim-body a[data-userid=' + data.sender + ']').parent().prev().attr('src');
                    addLeftUser(data.sender, username, img, issactive);
                    resetDiscussionTitle(data.sender, username, img);
                }
                var chatuser = $('.users-list .chat-user[data-userid=' + data.sender + ']');
                var msgcount = chatuser.find('.message-count').text();
                chatuser.find('.message-count').show();
                if (msgcount == '') {
                    chatuser.find('.message-count').text(1);
                } else {
                    chatuser.find('.message-count').text(parseInt(msgcount) + 1);
                }
                var headimg = chatuser.find('img').attr('src');
                var username = chatuser.find('.chat-user-name a').text();
                var html = '';
                html += '<div class="chat-message chat-left">';
                html += '<img class="message-avatar" src="' + headimg +'" alt="">';
                html += '<div class="message">';
                html += '<div><a class="message-author">' + username +'</a>';
                html += '<span class="message-date">' + data.time+'</span></div>';
                html += '<span class="message-content">';
                html += data.message;
                html += '</span>';
                html += '</div>';
                html += '</div>';
                addOrShowDiscussion(data.sender, false);
                var relBox = $('.chat-discussion[data-touser=' + data.sender + ']');
                relBox.append(html);
                srcollBottom(relBox);
            });
            //获取在线人列表
            connection.on("RefreshOnliner", data => {
                axios.post('/OA/Chat/GetChatUserAsync', chattinguserids).then(function (response) {
                    var data = response.data;
                    $('.chatim-userbox ul').empty();
                    $.each(data, function (index, item) {
                        var html = '<li>';
                        html += '<div class="chatim-user">';
                        html += '<img src="' + item.HeadImg+'" />';
                        html += '<span><a data-userid="' + item.UserId + '">' + item.UserName + '</a></span>';
                        html += '</div>';
                        html += '</li>';
                        if (item.IsOnline == 1) {
                            $('.chatim-userbox-online ul').append(html);
                        } else {
                            $('.chatim-userbox-notonline ul').append(html);
                        }
                    });
                });
            });
            function getToken() {
                return '@tokenClient.GetToken().Result';
            }
            document.getElementById('sendMessage').addEventListener('click', function (e) {
                e.preventDefault();
                sendMessage();
            });
            $('textarea[name=message]').on('keydown', function (e) {
                if (e.keyCode != 13) {
                    return;
                } else {
                    event.preventDefault();
                    e.returnValue = false;
                    sendMessage();
                }
            });
            $('.users-list').on('click', '.chat-user', function () {
                $('.users-list .chat-user').removeClass('active');
                $(this).addClass('active');
                var currentDom = $(this).find('.chat-user-name a');
                var userid = currentDom.attr('data-userid');
                var imgsrc = $(this).find('img').attr('src');
                resetDiscussionTitle(userid, currentDom.text(), imgsrc);
                addOrShowDiscussion(userid, true);
                resetUserMessageCount(userid);
                addOnlines(userid);
                $('.chat-message-form').show();
            });
            function sendMessage() {
                var userid = $('#ToUserId').val();
                var message = $('textarea[name=message]').val();
                if (message == '' || message.trim() == '') {
                    return;
                }
                connection.invoke('SendMessage', userid, currentUserid, message);
                $('textarea[name=message]').val('');
                var time = $.getCurrentTime();
                var html = '';
                html += '<div class="chat-message chat-right">';
                html += '<img class="message-avatar" src="@user.HeadImg" alt="">';
                html += '<div class="message">';
                html += '<div><a class="message-author">@user.UserName</a>';
                html += '<span class="message-date">' + time + '</span></div>';
                html += '<span class="message-content">';
                html += message;
                html += '</span>';
                html += '</div>';
                html += '</div>';
                var chatdis = $('.chat-discussion[data-touser=' + userid + ']');
                chatdis.append(html);
                resetUserMessageCount(userid);
                srcollBottom(chatdis);
            }
            function srcollBottom(container) {
                var scrollToContainer = container.find('.chat-message :last');
                container.animate({
                    scrollTop: scrollToContainer.offset().top - container.offset().top + container.scrollTop()
                }, 800);
            }
            function resetUserMessageCount(userid) {
                var chatuser = $('.users-list .chat-user[data-userid=' + userid + ']');
                chatuser.find('.message-count').text('').hide();
            }
            function addOnlines(userid) {
                var flag = false;
                for (var i = 0; i < chattinguserids.length; i++) {
                    if (chattinguserids[i] == userid) {
                        flag = true;
                    }
                }
                if (!flag) {
                    chattinguserids.push(userid);
                }
            }
            function showChatBox(userid) {
                var length = $('.users-list .chat-user').length;
                if (length <= 1) {
                    $('.chat-main-left').show();
                }
                addOrShowDiscussion(userid, true);
            }
            function addOrShowDiscussion(userid, toTop) {
                var disc = $('.chat-discussion[data-touser=' + userid + ']');
                if (disc.length == 1) {
                    $('.chat-discussion').hide();
                    disc.show();
                } else {
                    var html = '';
                    if ($('.chat-discussion').length == 1 || toTop == true) {
                        $('.chat-discussion').hide();
                        html = '<div class="chat-discussion" data-pageindex="0" data-touser="' + userid + '"><a class="more-msg"><i class="fa fa-clock-o"></i>查看更多消息</a></div>';
                    } else {
                        html = '<div class="chat-discussion" style="display:none" data-pageindex="0" data-touser="' + userid + '"><a class="more-msg"><i class="fa fa-clock-o"></i>查看更多消息</a></div>';
                    }
                    $('.chat-discussion:last').after(html)
                }
                $('.chat-message-form').show();
            }
            function resetDiscussionTitle(userid, username,imgsrc) {
                $('#ToUserId').val(userid);
                $('.currentUser span').text(username);
                $('.currentUser img').attr('src', imgsrc);
            }
            function addLeftUser(userid, username, img,isactive) {
                var html = '';
                if (isactive) {
                    $('.chat-user').removeClass('active');
                    html += '<div class="chat-user active" data-userid="' + userid + '">';
                } else {
                    html += '<div class="chat-user" data-userid="' + userid + '">';
                }
                html += '<span class="pull-right message-count"></span>';
                html += '<img class="chat-avatar" src="' + img + '" alt="">';
                html += '<div class="chat-user-name"><a data-userid="' + userid + '">' + username + '</a><span class="chat-close"><i class="fa fa-close"></i></span>';
                html += '</div>';
                html += '</div>';
                $('.users-list').append(html);
                $('.chat-main-left').show();
            }
            $('.chatim-userbox-category').on('click', function () {
                var type = $(this).attr('data-type');
                if (type == 1) {
                    $(this).attr('data-type', 0);
                    $(this).find('span i').attr('class', 'fa fa-angle-right');
                    $(this).next().hide();
                } else {
                    $(this).attr('data-type', 1);
                    $(this).find('span i').attr('class', 'fa fa-angle-down');
                    $(this).next().show();
                }
            });
            $('.chatim-userbox-online ul').on('dblclick', 'li', function () {
                var userid = $(this).find('a').attr('data-userid');
                var username = $(this).find('a').text();
                var _target = $('.users-list .chat-user[data-userid=' + userid + ']');
                if (_target[0] == undefined) {
                    var img = $(this).find('img').attr('src');
                    addLeftUser(userid, username, img, true);
                    showChatBox(userid);
                } else {
                    $('.users-list .chat-user').removeClass('active');
                    _target.addClass('active');
                    addOrShowDiscussion(userid, true);
                }
                var imgsrc = $(this).find('img').attr('src');
                resetDiscussionTitle(userid, username, imgsrc);
            });
            $('.users-list').on('click', '.chat-close', function (e) {
                e.stopPropagation();
                var currentUser = $(this).parent().parent();
                //当前会话只有一个情况
                var uleg = $('.users-list .chat-user').length;
                if (uleg == 1) {
                    currentUser.remove();
                    $('.chat-discussion').hide();
                    $('.chat-discussion:first').show();
                    resetDiscussionTitle('', '','/uploadfile/342bd59b-edf4-48cf-aa27-d13e5a0b70df.jpeg');
                    $('.chat-main-left,.chat-message-form').hide();
                } else {
                    var prevUser = currentUser.prev();
                    if (prevUser.length == 1) {
                        var userid = prevUser.find('a').attr('data-userid');
                        var username = prevUser.find('a').text();
                        if (currentUser.hasClass('active')) {
                            prevUser.addClass('active');
                        }
                        addOrShowDiscussion(userid);
                        var imgsrc = prevUser.find('img').attr('src');
                        resetDiscussionTitle(userid, username, imgsrc)
                    } else {
                        var nextUser = currentUser.next();
                        if (nextUser.length == 1) {
                            var nextUserId = nextUser.find('a').attr('data-userid');
                            var nextUsername = nextUser.find('a').text();
                            if (currentUser.hasClass('active')) {
                                nextUser.addClass('active');
                            }
                            addOrShowDiscussion(nextUserId);
                            var imgsrc = nextUser.find('img').attr('src');
                            resetDiscussionTitle(nextUserId, nextUsername, imgsrc)
                        }
                    }
                    currentUser.remove();
                }
            });

            $('.chatim-footer').on('click', 'a', function () {
                var type = $(this).attr('data-type');
                if (type == 1) {
                    $(this).attr('data-type', 0);
                    $('.chatim-title,.chatim-body').fadeOut();
                    $(this).find('i').attr('class', 'fa fa-comments');
                    $('.chatim').removeClass('active');
                } else {
                    $(this).attr('data-type', 1);
                    $('.chatim-title,.chatim-body').fadeIn();
                    $(this).find('i').attr('class', 'fa fa-close');
                    $('.chatim').addClass('active');
                }
            });
            $('.chat-main-right').on('click', 'a.more-msg', function () {
                var _this = $(this);
                var pageindex = _this.parent().attr('data-pageindex');
                var receiver = _this.parent().attr('data-touser');
                var url = '/OA/Chat/GetChatListAsync?PageIndex=' + pageindex + '&Receiver=' + receiver + '';
                axios.get(url).then(function (response) {
                    var data = response.data;
                    if (data.length > 0) {
                        var ToUserId = $('#ToUserId').val();
                        var currentDis = $('.chat-discussion[data-touser=' + ToUserId + ']');
                        currentDis.find('a.more-msg').hide();
                        var html = '<a class="more-msg"><i class="fa fa-clock-o"></i>查看更多消息</a>';
                        $.each(data, function (index, item) {
                            var headimg = '';
                            var username = '';
                            if (item.Sender == '@user.UserId') {
                                headimg = '@user.HeadImg';
                                username = '@user.UserName';
                                html += '<div class="chat-message chat-right">';
                            } else {
                                headimg = $('.currentUser img').attr('src');
                                username = $('.currentUser span').text();
                                html += '<div class="chat-message chat-left">';
                            }
                            var time = $.unixToDate(item.CreateTime, true);
                            html += '<img class="message-avatar" src="' + headimg + '" alt="">';
                            html += '<div class="message">';
                            html += '<div><a class="message-author">' + username + '</a>';
                            html += '<span class="message-date">' + time + '</span></div>';
                            html += '<span class="message-content">';
                            html += item.Message;
                            html += '</span>';
                            html += '</div>';
                            html += '</div>';
                        });
                        var addpageindex = pageindex == 0 ? 1 : pageindex;
                        if (addpageindex == 1) {
                            currentDis.empty();
                        }
                        currentDis.prepend(html);
                        currentDis.attr('data-pageindex', parseInt(addpageindex) + 1);
                    } else {
                        _this.hide();
                    }
                });
            });
        });
    </script>
}
<div class="wrapper-content">
    <div class="row">
        <div class="ibox">
            <div class="ibox-content">
                <div class="row" style="margin:0px auto;text-align: center;">
                    <div class="chat-main">
                        <div class="chat-main-left">
                            <div class="chat-users">
                                <div class="users-list"></div>
                            </div>
                        </div>
                        <div class="chat-main-right">
                            <div class="currentUser">
                                <img src="/uploadfile/342bd59b-edf4-48cf-aa27-d13e5a0b70df.jpeg" />
                                <span></span>
                                <input type="hidden" id="ToUserId" value="" />
                            </div>
                            <div class="chat-discussion" data-touser="">
                                <h3>
                                    WEB 在线聊天系统
                                </h3>
                            </div>
                            <div class="chat-message-form" style="display:none">
                                <div class="form-group">
                                    <textarea class="form-control message-input" name="message"></textarea>
                                </div>
                                <button class="btn btn-primary" id="sendMessage">发送</button>
                            </div>
                        </div>
                        <div class="clear"></div>
                    </div>
                </div>

                <div class="chatim active">
                    <div class="chatim-title">
                        <img src="@user.HeadImg" />
                        <span class="chatim-title-username">
                            @user.UserName
                        </span>
                        <span class="green">在线</span>
                    </div>
                    <div class="chatim-body">
                        <div class="chatim-userbox chatim-userbox-online">
                            <div class="chatim-userbox-category" data-type="1">
                                <span><i class="fa fa-angle-down"></i></span>在线用户
                            </div>
                            <ul></ul>
                        </div>
                        <div class="chatim-userbox chatim-userbox-notonline">
                            <div class="chatim-userbox-category" data-type="0">
                                <span><i class="fa fa-angle-right"></i></span>未在线用户
                            </div>
                            <ul style="display:none"></ul>
                        </div>
                    </div>

                    <div class="chatim-footer">
                        <a data-type="1"><i class="fa fa-close"></i></a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

 

数据库设计,就一张表

  

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for oa_chat
-- ----------------------------
DROP TABLE IF EXISTS `oa_chat`;
CREATE TABLE `oa_chat`  (
  `Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `Sender` bigint(20) NOT NULL COMMENT '发送方',
  `Message` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '消息',
  `Receiver` bigint(20) NOT NULL COMMENT '接收方',
  `CreateTime` bigint(20) NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`Id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 156 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

  

 

效果如下:

双击在线用户发送并发送信息

用户接收到消息

 

部分代码地址:

https://github.com/wangmaosheng/MsSystem-BPM-ServiceAndWebApps/blob/master/src/Web/MVC/MsSystem.Web/Areas/OA/Views/Chat/Index.cshtml

也可以clone 下项目运行查看效果,docker功能已完成,可直接运行

posted on 2019-08-19 16:41  Jade_K  阅读(3488)  评论(0编辑  收藏  举报

导航