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