后端:
新增好友请求事件和好友已添加事件
This commit is contained in:
+15
-2
@@ -1,13 +1,26 @@
|
||||
using IM_API.Domain.Events;
|
||||
using IM_API.Interface.Services;
|
||||
using MassTransit;
|
||||
|
||||
namespace IM_API.Application.EventHandlers.FriendAddHandler
|
||||
{
|
||||
public class FriendAddConversationHandler : IConsumer<FriendAddEvent>
|
||||
{
|
||||
public Task Consume(ConsumeContext<FriendAddEvent> context)
|
||||
private readonly IFriendSerivce _friendService;
|
||||
public FriendAddConversationHandler(IFriendSerivce friendService)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_friendService = friendService;
|
||||
}
|
||||
|
||||
public async Task Consume(ConsumeContext<FriendAddEvent> context)
|
||||
{
|
||||
var @event = context.Message;
|
||||
//为请求发起人添加好友记录
|
||||
await _friendService.MakeFriendshipAsync(
|
||||
@event.RequestUserId, @event.ResponseUserId, @event.RequestInfo.RemarkName);
|
||||
//为接收人添加好友记录
|
||||
await _friendService.MakeFriendshipAsync(
|
||||
@event.ResponseUserId, @event.RequestUserId, @event.requestUserRemarkname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-10
@@ -1,28 +1,37 @@
|
||||
using IM_API.Domain.Events;
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Hubs;
|
||||
using IM_API.Interface.Services;
|
||||
using IM_API.Models;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace IM_API.Application.EventHandlers.FriendAddHandler
|
||||
{
|
||||
public class FriendAddSignalRHandler : IConsumer<FriendAddEvent>
|
||||
{
|
||||
private readonly IFriendSerivce _friendService;
|
||||
public FriendAddSignalRHandler(IFriendSerivce friendSerivce)
|
||||
private readonly IHubContext<ChatHub> _chathub;
|
||||
public FriendAddSignalRHandler(IHubContext<ChatHub> chathub)
|
||||
{
|
||||
_friendService = friendSerivce;
|
||||
_chathub = chathub;
|
||||
}
|
||||
|
||||
public async Task Consume(ConsumeContext<FriendAddEvent> context)
|
||||
{
|
||||
var @event = context.Message;
|
||||
//为请求发起人添加好友记录
|
||||
await _friendService.MakeFriendshipAsync(
|
||||
@event.RequestUser.Id, @event.ResponseUser.Id, @event.RequestInfo.RemarkName);
|
||||
//为接收人添加好友记录
|
||||
await _friendService.MakeFriendshipAsync(
|
||||
@event.ResponseUser.Id, @event.RequestUser.Id, @event.requestUserRemarkname);
|
||||
|
||||
var usersList = new List<string> {
|
||||
@event.RequestUserId.ToString(), @event.ResponseUserId.ToString()
|
||||
};
|
||||
var res = new HubResponse<MessageBaseDto>("Event", new MessageBaseDto()
|
||||
{
|
||||
ChatType = ChatType.PRIVATE,
|
||||
Content = "您有新的好友关系已添加",
|
||||
MsgId = @event.EventId.ToString(),
|
||||
ReceiverId = @event.ResponseUserId,
|
||||
SenderId = @event.RequestUserId,
|
||||
TimeStamp = DateTime.UtcNow
|
||||
});
|
||||
await _chathub.Clients.Users(usersList).SendAsync("ReceiveMessage", res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -28,13 +28,13 @@ namespace IM_API.Application.EventHandlers.MessageCreatedHandler
|
||||
MessageBaseDto messageBaseDto = new MessageBaseDto
|
||||
{
|
||||
MsgId = @event.MessageId.ToString(),
|
||||
ChatType = @event.ChatType.ToString(),
|
||||
ChatType = @event.ChatType,
|
||||
Content = @event.MessageContent,
|
||||
GroupMemberId = null,
|
||||
ReceiverId = @event.MsgRecipientId,
|
||||
SenderId = @event.MsgSenderId,
|
||||
TimeStamp = @event.MessageCreated,
|
||||
Type = @event.MessageMsgType.ToString()
|
||||
Type = @event.MessageMsgType
|
||||
};
|
||||
await _hub.Clients.Users(@event.MsgRecipientId.ToString()).SendAsync("ReceiveMessage", messageBaseDto);
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using IM_API.Domain.Events;
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Hubs;
|
||||
using IM_API.Interface.Services;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace IM_API.Application.EventHandlers.RequestFriendHandler
|
||||
{
|
||||
public class RequestFriendSignalRHandler:IConsumer<RequestFriendEvent>
|
||||
{
|
||||
private readonly IHubContext<ChatHub> _hub;
|
||||
private readonly IUserService _userService;
|
||||
public RequestFriendSignalRHandler(IHubContext<ChatHub> hubContext, IUserService userService)
|
||||
{
|
||||
_hub = hubContext;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
public async Task Consume(ConsumeContext<RequestFriendEvent> context)
|
||||
{
|
||||
var @event = context.Message;
|
||||
var userInfo = await _userService.GetUserInfoAsync(@event.FromUserId);
|
||||
var res = new HubResponse<FriendRequestResDto>("Event", new FriendRequestResDto()
|
||||
{
|
||||
RequestUser = @event.FromUserId,
|
||||
ResponseUser = @event.ToUserId,
|
||||
Created = DateTime.UtcNow,
|
||||
Description = @event.Description,
|
||||
Avatar = userInfo.Avatar,
|
||||
NickName = userInfo.NickName
|
||||
});
|
||||
await _hub.Clients.User(@event.ToUserId.ToString()).SendAsync("ReceiveMessage", res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,13 @@ namespace IM_API.Configs
|
||||
.ForMember(dest => dest.StateEnum , opt => opt.MapFrom(src => FriendRequestState.Pending))
|
||||
.ForMember(dest => dest.Description , opt => opt.MapFrom(src => src.Description))
|
||||
;
|
||||
|
||||
CreateMap<FriendRequest, FriendRequestDto>()
|
||||
.ForMember(dest => dest.ToUserId, opt => opt.MapFrom(src => src.ResponseUser))
|
||||
.ForMember(dest => dest.FromUserId, opt => opt.MapFrom(src => src.RequestUser))
|
||||
.ForMember(dest => dest.RemarkName, opt => opt.MapFrom(src => src.RemarkName))
|
||||
.ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Description))
|
||||
;
|
||||
//消息模型转换
|
||||
CreateMap<Message, MessageBaseDto>()
|
||||
.ForMember(dest => dest.Type , opt => opt.MapFrom(src => src.MsgTypeEnum.ToString()))
|
||||
@@ -59,8 +66,8 @@ namespace IM_API.Configs
|
||||
;
|
||||
CreateMap<MessageBaseDto, Message>()
|
||||
.ForMember(dest => dest.Sender, opt => opt.MapFrom(src => src.SenderId))
|
||||
.ForMember(dest => dest.ChatTypeEnum,opt => opt.MapFrom(src => Enum.Parse<ChatType>(src.ChatType,true)))
|
||||
.ForMember(dest => dest.MsgTypeEnum, opt => opt.MapFrom(src => Enum.Parse<MessageMsgType>(src.Type,true)))
|
||||
.ForMember(dest => dest.ChatTypeEnum,opt => opt.MapFrom(src => src.ChatType))
|
||||
.ForMember(dest => dest.MsgTypeEnum, opt => opt.MapFrom(src => src.Type))
|
||||
.ForMember(dest => dest.Created, opt => opt.MapFrom(src => src.TimeStamp))
|
||||
.ForMember(dest => dest.Content, opt => opt.MapFrom(src => src.Content))
|
||||
.ForMember(dest => dest.Recipient, opt => opt.MapFrom(src => src.ReceiverId))
|
||||
|
||||
@@ -8,12 +8,12 @@ namespace IM_API.Domain.Events
|
||||
/// <summary>
|
||||
/// 发起请求用户
|
||||
/// </summary>
|
||||
public UserInfoDto RequestUser { get; init; }
|
||||
public int RequestUserId { get; init; }
|
||||
public string? requestUserRemarkname { get; init; }
|
||||
/// <summary>
|
||||
/// 接受请求用户
|
||||
/// </summary>
|
||||
public UserInfoDto ResponseUser { get; init; }
|
||||
public int ResponseUserId { get; init; }
|
||||
|
||||
public FriendRequestDto RequestInfo { get; init; }
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace IM_API.Domain.Events
|
||||
{
|
||||
public record RequestFriendEvent : DomainEvent
|
||||
{
|
||||
public override string EventType => "IM.FRIENDS_FRIEND_REQUEST";
|
||||
public int FromUserId { get; init; }
|
||||
public int ToUserId { get; init; }
|
||||
public string Description { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using IM_API.Tools;
|
||||
|
||||
namespace IM_API.Dtos
|
||||
{
|
||||
public class HubResponse<T>
|
||||
{
|
||||
public int Code { get; init; }
|
||||
public string Method { get; init; }
|
||||
public HubResponseType Type { get; init; }
|
||||
public string Message { get; init; }
|
||||
public T? Data { get; init; }
|
||||
public HubResponse(string method)
|
||||
{
|
||||
Code = CodeDefine.SUCCESS.Code;
|
||||
Message = CodeDefine.SUCCESS.Message;
|
||||
Type = HubResponseType.ActionStatus;
|
||||
}
|
||||
public HubResponse(string method,T data)
|
||||
{
|
||||
Code = CodeDefine.SUCCESS.Code;
|
||||
Message = CodeDefine.SUCCESS.Message;
|
||||
Type = HubResponseType.ActionStatus;
|
||||
Data = data;
|
||||
}
|
||||
public HubResponse(CodeDefine codedefine,string method)
|
||||
{
|
||||
Code = codedefine.Code;
|
||||
Method = method;
|
||||
Message = codedefine.Message;
|
||||
Type = HubResponseType.ActionStatus;
|
||||
}
|
||||
public HubResponse(CodeDefine codeDefine, string method, HubResponseType type, T? data)
|
||||
{
|
||||
Code = codeDefine.Code;
|
||||
Method = method;
|
||||
Type = type;
|
||||
Message = codeDefine.Message;
|
||||
Data = data;
|
||||
}
|
||||
}
|
||||
public enum HubResponseType
|
||||
{
|
||||
ChatMsg = 1, // 聊天内容
|
||||
SystemNotice = 2, // 系统通知(如:申请好友成功)
|
||||
ActionStatus = 3 // 状态变更(如:对方正在输入、已读回执)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
namespace IM_API.Dtos
|
||||
using IM_API.Models;
|
||||
|
||||
namespace IM_API.Dtos
|
||||
{
|
||||
public record MessageBaseDto
|
||||
{
|
||||
// 使用 { get; init; } 确保对象创建后不可修改,且支持无参构造
|
||||
public string Type { get; init; } = default!;
|
||||
public string ChatType { get; init; } = default!;
|
||||
public MessageMsgType Type { get; init; } = default!;
|
||||
public ChatType ChatType { get; init; } = default!;
|
||||
public string? MsgId { get; init; }
|
||||
public int SenderId { get; init; }
|
||||
public int ReceiverId { get; init; }
|
||||
|
||||
@@ -40,17 +40,17 @@ namespace IM_API.Hubs
|
||||
}
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
public async Task SendMessage(MessageBaseDto dto)
|
||||
public async Task<HubResponse<MessageBaseDto?>> SendMessage(MessageBaseDto dto)
|
||||
{
|
||||
if (!Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
await Clients.Caller.SendAsync("ReceiveMessage", new BaseResponse<object?>(CodeDefine.AUTH_FAILED));
|
||||
Context.Abort();
|
||||
return;
|
||||
return new HubResponse<MessageBaseDto?>(CodeDefine.AUTH_FAILED, "SendMessage");
|
||||
}
|
||||
var userIdStr = Context.User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
MessageBaseDto msgInfo = null;
|
||||
if(dto.ChatType.ToLower() == ChatType.PRIVATE.ToString().ToLower())
|
||||
if(dto.ChatType == ChatType.PRIVATE)
|
||||
{
|
||||
msgInfo = await _messageService.SendPrivateMessageAsync(int.Parse(userIdStr), dto.ReceiverId, dto);
|
||||
}
|
||||
@@ -58,19 +58,19 @@ namespace IM_API.Hubs
|
||||
{
|
||||
msgInfo = await _messageService.SendGroupMessageAsync(int.Parse(userIdStr), dto.ReceiverId, dto);
|
||||
}
|
||||
return;
|
||||
return new HubResponse<MessageBaseDto?>("SendMessage", msgInfo);
|
||||
}
|
||||
public async Task ClearUnreadCount(int conversationId)
|
||||
public async Task<HubResponse<object?>> ClearUnreadCount(int conversationId)
|
||||
{
|
||||
if (!Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
await Clients.Caller.SendAsync("ReceiveMessage", new BaseResponse<object?>(CodeDefine.AUTH_FAILED));
|
||||
Context.Abort();
|
||||
return;
|
||||
return new HubResponse<object?>(CodeDefine.AUTH_FAILED, "ClearUnreadCount"); ;
|
||||
}
|
||||
var userIdStr = Context.User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
await _conversationService.ClearUnreadCountAsync(int.Parse(userIdStr), conversationId);
|
||||
return;
|
||||
return new HubResponse<object?>("ClearUnreadCount");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,11 @@ public partial class FriendRequest
|
||||
/// </summary>
|
||||
public sbyte State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string RemarkName { get; set; } = null!;
|
||||
|
||||
public virtual User RequestUserNavigation { get; set; } = null!;
|
||||
|
||||
public virtual User ResponseUserNavigation { get; set; } = null!;
|
||||
|
||||
@@ -281,6 +281,9 @@ public partial class ImContext : DbContext
|
||||
entity.Property(e => e.Description)
|
||||
.HasComment("申请附言 ")
|
||||
.HasColumnType("text");
|
||||
entity.Property(e => e.RemarkName)
|
||||
.HasMaxLength(20)
|
||||
.HasComment("备注");
|
||||
entity.Property(e => e.RequestUser)
|
||||
.HasComment("申请人 ")
|
||||
.HasColumnType("int(11)");
|
||||
|
||||
@@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using StackExchange.Redis;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace IM_API
|
||||
{
|
||||
@@ -38,7 +40,12 @@ namespace IM_API
|
||||
|
||||
builder.Services.AddAllService(configuration);
|
||||
|
||||
builder.Services.AddSignalR();
|
||||
builder.Services.AddSignalR().AddJsonProtocol(options =>
|
||||
{
|
||||
// 枚举输出字符串
|
||||
options.PayloadSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
||||
options.PayloadSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
});
|
||||
//允许所有来源(跨域)
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
@@ -110,6 +117,10 @@ namespace IM_API
|
||||
{
|
||||
// 保持 ISO 8601 格式
|
||||
options.JsonSerializerOptions.Converters.Add(new UtcDateTimeConverter());
|
||||
// 将枚举转换为字符串
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
||||
// 建议:保持驼峰命名
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
});
|
||||
builder.Services.AddModelValidation(configuration);
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using AutoMapper;
|
||||
using IM_API.Domain.Events;
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Exceptions;
|
||||
using IM_API.Interface.Services;
|
||||
using IM_API.Models;
|
||||
using IM_API.Tools;
|
||||
using MassTransit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IM_API.Services
|
||||
@@ -13,11 +15,13 @@ namespace IM_API.Services
|
||||
private readonly ImContext _context;
|
||||
private readonly ILogger<FriendService> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
public FriendService(ImContext context, ILogger<FriendService> logger, IMapper mapper)
|
||||
private readonly IPublishEndpoint _endpoint;
|
||||
public FriendService(ImContext context, ILogger<FriendService> logger, IMapper mapper, IPublishEndpoint endpoint)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
_endpoint = endpoint;
|
||||
}
|
||||
#region 拉黑好友
|
||||
public async Task<bool> BlockeFriendAsync(int friendId)
|
||||
@@ -127,13 +131,18 @@ namespace IM_API.Services
|
||||
|
||||
//同意后标记
|
||||
case HandleFriendRequestAction.Accept:
|
||||
friend.StatusEnum = FriendStatus.Added;
|
||||
friendRequest.StateEnum = FriendRequestState.Passed;
|
||||
await _endpoint.Publish(new FriendAddEvent()
|
||||
{
|
||||
AggregateId = friendRequest.Id.ToString(),
|
||||
OccurredAt = DateTime.UtcNow,
|
||||
Created = DateTime.UtcNow,
|
||||
EventId = Guid.NewGuid(),
|
||||
OperatorId = friendRequest.ResponseUser,
|
||||
RequestInfo = _mapper.Map<FriendRequestDto>(friendRequest),
|
||||
requestUserRemarkname = requestDto.RemarkName,
|
||||
|
||||
//根据当前好友请求为被申请方添加一条好友记录(注意:好友记录为双向)
|
||||
var ResponseFriend = _mapper.Map<Friend>(friendRequest);
|
||||
if (!string.IsNullOrEmpty(requestDto.RemarkName)) ResponseFriend.RemarkName = requestDto.RemarkName;
|
||||
_context.Friends.Add(ResponseFriend);
|
||||
});
|
||||
break;
|
||||
|
||||
//无效操作
|
||||
@@ -172,6 +181,16 @@ namespace IM_API.Services
|
||||
var friendRequst = _mapper.Map<FriendRequest>(dto);
|
||||
_context.FriendRequests.Add(friendRequst);
|
||||
await _context.SaveChangesAsync();
|
||||
await _endpoint.Publish(new RequestFriendEvent()
|
||||
{
|
||||
AggregateId = friendRequst.Id.ToString(),
|
||||
OccurredAt = friendRequst.Created,
|
||||
Description = friendRequst.Description,
|
||||
EventId = Guid.NewGuid(),
|
||||
FromUserId = friendRequst.RequestUser,
|
||||
ToUserId = friendRequst.ResponseUser,
|
||||
OperatorId = friendRequst.RequestUser
|
||||
});
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user