web版聊天功能简单实现
阅读原文时间:2023年07月16日阅读:1

一、问题

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

要完成一个功能我觉得首先要分析该功能的逻辑及技术难点,而不是盲目的直接就撸代码,这样非常浪费时间。个人觉得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 _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{